boomqueries
Advanced tools
Comparing version 0.0.4 to 0.0.6
@@ -1,26 +0,53 @@ | ||
/*! BoomQueries 0.0.4 | http://boomtownroi.github.io/boomqueries/ | (c) 2014 BoomTown | MIT License */ | ||
(function (global, boomQueries) { | ||
if(typeof define === 'function' && define.amd) { | ||
define(['boomQueries'], boomQueries); | ||
} else if (typeof module === 'object' && module.exports) { | ||
module.exports = boomQueries(); | ||
/*! BoomQueries 0.0.6 | http://boomtownroi.github.io/boomqueries/ | (c) 2014 BoomTown | MIT License */ | ||
(function (root, factory) { | ||
if (typeof define === 'function' && define.amd) { | ||
// AMD | ||
define(['boomQueries'], factory); | ||
} else if (typeof exports === 'object') { | ||
// Node, CommonJS-like | ||
module.exports = factory(); | ||
} else { | ||
window.boomQueries = boomQueries(); | ||
// Browser globals (root is window) | ||
root.boomQueries = factory(); | ||
} | ||
}(window, function() { | ||
}(this, function() { | ||
'use strict'; | ||
function boomQuery() { | ||
// Array of dom nodes which update their class when the window resizes | ||
this.nodes = []; | ||
// Array of dom nodes which update their class when the window resizes | ||
var nodes = []; | ||
// Hash of selectors with their corresponding break points | ||
this.map = {}; | ||
// Dispatch our custom event when the window resizes | ||
window.addEventListener('resize', this.debounce(this, this.update, 100), false); | ||
// Hash of selectors with their corresponding break points | ||
var map = {}; | ||
// classList.add() Polyfill | ||
function addClass(el, className) { | ||
if (el.classList) | ||
el.classList.add(className); | ||
else | ||
el.className += ' ' + className; | ||
} | ||
// classList.remove() Polyfill | ||
function removeClass(el, className) { | ||
if (el.classList) | ||
el.classList.remove(className); | ||
else | ||
el.className = el.className.replace(new RegExp('(^|\\b)' + className.split(' ').join('|') + '(\\b|$)', 'gi'), ' '); | ||
} | ||
// Polyfill for CustomEvent | ||
// source: https://developer.mozilla.org/en/docs/Web/API/CustomEvent | ||
var CustomEvent = window.CustomEvent; | ||
if (typeof CustomEvent === "object") { | ||
CustomEvent = function ( event, params ) { | ||
params = params || { bubbles: false, cancelable: false, detail: undefined }; | ||
var evt = document.createEvent( 'CustomEvent' ); | ||
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail ); | ||
return evt; | ||
}; | ||
CustomEvent.prototype = window.Event.prototype; | ||
} | ||
// Rate limit the amount of times our update method gets called on window resize | ||
boomQuery.prototype.debounce = function(context, func, wait, immediate) { | ||
function debounce(context, func, wait, immediate) { | ||
var timeout; | ||
@@ -38,30 +65,30 @@ return function() { | ||
}; | ||
}; | ||
} | ||
// Called whenever we need to ensure all nodes have their proper class | ||
boomQuery.prototype.update = function(options) { | ||
function update(options) { | ||
var details = {}; | ||
// You can pass a custom object to each node when we dispatch the event | ||
if ( typeof options !== 'undefined' ) details["detail"] = options; | ||
var updateEvent = new CustomEvent("checkyourself", details); | ||
// Loop through our nodes firing a "checkyourself" event on each of them | ||
this.nodes.forEach(function(node) { | ||
if ( typeof options !== 'undefined' ) details.detail = options; | ||
var updateEvent = new CustomEvent('checkyourself', details); | ||
// Loop through our nodes firing a 'checkyourself' event on each of them | ||
nodes.forEach(function(node) { | ||
node.dispatchEvent(updateEvent); | ||
}); | ||
}; | ||
} | ||
// Internal function that accepts a DOM node with break points | ||
// Adds custom properties and a listener to the node and then stores the node in an internal array | ||
boomQuery.prototype._add = function(node, breakPoints, selector) { | ||
function _add(node, breakPoints, selector) { | ||
// Check to ensure we aren't already tracking this node | ||
if ( node.breaks === undefined ) { | ||
// Store the break points array in the node | ||
node.breaks = breakPoints; | ||
// If we pass a selector/name, add it to the node so we can reference it later | ||
// If we pass a selector/name, add it to the node so we can reference it later | ||
if ( selector !== null ) node.selector = selector; | ||
// Attach an event listener with functionality to update it's own class | ||
node.addEventListener("checkyourself", function(event) { | ||
node.addEventListener('checkyourself', function(event) { | ||
// event.detail is custom object if we have one | ||
@@ -79,7 +106,7 @@ | ||
} | ||
this.classList.remove(this.breaks[componentBreaksCounter][1]); | ||
removeClass(this, this.breaks[componentBreaksCounter][1]); | ||
} | ||
if ( currentBreak >= 0 ) { | ||
this.classList.add(this.breaks[currentBreak][1]); | ||
addClass(this, this.breaks[currentBreak][1]); | ||
} | ||
@@ -94,3 +121,3 @@ | ||
}; | ||
var completedEvent = new CustomEvent("nodeUpdated", details); | ||
var completedEvent = new CustomEvent('nodeUpdated', details); | ||
@@ -102,6 +129,6 @@ // You can now attach an event listener to this node to catch when we have completed the event | ||
node.addEventListener("cleanup", function(event) { | ||
node.addEventListener('cleanup', function(event) { | ||
var self = this; | ||
this.breaks.forEach(function(br) { | ||
self.classList.remove(br[1]); | ||
classListRemove(self, br[1]); | ||
}); | ||
@@ -111,17 +138,17 @@ }); | ||
// Push the node on to our stack of nodes | ||
this.nodes.push(node); | ||
nodes.push(node); | ||
} | ||
}; | ||
} | ||
// Internal method that accepts a css selector, | ||
boomQuery.prototype._addSelector = function(selector, breakPoints) { | ||
// Internal method that accepts a css selector, | ||
function _addSelector(selector, breakPoints) { | ||
// Add selector to internal map hash for refreshing | ||
this.map[selector] = breakPoints; | ||
map[selector] = breakPoints; | ||
// Loop through nodes adding them internally | ||
var nodes = document.querySelectorAll(selector), self = this; | ||
var nodes = document.querySelectorAll(selector); | ||
Array.prototype.forEach.call(nodes, function(node) { | ||
self._add(node, breakPoints, selector); | ||
_add(node, breakPoints, selector); | ||
}); | ||
}; | ||
} | ||
@@ -132,50 +159,52 @@ // Main method for external use | ||
// Name is an optional parameter that allows you to specify or name a DOM node | ||
boomQuery.prototype.add = function (selector, breakPoints, name) { | ||
function add(selector, breakPoints, name) { | ||
if ( typeof selector === 'string' ) { | ||
this._addSelector(selector, breakPoints); | ||
_addSelector(selector, breakPoints); | ||
} else { | ||
var id = null, self = this; | ||
var id = null; | ||
if ( name !== 'undefined' ) id = name; | ||
if ( selector.constructor === Array ) { | ||
selector.forEach(function(node){ | ||
self._add(node, breakPoints, id); | ||
_add(node, breakPoints, id); | ||
}); | ||
} else { | ||
this._add(selector, breakPoints, id); | ||
_add(selector, breakPoints, id); | ||
} | ||
} | ||
this.update(); | ||
}; | ||
update(); | ||
} | ||
// Call refresh method when new DOM elements have been added | ||
boomQuery.prototype.refresh = function() { | ||
function refresh() { | ||
// First let's remove any nodes which have been removed from DOM | ||
this.remove(); | ||
remove(); | ||
// Now we need to roll through css selectors and requery them to see if there are a new nodes we need to consume | ||
var selectors = Object.keys(this.map), self = this; | ||
var selectors = Object.keys(map); | ||
selectors.forEach(function(selector) { | ||
self._addSelector(selector, self.map[selector]); | ||
_addSelector(selector, map[selector]); | ||
}); | ||
this.update(); | ||
}; | ||
update(); | ||
} | ||
// Internal method to stay DRY | ||
boomQuery.prototype._delete = function(i) { | ||
function _delete(i) { | ||
// Remove event listener before discarding to avoid zombies | ||
this.nodes[i].dispatchEvent(new CustomEvent("cleanup")); | ||
this.nodes[i].removeEventListener("checkyourself"); | ||
this.nodes[i].removeEventListener("cleanup"); | ||
this.nodes.splice(i, 1); | ||
nodes[i].dispatchEvent(new CustomEvent('cleanup')); | ||
nodes[i].removeEventListener('checkyourself'); | ||
nodes[i].removeEventListener('cleanup'); | ||
nodes.splice(i, 1); | ||
return true; | ||
}; | ||
} | ||
// Remove internal nodes based on selector or it's presence in the DOM | ||
boomQuery.prototype.remove = function(selector) { | ||
function remove(selector) { | ||
var i; | ||
// Remove node based on selector or unique name provided | ||
if ( selector !== undefined ) { | ||
for ( var i = this.nodes.length; i--; ) { | ||
if ( this.nodes[i].selector === selector ) { | ||
this._delete(i); | ||
for ( i = nodes.length; i--; ) { | ||
if ( nodes[i].selector === selector ) { | ||
_delete(i); | ||
} | ||
@@ -185,33 +214,47 @@ } | ||
// If we pass an ID of DOM node to delete, it won't be contained in our selector map | ||
if ( this.map.hasOwnProperty(selector) ) delete this.map[selector]; | ||
if ( map.hasOwnProperty(selector) ) delete map[selector]; | ||
// If a selector is not passed, let's remove the node if it is no longer in the DOM | ||
} else { | ||
for ( var i = this.nodes.length; i--; ) { | ||
if ( !document.body.contains(this.nodes[i]) ) { | ||
this._delete(i); | ||
for ( i = nodes.length; i--; ) { | ||
if ( !document.body.contains(nodes[i]) ) { | ||
_delete(i); | ||
} | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
boomQuery.prototype.get = function(selector) { | ||
function get(selector) { | ||
// Loop through internal array of nodes | ||
for ( var i = this.nodes.length; i--; ) { | ||
if ( this.nodes[i].selector === selector ) { | ||
return this.nodes[i]; | ||
for ( var i = nodes.length; i--; ) { | ||
if ( nodes[i].selector === selector ) { | ||
return nodes[i]; | ||
} | ||
} | ||
}; | ||
} | ||
// Just logs the internal array of nodes for debug/inspection | ||
// You can specify which internal store you want to inspect: map or nodes | ||
boomQuery.prototype.inspect = function(which) { | ||
if ( typeof console !== "undefined" ) { | ||
if ( which === 'map' ) console.log(this.map); | ||
else console.log(this.nodes); | ||
function inspect(which) { | ||
if ( typeof console !== 'undefined' ) { | ||
if ( which === 'map' ) console.log(map); | ||
else console.log(nodes); | ||
} | ||
} | ||
// Dispatch our custom event when the window resizes | ||
window.addEventListener('resize', debounce(null, update, 100), false); | ||
return { | ||
// Exposing for tests | ||
nodes: nodes, | ||
map: map, | ||
update: update, | ||
add: add, | ||
refresh: refresh, | ||
remove: remove, | ||
get: get, | ||
inspect: inspect | ||
}; | ||
return new boomQuery(); | ||
})); | ||
})); |
{ | ||
"name": "boomqueries", | ||
"title": "BoomQueries", | ||
"description": "BoomQueries is our take on element-queries; sizing elements based on their container.", | ||
"version": "0.0.4", | ||
"description": "BoomQueries is our take on element queries; sizing elements based on their container.", | ||
"version": "0.0.6", | ||
"keywords": [ | ||
"boomqueries", | ||
"element", | ||
"query", | ||
"resize", | ||
"client" | ||
], | ||
"homepage": "http://boomtownroi.github.io/boomqueries/", | ||
@@ -7,0 +14,0 @@ "author": { |
@@ -19,6 +19,6 @@ # BoomQueries | ||
* Clone the repo, `git clone git://github.com/boomtownroi/boomqueries.git` | ||
* Install with [Bower](http://bower.io): `bower install boomqueries` | ||
* Install with [Bower](http://bower.io): `bower install boomqueries --save` | ||
* Install with [npm](http://npmjs.org): `npm install boomqueries` | ||
Please see tests/kitchensink.html for a thorough example of usage. | ||
[Simple Demo](http://boomtownroi.github.io/boomqueries/) | [Complex Demo](http://boomtownroi.github.io/boomqueries/kitchensink.html) | ||
@@ -50,3 +50,3 @@ ## Initializing/Adding Components | ||
// boomQueries.get('myComponent') you can get your node | ||
// boomQueries.get('myComponent') you can get your node | ||
// boomQueries.remove('myComponent') you can remove your node | ||
@@ -53,0 +53,0 @@ |
15202
220