flexlayout-rails 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,169 @@
1
+ /*!
2
+ jQuery Wookmark plugin 0.5
3
+ @name jquery.wookmark.js
4
+ @author Christoph Ono (chri@sto.ph or @gbks)
5
+ @version 0.5
6
+ @date 3/19/2012
7
+ @category jQuery plugin
8
+ @copyright (c) 2009-2012 Christoph Ono (www.wookmark.com)
9
+ @license Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
10
+ */
11
+ $.fn.wookmark = function(options) {
12
+
13
+ if(!this.wookmarkOptions) {
14
+ this.wookmarkOptions = $.extend( {
15
+ container: $('body'),
16
+ offset: 2,
17
+ autoResize: false,
18
+ itemWidth: $(this[0]).outerWidth(),
19
+ resizeDelay: 50
20
+ }, options);
21
+ } else if(options) {
22
+ this.wookmarkOptions = $.extend(this.wookmarkOptions, options);
23
+ }
24
+
25
+ // Layout variables.
26
+ if(!this.wookmarkColumns) {
27
+ this.wookmarkColumns = null;
28
+ this.wookmarkContainerWidth = null;
29
+ }
30
+
31
+ // Main layout function.
32
+ this.wookmarkLayout = function() {
33
+ // Calculate basic layout parameters.
34
+ var columnWidth = this.wookmarkOptions.itemWidth + this.wookmarkOptions.offset;
35
+ var containerWidth = this.wookmarkOptions.container.width();
36
+ var columns = Math.floor((containerWidth+this.wookmarkOptions.offset)/columnWidth);
37
+ var offset = Math.round((containerWidth - (columns*columnWidth-this.wookmarkOptions.offset))/2);
38
+
39
+ // If container and column count hasn't changed, we can only update the columns.
40
+ var bottom = 0;
41
+ if(this.wookmarkColumns != null && this.wookmarkColumns.length == columns) {
42
+ bottom = this.wookmarkLayoutColumns(columnWidth, offset);
43
+ } else {
44
+ bottom = this.wookmarkLayoutFull(columnWidth, columns, offset);
45
+ }
46
+
47
+ // Set container height to height of the grid.
48
+ this.wookmarkOptions.container.css('height', bottom+'px');
49
+ };
50
+
51
+ /**
52
+ * Perform a full layout update.
53
+ */
54
+ this.wookmarkLayoutFull = function(columnWidth, columns, offset) {
55
+ // Prepare Array to store height of columns.
56
+ var heights = [];
57
+ while(heights.length < columns) {
58
+ heights.push(0);
59
+ }
60
+
61
+ // Store column data.
62
+ this.wookmarkColumns = [];
63
+ while(this.wookmarkColumns.length < columns) {
64
+ this.wookmarkColumns.push([]);
65
+ }
66
+
67
+ // Loop over items.
68
+ var item, top, left, i=0, k=0, length=this.length, shortest=null, shortestIndex=null, bottom = 0;
69
+ for(; i<length; i++ ) {
70
+ item = $(this[i]);
71
+
72
+ // Find the shortest column.
73
+ shortest = null;
74
+ shortestIndex = 0;
75
+ for(k=0; k<columns; k++) {
76
+ if(shortest == null || heights[k] < shortest) {
77
+ shortest = heights[k];
78
+ shortestIndex = k;
79
+ }
80
+ }
81
+
82
+ // Postion the item.
83
+ item.css({
84
+ position: 'absolute',
85
+ top: shortest+'px',
86
+ left: (shortestIndex*columnWidth + offset)+'px'
87
+ });
88
+
89
+ // Update column height.
90
+ heights[shortestIndex] = shortest + item.outerHeight() + this.wookmarkOptions.offset;
91
+ bottom = Math.max(bottom, heights[shortestIndex]);
92
+
93
+ this.wookmarkColumns[shortestIndex].push(item);
94
+ }
95
+
96
+ return bottom;
97
+ };
98
+
99
+ /**
100
+ * This layout function only updates the vertical position of the
101
+ * existing column assignments.
102
+ */
103
+ this.wookmarkLayoutColumns = function(columnWidth, offset) {
104
+ var heights = [];
105
+ while(heights.length < this.wookmarkColumns.length) {
106
+ heights.push(0);
107
+ }
108
+
109
+ var i=0, length = this.wookmarkColumns.length, column;
110
+ var k=0, kLength, item;
111
+ var bottom = 0;
112
+ for(; i<length; i++) {
113
+ column = this.wookmarkColumns[i];
114
+ kLength = column.length;
115
+ for(k=0; k<kLength; k++) {
116
+ item = column[k];
117
+ item.css({
118
+ left: (i*columnWidth + offset)+'px',
119
+ top: heights[i]+'px'
120
+ });
121
+ heights[i] += item.outerHeight() + this.wookmarkOptions.offset;
122
+
123
+ bottom = Math.max(bottom, heights[i]);
124
+ }
125
+ }
126
+
127
+ return bottom;
128
+ };
129
+
130
+ // Listen to resize event if requested.
131
+ this.wookmarkResizeTimer = null;
132
+ if(!this.wookmarkResizeMethod) {
133
+ this.wookmarkResizeMethod = null;
134
+ }
135
+ if(this.wookmarkOptions.autoResize) {
136
+ // This timer ensures that layout is not continuously called as window is being dragged.
137
+ this.wookmarkOnResize = function(event) {
138
+ if(this.wookmarkResizeTimer) {
139
+ clearTimeout(this.wookmarkResizeTimer);
140
+ }
141
+ this.wookmarkResizeTimer = setTimeout($.proxy(this.wookmarkLayout, this), this.wookmarkOptions.resizeDelay)
142
+ };
143
+
144
+ // Bind event listener.
145
+ if(!this.wookmarkResizeMethod) {
146
+ this.wookmarkResizeMethod = $.proxy(this.wookmarkOnResize, this);
147
+ }
148
+ $(window).resize(this.wookmarkResizeMethod);
149
+ };
150
+
151
+ /**
152
+ * Clear event listeners and time outs.
153
+ */
154
+ this.wookmarkClear = function() {
155
+ if(this.wookmarkResizeTimer) {
156
+ clearTimeout(this.wookmarkResizeTimer);
157
+ this.wookmarkResizeTimer = null;
158
+ }
159
+ if(this.wookmarkResizeMethod) {
160
+ $(window).unbind('resize', this.wookmarkResizeMethod);
161
+ }
162
+ };
163
+
164
+ // Apply layout
165
+ this.wookmarkLayout();
166
+
167
+ // Display items (if hidden).
168
+ this.show();
169
+ };
@@ -0,0 +1,11 @@
1
+ /*!
2
+ jQuery Wookmark plugin 0.5
3
+ @name jquery.wookmark.js
4
+ @author Christoph Ono (chri@sto.ph or @gbks)
5
+ @version 0.5
6
+ @date 3/19/2012
7
+ @category jQuery plugin
8
+ @copyright (c) 2009-2012 Christoph Ono (www.wookmark.com)
9
+ @license Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) license.
10
+ */
11
+ $.fn.wookmark=function(a){if(!this.wookmarkOptions){this.wookmarkOptions=$.extend({container:$("body"),offset:2,autoResize:false,itemWidth:$(this[0]).outerWidth(),resizeDelay:50},a)}else if(a){this.wookmarkOptions=$.extend(this.wookmarkOptions,a)}if(!this.wookmarkColumns){this.wookmarkColumns=null;this.wookmarkContainerWidth=null}this.wookmarkLayout=function(){var a=this.wookmarkOptions.itemWidth+this.wookmarkOptions.offset;var b=this.wookmarkOptions.container.width();var c=Math.floor((b+this.wookmarkOptions.offset)/a);var d=Math.round((b-(c*a-this.wookmarkOptions.offset))/2);var e=0;if(this.wookmarkColumns!=null&&this.wookmarkColumns.length==c){e=this.wookmarkLayoutColumns(a,d)}else{e=this.wookmarkLayoutFull(a,c,d)}this.wookmarkOptions.container.css("height",e+"px")};this.wookmarkLayoutFull=function(a,b,c){var d=[];while(d.length<b){d.push(0)}this.wookmarkColumns=[];while(this.wookmarkColumns.length<b){this.wookmarkColumns.push([])}var e,f,g,h=0,i=0,j=this.length,k=null,l=null,m=0;for(;h<j;h++){e=$(this[h]);k=null;l=0;for(i=0;i<b;i++){if(k==null||d[i]<k){k=d[i];l=i}}e.css({position:"absolute",top:k+"px",left:l*a+c+"px"});d[l]=k+e.outerHeight()+this.wookmarkOptions.offset;m=Math.max(m,d[l]);this.wookmarkColumns[l].push(e)}return m};this.wookmarkLayoutColumns=function(a,b){var c=[];while(c.length<this.wookmarkColumns.length){c.push(0)}var d=0,e=this.wookmarkColumns.length,f;var g=0,h,i;var j=0;for(;d<e;d++){f=this.wookmarkColumns[d];h=f.length;for(g=0;g<h;g++){i=f[g];i.css({left:d*a+b+"px",top:c[d]+"px"});c[d]+=i.outerHeight()+this.wookmarkOptions.offset;j=Math.max(j,c[d])}}return j};this.wookmarkResizeTimer=null;if(!this.wookmarkResizeMethod){this.wookmarkResizeMethod=null}if(this.wookmarkOptions.autoResize){this.wookmarkOnResize=function(a){if(this.wookmarkResizeTimer){clearTimeout(this.wookmarkResizeTimer)}this.wookmarkResizeTimer=setTimeout($.proxy(this.wookmarkLayout,this),this.wookmarkOptions.resizeDelay)};if(!this.wookmarkResizeMethod){this.wookmarkResizeMethod=$.proxy(this.wookmarkOnResize,this)}$(window).resize(this.wookmarkResizeMethod)}this.wookmarkClear=function(){if(this.wookmarkResizeTimer){clearTimeout(this.wookmarkResizeTimer);this.wookmarkResizeTimer=null}if(this.wookmarkResizeMethod){$(window).unbind("resize",this.wookmarkResizeMethod)}};this.wookmarkLayout();this.show()}
@@ -0,0 +1,403 @@
1
+ /*
2
+ Name: MultiColumn
3
+ Version: 0.0.2 (April 23 2010)
4
+ Author: Finn Rudolph
5
+ Company: http://stadtwerk.org/
6
+
7
+ License: This script is licensed under a Creative Commons
8
+ Attribution-Noncommercial 3.0 Unported License
9
+ (http://creativecommons.org/licenses/by-nc/3.0/).
10
+
11
+ You are free:
12
+ + to Share - to copy, distribute and transmit the work
13
+ + to Remix - to adapt the work
14
+
15
+ Under the following conditions:
16
+ + Attribution. You must attribute the work in the manner specified by the author or licensor
17
+ (but not in any way that suggests that they endorse you or your use of the work).
18
+ + Noncommercial. You may not use this work for commercial purposes.
19
+
20
+ + For any reuse or distribution, you must make clear to others the license terms of this work.
21
+ + Any of the above conditions can be waived if you get permission from the copyright holder.
22
+ + Nothing in this license impairs or restricts the author's moral rights.
23
+
24
+ Credits: This script uses the domReadyEvent from Tanny O'Haley [1].
25
+
26
+ [1] http://tanny.ica.com/ICA/TKO/tkoblog.nsf/dx/domcontentloaded-for-browsers-part-v
27
+ */
28
+
29
+ /* MultiColumn constructor */
30
+ function MultiColumn()
31
+ {
32
+ /* Setting option defaults */
33
+ this.defaults =
34
+ {
35
+ className: 'multi-column', /* CSS class name for the element that contains multiple columns */
36
+ columnName: 'column', /* CSS class name for the column element */
37
+ columnCount: 3, /* column-count */
38
+ columnGap: 30 /* column-gap */
39
+ };
40
+
41
+ /* Closure for this */
42
+ var my = this;
43
+
44
+ /* Initiate MultiColumn */
45
+ this.init = function (options)
46
+ {
47
+ /* Evaluate options */
48
+ for(var name in my.defaults)
49
+ {
50
+ this[name] = (options !== undefined && options[name] !== undefined) ? options[name] : my.defaults[name];
51
+ }
52
+
53
+ my.refresh();
54
+ my.Resize.init();
55
+ };
56
+
57
+ /* Refresh multiple columns */
58
+ this.refresh = function()
59
+ {
60
+ /* Get all elements that contain multiple columns */
61
+ var multiColumnElements = my.Tool.getElementsByClass(my.className, '*', document);
62
+ var max = multiColumnElements.length;
63
+ for(var i=0;i<max;i++)
64
+ {
65
+ /* Build multiple columns for each element */
66
+ my.build(multiColumnElements[i]);
67
+ }
68
+ };
69
+
70
+ /* Build multiple columns */
71
+ this.build = function(element)
72
+ {
73
+ /* Calculate column width in px */
74
+ var totalGapWidth = my.columnGap * (my.columnCount -1);
75
+ var totalWidth = parseInt(element.offsetWidth,10);
76
+ var columnWidth = Math.round((totalWidth - totalGapWidth) / my.columnCount);
77
+ var subPixel = (totalWidth-totalGapWidth)-(columnWidth*3);
78
+
79
+ /* Get or create columns element */
80
+ var columnsDiv = my.Tool.getElementsByClass('result', 'div', element);
81
+
82
+ if(columnsDiv != '')
83
+ {
84
+ element.removeChild(columnsDiv[0]);
85
+ }
86
+
87
+ columnsDiv = document.createElement('div');
88
+ my.Tool.setClassName(columnsDiv, 'result');
89
+ columnsDiv.style.width = totalWidth+'px';
90
+
91
+ var columns = my.getColumnElements(element);
92
+ var max = columns.length;
93
+ var gap = my.columnGap / 2;
94
+ var columnDiv;
95
+ for(var i=0;i<max;i++)
96
+ {
97
+ column = columns[i];
98
+
99
+ /* Create element */
100
+ columnDiv = document.createElement('div');
101
+ my.Tool.setClassName(columnDiv, my.columnName);
102
+ columnsDiv.appendChild(columnDiv);
103
+
104
+ /* Set width and padding */
105
+ columnDiv.style.width = columnWidth + 'px';
106
+ if(i === 0)
107
+ {
108
+ columnDiv.style.paddingRight = (gap + subPixel) + 'px';
109
+ }
110
+ else if(i+1 === max)
111
+ {
112
+ columnDiv.style.paddingLeft = gap + 'px';
113
+ }
114
+ else
115
+ {
116
+ columnDiv.style.padding = '0 '+gap+'px 0 '+gap+'px';
117
+ }
118
+
119
+ for(node in column)
120
+ {
121
+ columnDiv.appendChild(column[node].cloneNode(true));
122
+ }
123
+ }
124
+ element.appendChild(columnsDiv);
125
+ };
126
+
127
+
128
+ /* Get column elements */
129
+ this.getColumnElements = function(element)
130
+ {
131
+ /* Calculate max column height */
132
+ var totalHeight = parseInt(element.offsetHeight,10);
133
+ var maxColumnHeigth = totalHeight / my.columnCount;
134
+
135
+ /* Walk through all child nodes and get their height */
136
+ var children = element.childNodes;
137
+ var column = [], columnChilds = [], child, columnHeight = 0;
138
+ var max = children.length;
139
+ for(var i=0;i<max;i++)
140
+ {
141
+ child = children[i];
142
+
143
+ /* Only process element nodes */
144
+ if(child && child.nodeType === 1)
145
+ {
146
+ /* Calculate rendered height of the child element */
147
+ child.renderedHeight = child.offsetHeight;
148
+
149
+ /* Store column childs in an array */
150
+ columnChilds.push(child);
151
+ columnHeight += child.renderedHeight;
152
+
153
+ /* The end of a column has been reached if the elements hit the max column height */
154
+ if(columnHeight >= maxColumnHeigth)
155
+ {
156
+ column.push(columnChilds);
157
+
158
+ /* Reset column height and childs */
159
+ columnHeight = 0;
160
+ columnChilds = [];
161
+ }
162
+ }
163
+ }
164
+ column.push(columnChilds);
165
+
166
+ /* Return column array that holds the column elements */
167
+ return column;
168
+ };
169
+
170
+ /* Resize functions */
171
+ this.Resize =
172
+ {
173
+ init: function()
174
+ {
175
+ my.refresh();
176
+ var otherFunctions = window.onresize;
177
+ if(typeof window.onresize != 'function')
178
+ {
179
+ window.onresize = function()
180
+ {
181
+ my.refresh();
182
+ };
183
+ }
184
+ else
185
+ {
186
+ window.onresize = function()
187
+ {
188
+ if (otherFunctions)
189
+ {
190
+ otherFunctions();
191
+ }
192
+ my.refresh();
193
+ };
194
+ }
195
+ }
196
+ };
197
+
198
+
199
+ /* Helper functions */
200
+ this.Tool =
201
+ {
202
+ setClassName: function(element, className)
203
+ {
204
+ if(element)
205
+ {
206
+ element.setAttribute('class', className);
207
+ element.setAttribute('className', className);
208
+ }
209
+ },
210
+
211
+
212
+ getElementsByClass: function(searchClass, tag, node)
213
+ {
214
+ var classElements = [];
215
+ var elements = node.getElementsByTagName(tag);
216
+ var max = elements.length;
217
+ var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
218
+ for(var i = 0, j = 0; i < max; i++)
219
+ {
220
+ if(pattern.test(elements[i].className))
221
+ {
222
+ classElements[j] = elements[i];
223
+ j++;
224
+ }
225
+ }
226
+ return classElements;
227
+ }
228
+ };
229
+ }
230
+
231
+ /* DOMContentLoaded event handler - by Tanny O'Haley [1] */
232
+ var domReadyEvent =
233
+ {
234
+ name: "domReadyEvent",
235
+ /* Array of DOMContentLoaded event handlers.*/
236
+ events: {},
237
+ domReadyID: 1,
238
+ bDone: false,
239
+ DOMContentLoadedCustom: null,
240
+
241
+ /* Function that adds DOMContentLoaded listeners to the array.*/
242
+ add: function(handler)
243
+ {
244
+ /* Assign each event handler a unique ID. If the handler has an ID, it has already been added to the events object or been run.*/
245
+ if (!handler.$$domReadyID)
246
+ {
247
+ handler.$$domReadyID = this.domReadyID++;
248
+
249
+ /* If the DOMContentLoaded event has happened, run the function. */
250
+ if(this.bDone)
251
+ {
252
+ handler();
253
+ }
254
+
255
+ /* store the event handler in the hash table */
256
+ this.events[handler.$$domReadyID] = handler;
257
+ }
258
+ },
259
+
260
+ remove: function(handler)
261
+ {
262
+ /* Delete the event handler from the hash table */
263
+ if (handler.$$domReadyID)
264
+ {
265
+ delete this.events[handler.$$domReadyID];
266
+ }
267
+ },
268
+
269
+ /* Function to process the DOMContentLoaded events array. */
270
+ run: function()
271
+ {
272
+ /* quit if this function has already been called */
273
+ if (this.bDone)
274
+ {
275
+ return;
276
+ }
277
+
278
+ /* Flag this function so we don't do the same thing twice */
279
+ this.bDone = true;
280
+
281
+ /* iterates through array of registered functions */
282
+ for (var i in this.events)
283
+ {
284
+ this.events[i]();
285
+ }
286
+ },
287
+
288
+ schedule: function()
289
+ {
290
+ /* Quit if the init function has already been called*/
291
+ if (this.bDone)
292
+ {
293
+ return;
294
+ }
295
+
296
+ /* First, check for Safari or KHTML.*/
297
+ if(/KHTML|WebKit/i.test(navigator.userAgent))
298
+ {
299
+ if(/loaded|complete/.test(document.readyState))
300
+ {
301
+ this.run();
302
+ }
303
+ else
304
+ {
305
+ /* Not ready yet, wait a little more.*/
306
+ setTimeout(this.name + ".schedule()", 100);
307
+ }
308
+ }
309
+ else if(document.getElementById("__ie_onload"))
310
+ {
311
+ /* Second, check for IE.*/
312
+ return true;
313
+ }
314
+
315
+ /* Check for custom developer provided function.*/
316
+ if(typeof this.DOMContentLoadedCustom === "function")
317
+ {
318
+ /* if DOM methods are supported, and the body element exists (using a double-check
319
+ including document.body, for the benefit of older moz builds [eg ns7.1] in which
320
+ getElementsByTagName('body')[0] is undefined, unless this script is in the body section) */
321
+ if(typeof document.getElementsByTagName !== 'undefined' && (document.getElementsByTagName('body')[0] !== null || document.body !== null))
322
+ {
323
+ /* Call custom function. */
324
+ if(this.DOMContentLoadedCustom())
325
+ {
326
+ this.run();
327
+ }
328
+ else
329
+ {
330
+ /* Not ready yet, wait a little more. */
331
+ setTimeout(this.name + ".schedule()", 250);
332
+ }
333
+ }
334
+ }
335
+ return true;
336
+ },
337
+
338
+ init: function()
339
+ {
340
+ /* If addEventListener supports the DOMContentLoaded event.*/
341
+ if(document.addEventListener)
342
+ {
343
+ document.addEventListener("DOMContentLoaded", function() { domReadyEvent.run(); }, false);
344
+ }
345
+
346
+ /* Schedule to run the init function.*/
347
+ setTimeout("domReadyEvent.schedule()", 100);
348
+
349
+ function run()
350
+ {
351
+ domReadyEvent.run();
352
+ }
353
+
354
+ /* Just in case window.onload happens first, add it to onload using an available method.*/
355
+ if(typeof addEvent !== "undefined")
356
+ {
357
+ addEvent(window, "load", run);
358
+ }
359
+ else if(document.addEventListener)
360
+ {
361
+ document.addEventListener("load", run, false);
362
+ }
363
+ else if(typeof window.onload === "function")
364
+ {
365
+ var oldonload = window.onload;
366
+ window.onload = function()
367
+ {
368
+ domReadyEvent.run();
369
+ oldonload();
370
+ };
371
+ }
372
+ else
373
+ {
374
+ window.onload = run;
375
+ }
376
+
377
+ /* for Internet Explorer */
378
+ /*@cc_on
379
+ @if (@_win32 || @_win64)
380
+ document.write("<script id=__ie_onload defer src=\"//:\"><\/script>");
381
+ var script = document.getElementById("__ie_onload");
382
+ script.onreadystatechange = function()
383
+ {
384
+ if (this.readyState == "complete")
385
+ {
386
+ domReadyEvent.run(); // call the onload handler
387
+ }
388
+ };
389
+ @end
390
+ @*/
391
+ }
392
+ };
393
+
394
+ var domReady = function(handler) { domReadyEvent.add(handler); };
395
+ domReadyEvent.init();
396
+
397
+
398
+ /* Create MultiColumn instance when the DOM structure has been loaded */
399
+ domReady(function()
400
+ {
401
+ var MultiColumnCSS = new MultiColumn();
402
+ MultiColumnCSS.init();
403
+ });