Browse files

Refactored plugin as Wookmark class. Faster, simpler, more efficient.…

… wookmarkClear is not required anymore to update the layout. The class instance will be kept and used again. Updated readme to show current options and defaults.
  • Loading branch information...
1 parent 0e1c322 commit 60b2ab9c422746f8d5d5123d00e5a660ed0b6889 @Sebobo Sebobo committed Mar 15, 2013
View
3 .gitignore
@@ -2,3 +2,6 @@ node_modules
.project
.DS_Store
+
+/wookmark.jquery.sublime-project
+/wookmark.jquery.sublime-workspace
View
10 README.md
@@ -35,10 +35,12 @@ Where `myElement` is the class of the items you want to lay out in a grid.
### Options
$('.myElements').wookmark({
+ align: 'center',
+ autoResize: false,
container: $('#myContent'),
- offset: 5,
- itemWidth: 200,
- autoResize: true
+ itemWidth: 0,
+ offset: 2,
+ resizeDelay: 50
});
See the [documentation page](http://www.wookmark.com/jquery-plugin) for details on available options.
@@ -72,4 +74,4 @@ Please send me an [email](chri@sto.ph) with any feedback you have or contact me
Contributing
------------
-Contribute!
+Contribute!
View
3 example-api/index.html
@@ -84,9 +84,6 @@
* Refreshes the layout.
*/
function applyLayout() {
- // Clear our previous layout handler.
- if(handler) handler.wookmarkClear();
-
// Create a new layout handler.
handler = $('#tiles li');
handler.wookmark(options);
View
7 example-endless-scroll/index.html
@@ -98,13 +98,10 @@
var closeToBottom = ($(window).scrollTop() + winHeight > $(document).height() - 100);
if(closeToBottom) {
// Get the first then items from the grid, clone them, and add them to the bottom of the grid.
- var items = $('#tiles li');
- var firstTen = items.slice(0, 10);
+ var items = $('#tiles li'),
+ firstTen = items.slice(0, 10);
$('#tiles').append(firstTen.clone());
- // Clear our previous layout handler.
- if(handler) handler.wookmarkClear();
-
// Create a new layout handler.
handler = $('#tiles li');
handler.wookmark(options);
View
6 example-filter/and-filter.html
@@ -113,12 +113,6 @@
// This function filters the grid when a change is made.
var refresh = function() {
- // Clear our previous handler.
- if(handler) {
- handler.wookmarkClear();
- handler = null;
- }
-
// This hides all grid items ("inactive" is a CSS class that sets opacity to 0).
$('#tiles li').addClass('inactive');
View
6 example-filter/index.html
@@ -113,12 +113,6 @@
// This function filters the grid when a change is made.
var refresh = function() {
- // Clear our previous handler.
- if(handler) {
- handler.wookmarkClear();
- handler = null;
- }
-
// This hides all grid items ("inactive" is a CSS class that sets opacity to 0).
$('#tiles li').addClass('inactive');
View
6 example-filter/or-filter.html
@@ -113,12 +113,6 @@
// This function filters the grid when a change is made.
var refresh = function() {
- // Clear our previous handler.
- if(handler) {
- handler.wookmarkClear();
- handler = null;
- }
-
// This hides all grid items ("inactive" is a CSS class that sets opacity to 0).
$('#tiles li').addClass('inactive');
View
246 jquery.wookmark.js
@@ -3,16 +3,24 @@
@name jquery.wookmark.js
@author Christoph Ono (chri@sto.ph or @gbks)
@author Sebastian Helzle (sebastian@helzle.net or @sebobo)
- @version 1.0.4
+ @version 1.1.0
@date 1/27/2013
@category jQuery plugin
@copyright (c) 2009-2013 Christoph Ono (www.wookmark.com)
@license Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/
(function($){
+ var Wookmark, defaultOptions, __bind;
+
+ __bind = function(fn, me) {
+ return function() {
+ return fn.apply(me, arguments);
+ };
+ };
+
// Wookmark default options
- var defaultOptions = {
+ defaultOptions = {
align: 'center',
container: $('body'),
offset: 2,
@@ -21,203 +29,207 @@
resizeDelay: 50
};
- $.fn.wookmark = function(options) {
- // Set options to empty object if undefined
- if (options == null) {
- options = {};
- }
+ Wookmark = (function(options) {
- var $self = $(this[0]);
+ function Wookmark(handler, options) {
+ this.handler = handler;
- function getItemWidth(fixedWidth) {
- if(fixedWidth === undefined) {
- return $self.outerWidth();
- }
- return fixedWidth;
- }
+ // Layout variables.
+ this.columns = null;
+ this.containerWidth = null;
+ this.resizeTimer = null;
- // Create options for each plugin instance
- this.wookmarkOptions = $.extend({}, defaultOptions, options);
+ $.extend(true, this, defaultOptions, options);
- // Layout variables.
- if(!this.wookmarkColumns) {
- this.wookmarkColumns = null;
- this.wookmarkContainerWidth = null;
- }
+ // Bind methods
+ this.update = __bind(this.update, this);
+ this.onResize = __bind(this.onResize, this);
+ this.getItemWidth = __bind(this.getItemWidth, this);
+ this.layout = __bind(this.layout, this);
+ this.layoutFull = __bind(this.layoutFull, this);
+ this.layoutColumns = __bind(this.layoutColumns, this);
+ this.clear = __bind(this.clear, this);
+
+ // Listen to resize event if requested.
+ if (this.autoResize) {
+ $(window).bind('resize.wookmark', this.onResize);
+ this.container.bind('refreshWookmark', this.onResize);
+ };
+ };
+
+ // Method for updating the plugins options
+ Wookmark.prototype.update = function(options) {
+ $.extend(true, this, options);
+ };
+
+ // This timer ensures that layout is not continuously called as window is being dragged.
+ Wookmark.prototype.onResize = function() {
+ clearTimeout(this.resizeTimer);
+ this.resizeTimer = setTimeout(this.layout, this.resizeDelay);
+ };
+
+ // Method to get the standard item width
+ Wookmark.prototype.getItemWidth = function() {
+ return this.itemWidth === undefined ? this.handler.eq(0).outerWidth() : this.itemWidth;
+ };
- // Main layout function.
- this.wookmarkLayout = function() {
+ // Main layout methdd.
+ Wookmark.prototype.layout = function() {
// Do nothing if container isn't visible
- if(!this.wookmarkOptions.container.is(":visible")) {
+ if(!this.container.is(":visible")) {
return;
}
// Calculate basic layout parameters.
- var columnWidth = getItemWidth(this.wookmarkOptions.itemWidth) + this.wookmarkOptions.offset;
- var containerWidth = this.wookmarkOptions.container.width();
- var columns = Math.floor((containerWidth + this.wookmarkOptions.offset) / columnWidth);
- var offset;
+ var columnWidth = this.getItemWidth() + this.offset,
+ containerWidth = this.container.width(),
+ columns = Math.floor((containerWidth + this.offset) / columnWidth),
+ offset = 0,
+ bottom = 0;
// Calculate the offset based on the alignment of columns to the parent container
- switch (this.wookmarkOptions.align) {
+ switch (this.align) {
case 'left':
case 'right':
- offset = Math.floor((columns / columnWidth + this.wookmarkOptions.offset) / 2);
+ offset = Math.floor((columns / columnWidth + this.offset) / 2);
break;
-
case 'center':
default:
- offset = Math.round((containerWidth - (columns * columnWidth - this.wookmarkOptions.offset)) / 2);
+ offset = Math.round((containerWidth - (columns * columnWidth - this.offset)) / 2);
break;
}
// If container and column count hasn't changed, we can only update the columns.
- var bottom = 0;
- if(this.wookmarkColumns != null && this.wookmarkColumns.length == columns) {
- bottom = this.wookmarkLayoutColumns(columnWidth, offset);
+ if(this.columns != null && this.columns.length == columns) {
+ bottom = this.layoutColumns(columnWidth, offset);
} else {
- bottom = this.wookmarkLayoutFull(columnWidth, columns, offset);
+ bottom = this.layoutFull(columnWidth, columns, offset);
}
// Set container height to height of the grid.
- this.wookmarkOptions.container.css('height', bottom + 'px');
+ this.container.css('height', bottom + 'px');
};
/**
* Perform a full layout update.
*/
- this.wookmarkLayoutFull = function(columnWidth, columns, offset) {
+ Wookmark.prototype.layoutFull = function(columnWidth, columns, offset) {
// Prepare Array to store height of columns.
var heights = [];
- while(heights.length < columns) {
+ while (heights.length < columns) {
heights.push(0);
}
// Store column data.
- this.wookmarkColumns = [];
- while(this.wookmarkColumns.length < columns) {
- this.wookmarkColumns.push([]);
+ this.columns = [];
+ while (this.columns.length < columns) {
+ this.columns.push([]);
}
// Loop over items.
- var item, top, left, i=0, k=0, length=this.length, shortest=null, shortestIndex=null, bottom = 0;
- for(; i<length; i++ ) {
- item = $(this[i]);
+ var item, top, left, i = 0, k = 0,
+ length = this.handler.length,
+ shortest = null,
+ shortestIndex = null,
+ bottom = 0,
+ itemCSS = {position: 'absolute'},
+ sideOffset;
+
+ for(; i < length; i++ ) {
+ item = this.handler.eq(i);
// Find the shortest column.
- shortest = null;
+ shortest = heights[0];
shortestIndex = 0;
- for(k=0; k<columns; k++) {
- if(shortest == null || heights[k] < shortest) {
+ for (k = 0; k < columns; k++) {
+ if (heights[k] < shortest) {
shortest = heights[k];
shortestIndex = k;
}
}
// Postion the item.
- item.css({
- position: 'absolute',
- top: shortest+'px'
- });
-
- var sideOffset = (shortestIndex * columnWidth + offset) + 'px';
- if(this.wookmarkOptions.align == 'right') {
- item.css('right', sideOffset);
+ itemCSS.top = shortest + 'px';
+
+ sideOffset = (shortestIndex * columnWidth + offset) + 'px';
+ if (this.align == 'right') {
+ itemCSS.right = sideOffset;
} else {
- item.css('left', sideOffset);
+ itemCSS.left = sideOffset;
}
+ item.css(itemCSS);
// Update column height.
- heights[shortestIndex] = shortest + item.outerHeight() + this.wookmarkOptions.offset;
+ heights[shortestIndex] = shortest + item.outerHeight() + this.offset;
bottom = Math.max(bottom, heights[shortestIndex]);
- this.wookmarkColumns[shortestIndex].push(item);
+ this.columns[shortestIndex].push(item);
}
-
return bottom;
};
/**
- * This layout function only updates the vertical position of the
+ * This layout method only updates the vertical position of the
* existing column assignments.
*/
- this.wookmarkLayoutColumns = function(columnWidth, offset) {
- var heights = [];
- while(heights.length < this.wookmarkColumns.length) {
+ Wookmark.prototype.layoutColumns = function(columnWidth, offset) {
+ var heights = [],
+ length = this.columns.length,
+ i = 0, column, k = 0, kLength, item,
+ bottom = 0, itemCSS, sideOffset;
+
+ while (heights.length < length) {
heights.push(0);
}
- var i=0, length = this.wookmarkColumns.length, column;
- var k=0, kLength, item;
- var bottom = 0;
- for(; i<length; i++) {
- column = this.wookmarkColumns[i];
+ for (; i < length; i++) {
+ column = this.columns[i];
kLength = column.length;
- for(k=0; k<kLength; k++) {
+ for (k = 0; k < kLength; k++) {
item = column[k];
- item.css({
- top: heights[i]+'px'
- });
+ itemCSS = {
+ top: heights[i] + 'px'
+ };
- var sideOffset = (i * columnWidth + offset) + 'px';
- if(this.wookmarkOptions.align == 'right') {
- item.css('right', sideOffset);
+ sideOffset = (i * columnWidth + offset) + 'px';
+ if (this.align == 'right') {
+ itemCSS.right = sideOffset;
} else {
- item.css('left', sideOffset);
+ itemCSS.left = sideOffset;
}
+ item.css(itemCSS);
- heights[i] += item.outerHeight() + this.wookmarkOptions.offset;
-
+ heights[i] += item.outerHeight() + this.offset;
bottom = Math.max(bottom, heights[i]);
}
}
-
return bottom;
};
- // Listen to resize event if requested.
- this.wookmarkResizeTimer = null;
- if(!this.wookmarkResizeMethod) {
- this.wookmarkResizeMethod = null;
- }
- if(this.wookmarkOptions.autoResize) {
- // This timer ensures that layout is not continuously called as window is being dragged.
- this.wookmarkOnResize = function(event) {
- if(this.wookmarkResizeTimer) {
- clearTimeout(this.wookmarkResizeTimer);
- }
- this.wookmarkResizeTimer = setTimeout($.proxy(this.wookmarkLayout, this), this.wookmarkOptions.resizeDelay)
- };
-
- // Bind event listener.
- if(!this.wookmarkResizeMethod) {
- this.wookmarkResizeMethod = $.proxy(this.wookmarkOnResize, this);
- }
- $(window).resize(this.wookmarkResizeMethod);
- this.wookmarkOptions.container.bind('refreshWookmark',this.wookmarkResizeMethod);
- };
-
/**
* Clear event listeners and time outs.
*/
- this.wookmarkClear = function() {
- if(this.wookmarkResizeTimer) {
- clearTimeout(this.wookmarkResizeTimer);
- this.wookmarkResizeTimer = null;
- }
- if(this.wookmarkResizeMethod) {
- $(window).unbind('resize', this.wookmarkResizeMethod);
- this.wookmarkOptions.container.unbind('refreshWookmark',this.wookmarkResizeMethod);
- }
+ Wookmark.prototype.clear = function() {
+ clearTimeout(this.resizeTimer);
+ $(window).unbind('resize.wookmark', this.onResize);
+ this.container.unbind('refreshWookmark', this.onResize);
};
- // Apply layout
- this.wookmarkLayout();
+ return Wookmark;
+ })();
- // Display items (if hidden).
- this.show();
+ $.fn.wookmark = function(options) {
+ // Create a wookmark instance if not available
+ if (!this.wookmarkInstance) {
+ this.wookmarkInstance = new Wookmark(this, options || {});
+ } else {
+ this.wookmarkInstance.update(options || {});
+ }
+
+ // Apply layout
+ this.wookmarkInstance.layout();
- // Maintain chainability
- return this;
+ // Display items (if hidden) and return jQuery object to maintain chainability
+ return this.show();
};
})(jQuery);
View
6 jquery.wookmark.min.js
@@ -3,10 +3,10 @@ jQuery wookmark plugin
@name jquery.wookmark.js
@author Christoph Ono (chri@sto.ph or @gbks)
@author Sebastian Helzle (sebastian@helzle.net or @sebobo)
-@version 1.0.4
-@date 03/12/2013
+@version 1.1.0
+@date 03/15/2013
@category jQuery plugin
@copyright (c) 2009-2013 Christoph Ono (www.wookmark.com)
@license Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
*/
-(function(o){var t={align:"center",container:o("body"),offset:2,autoResize:!1,itemWidth:0,resizeDelay:50};o.fn.wookmark=function(i){function s(o){return void 0===o?e.outerWidth():o}null==i&&(i={});var e=o(this[0]);return this.wookmarkOptions=o.extend({},t,i),this.wookmarkColumns||(this.wookmarkColumns=null,this.wookmarkContainerWidth=null),this.wookmarkLayout=function(){if(this.wookmarkOptions.container.is(":visible")){var o,t=s(this.wookmarkOptions.itemWidth)+this.wookmarkOptions.offset,i=this.wookmarkOptions.container.width(),e=Math.floor((i+this.wookmarkOptions.offset)/t);switch(this.wookmarkOptions.align){case"left":case"right":o=Math.floor((e/t+this.wookmarkOptions.offset)/2);break;case"center":default:o=Math.round((i-(e*t-this.wookmarkOptions.offset))/2)}var r=0;r=null!=this.wookmarkColumns&&this.wookmarkColumns.length==e?this.wookmarkLayoutColumns(t,o):this.wookmarkLayoutFull(t,e,o),this.wookmarkOptions.container.css("height",r+"px")}},this.wookmarkLayoutFull=function(t,i,s){for(var e=[];i>e.length;)e.push(0);for(this.wookmarkColumns=[];i>this.wookmarkColumns.length;)this.wookmarkColumns.push([]);for(var r,k=0,a=0,h=this.length,n=null,m=null,l=0;h>k;k++){for(r=o(this[k]),n=null,m=0,a=0;i>a;a++)(null==n||n>e[a])&&(n=e[a],m=a);r.css({position:"absolute",top:n+"px"});var w=m*t+s+"px";"right"==this.wookmarkOptions.align?r.css("right",w):r.css("left",w),e[m]=n+r.outerHeight()+this.wookmarkOptions.offset,l=Math.max(l,e[m]),this.wookmarkColumns[m].push(r)}return l},this.wookmarkLayoutColumns=function(o,t){for(var i=[];i.length<this.wookmarkColumns.length;)i.push(0);for(var s,e,r,k=0,a=this.wookmarkColumns.length,h=0,n=0;a>k;k++)for(s=this.wookmarkColumns[k],e=s.length,h=0;e>h;h++){r=s[h],r.css({top:i[k]+"px"});var m=k*o+t+"px";"right"==this.wookmarkOptions.align?r.css("right",m):r.css("left",m),i[k]+=r.outerHeight()+this.wookmarkOptions.offset,n=Math.max(n,i[k])}return n},this.wookmarkResizeTimer=null,this.wookmarkResizeMethod||(this.wookmarkResizeMethod=null),this.wookmarkOptions.autoResize&&(this.wookmarkOnResize=function(){this.wookmarkResizeTimer&&clearTimeout(this.wookmarkResizeTimer),this.wookmarkResizeTimer=setTimeout(o.proxy(this.wookmarkLayout,this),this.wookmarkOptions.resizeDelay)},this.wookmarkResizeMethod||(this.wookmarkResizeMethod=o.proxy(this.wookmarkOnResize,this)),o(window).resize(this.wookmarkResizeMethod),this.wookmarkOptions.container.bind("refreshWookmark",this.wookmarkResizeMethod)),this.wookmarkClear=function(){this.wookmarkResizeTimer&&(clearTimeout(this.wookmarkResizeTimer),this.wookmarkResizeTimer=null),this.wookmarkResizeMethod&&(o(window).unbind("resize",this.wookmarkResizeMethod),this.wookmarkOptions.container.unbind("refreshWookmark",this.wookmarkResizeMethod))},this.wookmarkLayout(),this.show(),this}})(jQuery);
+(function(t){var i,e,s;s=function(t,i){return function(){return t.apply(i,arguments)}},e={align:"center",container:t("body"),offset:2,autoResize:!1,itemWidth:0,resizeDelay:50},i=function(){function i(i,o){this.handler=i,this.columns=null,this.containerWidth=null,this.resizeTimer=null,t.extend(!0,this,e,o),this.update=s(this.update,this),this.onResize=s(this.onResize,this),this.getItemWidth=s(this.getItemWidth,this),this.layout=s(this.layout,this),this.layoutFull=s(this.layoutFull,this),this.layoutColumns=s(this.layoutColumns,this),this.clear=s(this.clear,this),this.autoResize&&(t(window).bind("resize.wookmark",this.onResize),this.container.bind("refreshWookmark",this.onResize))}return i.prototype.update=function(i){t.extend(!0,this,i)},i.prototype.onResize=function(){clearTimeout(this.resizeTimer),this.resizeTimer=setTimeout(this.layout,this.resizeDelay)},i.prototype.getItemWidth=function(){return void 0===this.itemWidth?this.handler.eq(0).outerWidth():this.itemWidth},i.prototype.layout=function(){if(this.container.is(":visible")){var t=this.getItemWidth()+this.offset,i=this.container.width(),e=Math.floor((i+this.offset)/t),s=0,o=0;switch(this.align){case"left":case"right":s=Math.floor((e/t+this.offset)/2);break;case"center":default:s=Math.round((i-(e*t-this.offset))/2)}o=null!=this.columns&&this.columns.length==e?this.layoutColumns(t,s):this.layoutFull(t,e,s),this.container.css("height",o+"px")}},i.prototype.layoutFull=function(t,i,e){for(var s=[];i>s.length;)s.push(0);for(this.columns=[];i>this.columns.length;)this.columns.push([]);for(var o,h,n=0,r=0,u=this.handler.length,l=null,a=null,c=0,f={position:"absolute"};u>n;n++){for(o=this.handler.eq(n),l=s[0],a=0,r=0;i>r;r++)l>s[r]&&(l=s[r],a=r);f.top=l+"px",h=a*t+e+"px","right"==this.align?f.right=h:f.left=h,o.css(f),s[a]=l+o.outerHeight()+this.offset,c=Math.max(c,s[a]),this.columns[a].push(o)}return c},i.prototype.layoutColumns=function(t,i){for(var e,s,o,h,n,r=[],u=this.columns.length,l=0,a=0,c=0;u>r.length;)r.push(0);for(;u>l;l++)for(e=this.columns[l],s=e.length,a=0;s>a;a++)o=e[a],h={top:r[l]+"px"},n=l*t+i+"px","right"==this.align?h.right=n:h.left=n,o.css(h),r[l]+=o.outerHeight()+this.offset,c=Math.max(c,r[l]);return c},i.prototype.clear=function(){clearTimeout(this.resizeTimer),t(window).unbind("resize.wookmark",this.onResize),this.container.unbind("refreshWookmark",this.onResize)},i}(),t.fn.wookmark=function(t){return this.wookmarkInstance?this.wookmarkInstance.update(t||{}):this.wookmarkInstance=new i(this,t||{}),this.wookmarkInstance.layout(),this.show()}})(jQuery);
View
2 wookmark.jquery.json
@@ -6,7 +6,7 @@
"ui",
"layout"
],
- "version": "1.0.4",
+ "version": "1.1.0",
"author": {
"name": "Christoph Ono",
"url": "http://germanysbestkeptsecret.com"

0 comments on commit 60b2ab9

Please sign in to comment.