flexlayout-rails 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,9 @@
1
+ module("Feature detection");
2
+
3
+ test("modernizr cssregions detection", function() {
4
+ notEqual(Modernizr.cssregions, undefined);
5
+ });
6
+
7
+ test("the browser isn't compatible with the css regions", function() {
8
+ equal(Modernizr.cssregions, false);
9
+ });
@@ -0,0 +1,43 @@
1
+ $(function(){
2
+ module("Layout");
3
+
4
+ $("#article").regions(["#article-region-1", "#article-region-2", "#article-region-3"]);
5
+
6
+ test("hide flow source", function() {
7
+ equal($('#article').css("display"), "none");
8
+ });
9
+
10
+ test("regions have content", function() {
11
+ notEqual($('.article-region').text(), "");
12
+ });
13
+
14
+ test("regions have different content", function() {
15
+ notEqual($('#article-region-1').text(), $('#article-region-2').text());
16
+ });
17
+
18
+ test("text in the first region is matching", function() {
19
+ var expected = /1Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod */;
20
+ ok(
21
+ expected.test($('#article-region-1').text()),
22
+ "is 1Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod"
23
+ );
24
+ });
25
+
26
+
27
+ // alternative method: use only a target jquery selector:
28
+ $("#alternative-article").regions('.alternative-region');
29
+
30
+ test("alternative method with jquery selector", function(){
31
+ var expected = /Lorem ipsum dolor sit amet, consectetur adipiscing elit. */;
32
+ ok(
33
+ expected.test($('.alternative-region:first').text()),
34
+ 'is Lorem ipsum dolor sit amet, consectetur adipisicing elit. …'
35
+ )
36
+ });
37
+
38
+
39
+ // handling oversized elements
40
+ test("oversized object visible", function(){
41
+ equal($('.alternative-region img#oversized').length, 1);
42
+ });
43
+ });
File without changes
@@ -0,0 +1,12 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'flexie-rails'
5
+
6
+ # Requires supporting files with custom matchers and macros, etc,
7
+ # in ./support/ and its subdirectories.
8
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
+
10
+ RSpec.configure do |config|
11
+
12
+ end
@@ -0,0 +1,6 @@
1
+ // test if the CSS regions support is enabled
2
+ // http://dev.w3.org/csswg/css3-regions/
3
+
4
+ Modernizr.addTest( "cssregions",function(){
5
+ return Modernizr.testAllProps("flow");
6
+ });
@@ -0,0 +1,2039 @@
1
+ /*
2
+ File: flexie.js
3
+
4
+ About: Version
5
+ 1.0.3
6
+
7
+ Project: Flexie
8
+
9
+ Description:
10
+ Legacy support for the CSS3 Flexible Box Model
11
+
12
+ License:
13
+ The MIT License
14
+
15
+ Copyright (c) 2010 Richard Herrera
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ of this software and associated documentation files (the "Software"), to deal
19
+ in the Software without restriction, including without limitation the rights
20
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ copies of the Software, and to permit persons to whom the Software is
22
+ furnished to do so, subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in
25
+ all copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
33
+ THE SOFTWARE.
34
+ */
35
+
36
+ /*
37
+ Class: Flexie
38
+ Scoped to the Flexie Global Namespace
39
+ */
40
+
41
+ /*jslint evil: true, regexp: false, plusplus: false */
42
+ /*global window, document */
43
+
44
+
45
+ var flexiebox = function(selector, options) {
46
+ return new Flexie.box($(selector), options)
47
+ }
48
+
49
+ var Flexie = (function (win, doc) {
50
+
51
+ // Scope public properties
52
+ var FLX = {},
53
+
54
+ // Each Flexie-modified DOM node gets a unique identifier
55
+ FLX_DOM_ID = 0,
56
+ FLX_DOM_ATTR = "data-flexie-id",
57
+ FLX_PARENT_ATTR = "data-flexie-parent",
58
+
59
+ // Store support for flexbox
60
+ SUPPORT,
61
+
62
+ // Store reference to engine
63
+ ENGINE,
64
+
65
+ ENGINES = {
66
+ "NW" : {
67
+ s : "*.Dom.select"
68
+ },
69
+ "DOMAssistant" : {
70
+ s : "*.$",
71
+ m : "*.DOMReady"
72
+ },
73
+ "Prototype" : {
74
+ s : "$$",
75
+ m : "document.observe",
76
+ p : "dom:loaded",
77
+ c : "document"
78
+ },
79
+ "YAHOO" : {
80
+ s : "*.util.Selector.query",
81
+ m : "*.util.Event.onDOMReady",
82
+ c : "*.util.Event"
83
+ },
84
+ "MooTools" : {
85
+ s : "$$",
86
+ m : "window.addEvent",
87
+ p : "domready"
88
+ },
89
+ "Sizzle" : {
90
+ s : "*"
91
+ },
92
+ "jQuery" : {
93
+ s : "*",
94
+ m : "*(document).ready"
95
+ },
96
+ "dojo" : {
97
+ s : "*.query",
98
+ m : "*.addOnLoad"
99
+ }
100
+ },
101
+
102
+ // Store reference to library
103
+ LIBRARY,
104
+
105
+ // Regular Expressions
106
+ PIXEL = /^-?\d+(?:px)?$/i,
107
+ NUMBER = /^-?\d/,
108
+ SIZES = /width|height|margin|padding|border/,
109
+ MSIE = /(msie) ([\w.]+)/,
110
+ WHITESPACE_CHARACTERS = /\t|\n|\r/g,
111
+ RESTRICTIVE_PROPERTIES = /^max\-([a-z]+)/,
112
+ PROTOCOL = /^https?:\/\//i,
113
+ LEADINGTRIM = /^\s\s*/,
114
+ TRAILINGTRIM = /\s\s*$/,
115
+ ONLY_WHITESPACE = /^\s*$/,
116
+ CSS_SELECTOR = /\s?(\#|\.|\[|\:(\:)?[^first\-(line|letter)|before|after]+)/g,
117
+
118
+ // String constants
119
+ EMPTY_STRING = "",
120
+ SPACE_STRING = " ",
121
+ PLACEHOLDER_STRING = "$1",
122
+ PADDING_RIGHT = "paddingRight",
123
+ PADDING_BOTTOM = "paddingBottom",
124
+ PADDING_LEFT = "paddingLeft",
125
+ PADDING_TOP = "paddingTop",
126
+ BORDER_RIGHT = "borderRightWidth",
127
+ BORDER_BOTTOM = "borderBottomWidth",
128
+ BORDER_LEFT = "borderLeftWidth",
129
+ BORDER_TOP = "borderTopWidth",
130
+ HORIZONTAL = "horizontal",
131
+ VERTICAL = "vertical",
132
+ INLINE_AXIS = "inline-axis",
133
+ BLOCK_AXIS = "block-axis",
134
+ INHERIT = "inherit",
135
+ LEFT = "left",
136
+
137
+ END_MUSTACHE = "}",
138
+
139
+ PREFIXES = " -o- -moz- -ms- -webkit- -khtml- ".split(SPACE_STRING),
140
+
141
+ DEFAULTS = {
142
+ orient : HORIZONTAL,
143
+ align : "stretch",
144
+ direction : INHERIT,
145
+ pack : "start"
146
+ },
147
+
148
+ // Global reference objects
149
+ FLEX_BOXES = [],
150
+ POSSIBLE_FLEX_CHILDREN = [],
151
+ DOM_ORDERED,
152
+
153
+ RESIZE_LISTENER,
154
+
155
+ // Minification optimizations
156
+ TRUE = true,
157
+ FALSE = false,
158
+ NULL = null,
159
+ UNDEFINED,
160
+
161
+ // If IE, which version?
162
+ BROWSER = {
163
+ IE : (function () {
164
+ var ie, ua = win.navigator.userAgent,
165
+ match = (MSIE).exec(ua.toLowerCase());
166
+
167
+ if (match) {
168
+ ie = parseInt(match[2], 10);
169
+ }
170
+
171
+ return ie;
172
+ }())
173
+ },
174
+
175
+ /*
176
+ selectivizr v1.0.0 - (c) Keith Clark, freely distributable under the terms
177
+ of the MIT license.
178
+
179
+ selectivizr.com
180
+ */
181
+ selectivizrEngine;
182
+
183
+ function trim (string) {
184
+ if (string) {
185
+ string = string.replace(LEADINGTRIM, EMPTY_STRING).replace(TRAILINGTRIM, EMPTY_STRING);
186
+ }
187
+
188
+ return string;
189
+ }
190
+
191
+ // --[ determineSelectorMethod() ]--------------------------------------
192
+ // walks through the engines object testing for an suitable
193
+ // selector engine.
194
+
195
+ // Moving outside Selectivizr scope because detection is needed before running selectivizrEngine
196
+ function determineSelectorMethod() {
197
+ // compatiable selector engines in order of CSS3 support
198
+ var engines = ENGINES, method,
199
+ engine, obj;
200
+
201
+ for (engine in engines) {
202
+ if (engines.hasOwnProperty(engine)) {
203
+ obj = engines[engine];
204
+
205
+ if (win[engine] && !method) {
206
+ method = eval(obj.s.replace("*", engine));
207
+
208
+ if (method) {
209
+ ENGINE = engine;
210
+ break;
211
+ }
212
+ }
213
+ }
214
+ }
215
+
216
+ return method;
217
+ }
218
+
219
+ // Event handler for onload/onresize events
220
+ function addEvent(type, func) {
221
+ type = "on" + type;
222
+ var oldevent = win[type];
223
+
224
+ if (typeof win[type] !== "function") {
225
+ win[type] = func;
226
+ } else {
227
+ win[type] = function () {
228
+ if (oldevent) {
229
+ oldevent();
230
+ }
231
+ func();
232
+ };
233
+ }
234
+ }
235
+
236
+ function attachLoadMethod(handler) {
237
+ if (!ENGINE) {
238
+ LIBRARY = determineSelectorMethod();
239
+ }
240
+
241
+ // compatiable selector engines in order of CSS3 support
242
+ var engines = ENGINES,
243
+ method, caller, args,
244
+ engine, obj;
245
+
246
+ for (engine in engines) {
247
+ if (engines.hasOwnProperty(engine)) {
248
+ obj = engines[engine];
249
+
250
+ if (win[engine] && !method && obj.m) {
251
+ method = eval(obj.m.replace("*", engine));
252
+ caller = obj.c ? eval(obj.c.replace("*", engine)) : win;
253
+ args = [];
254
+
255
+ if (method && caller) {
256
+ if (obj.p) {
257
+ args.push(obj.p);
258
+ }
259
+ args.push(handler);
260
+ method.apply(caller, args);
261
+ break;
262
+ }
263
+ }
264
+ }
265
+ }
266
+
267
+ if (!method) {
268
+ addEvent("load", handler);
269
+ }
270
+ }
271
+
272
+ function buildSelector (node) {
273
+ var selector = node.nodeName.toLowerCase();
274
+
275
+ if (node.id) {
276
+ selector += "#" + node.id;
277
+ } else if (node.FLX_DOM_ID) {
278
+ selector += "[" + FLX_DOM_ATTR + "='" + node.FLX_DOM_ID + "']";
279
+ }
280
+
281
+ return selector;
282
+ }
283
+
284
+ function setFlexieId (node) {
285
+ if (!node.FLX_DOM_ID) {
286
+ FLX_DOM_ID = (FLX_DOM_ID + 1);
287
+
288
+ node.FLX_DOM_ID = FLX_DOM_ID;
289
+ node.setAttribute(FLX_DOM_ATTR, node.FLX_DOM_ID);
290
+ }
291
+ }
292
+
293
+ function buildSelectorTree(text) {
294
+ var rules = [], ruletext, rule,
295
+ match, selector, proptext, splitprop, properties,
296
+ i, j, x;
297
+
298
+ // Tabs, Returns
299
+ text = text.replace(WHITESPACE_CHARACTERS, EMPTY_STRING);
300
+
301
+ // Leading / Trailing Whitespace
302
+ text = text.replace(/\s?(\{|\:|\})\s?/g, PLACEHOLDER_STRING);
303
+
304
+ ruletext = text.split(END_MUSTACHE);
305
+
306
+ for (i in ruletext) {
307
+ if (ruletext.hasOwnProperty(i)) {
308
+ text = ruletext[i];
309
+
310
+ if (text) {
311
+ rule = [text, END_MUSTACHE].join(EMPTY_STRING);
312
+
313
+ match = (/(\@media[^\{]+\{)?(.*)\{(.*)\}/).exec(rule);
314
+
315
+ if (match && match[3]) {
316
+ selector = match[2];
317
+ proptext = match[3].split(";");
318
+ properties = [];
319
+
320
+ for (j in proptext) {
321
+ if (proptext.hasOwnProperty(j)) {
322
+ x = proptext[j];
323
+ splitprop = x.split(":");
324
+
325
+ if (splitprop.length && splitprop[1]) {
326
+ properties.push({
327
+ property : splitprop[0],
328
+ value : splitprop[1]
329
+ });
330
+ }
331
+ }
332
+ }
333
+
334
+ if (selector && properties.length) {
335
+ rules.push({
336
+ selector : selector,
337
+ properties : properties
338
+ });
339
+ }
340
+ }
341
+ }
342
+ }
343
+ }
344
+
345
+ return rules;
346
+ }
347
+
348
+ function findFlexboxElements(rules) {
349
+ var selectors, properties,
350
+ property, value, shortProp,
351
+ selectorSplit = /\s?,\s?/,
352
+ createUniqueObject, addRules, key,
353
+ uniqueChildren = {}, uniqueBoxes = {},
354
+ i, j, rule, k, l, selector, m, n, prop;
355
+
356
+ createUniqueObject = function (selector, rules, prop, value) {
357
+ var unique, i, j, rule;
358
+
359
+ unique = {
360
+ selector : trim(selector),
361
+ properties : []
362
+ };
363
+
364
+ for (i = 0, j = rules.properties.length; i < j; i++) {
365
+ rule = rules.properties[i];
366
+
367
+ unique.properties.push({
368
+ property : trim(rule.property),
369
+ value : trim(rule.value)
370
+ });
371
+ }
372
+
373
+ if (prop && value) {
374
+ unique[prop] = value;
375
+ }
376
+
377
+ return unique;
378
+ };
379
+
380
+ addRules = function (selector, rules, prop, value) {
381
+ var box = (prop && value) ? uniqueChildren[selector] : uniqueBoxes[selector],
382
+ exists, x, i, j, rule, k, l;
383
+
384
+ if (box) {
385
+ for (i = 0, j = rules.properties.length; i < j; i++) {
386
+ rule = rules.properties[i];
387
+
388
+ for (k = 0, l = box.properties.length; k < l; k++) {
389
+ x = box.properties[k];
390
+
391
+ if (rule.property === x.property) {
392
+ exists = k;
393
+ return false;
394
+ }
395
+ }
396
+
397
+ if (exists) {
398
+ box.properties[exists] = rule;
399
+ } else {
400
+ box.properties.push(rule);
401
+ }
402
+ }
403
+
404
+ if (prop && value) {
405
+ box[prop] = value;
406
+ }
407
+ } else {
408
+ if (prop && value) {
409
+ uniqueChildren[selector] = createUniqueObject(selector, rules, prop, value);
410
+ } else {
411
+ uniqueBoxes[selector] = createUniqueObject(selector, rules, NULL, NULL);
412
+ }
413
+ }
414
+ };
415
+
416
+ for (i = 0, j = rules.length; i < j; i++) {
417
+ rule = rules[i];
418
+
419
+ selectors = trim(rule.selector).replace(selectorSplit, ",").split(selectorSplit);
420
+
421
+ for (k = 0, l = selectors.length; k < l; k++) {
422
+ selector = trim(selectors[k]);
423
+ properties = rule.properties;
424
+
425
+ for (m = 0, n = properties.length; m < n; m++) {
426
+ prop = properties[m];
427
+ property = trim(prop.property);
428
+ value = trim(prop.value);
429
+
430
+ if (property) {
431
+ shortProp = property.replace("box-", EMPTY_STRING);
432
+
433
+ switch (shortProp) {
434
+ case "display" :
435
+ if (value === "box") {
436
+ addRules(selector, rule, NULL, NULL);
437
+ }
438
+ break;
439
+
440
+ case "orient" :
441
+ case "align" :
442
+ case "direction" :
443
+ case "pack" :
444
+ addRules(selector, rule, NULL, NULL);
445
+ break;
446
+
447
+ case "flex" :
448
+ case "flex-group" :
449
+ case "ordinal-group" :
450
+ addRules(selector, rule, shortProp, value);
451
+ break;
452
+ }
453
+ }
454
+ }
455
+ }
456
+ }
457
+
458
+ for (key in uniqueBoxes) {
459
+ if (uniqueBoxes.hasOwnProperty(key)) {
460
+ FLEX_BOXES.push(uniqueBoxes[key]);
461
+ }
462
+ }
463
+
464
+ for (key in uniqueChildren) {
465
+ if (uniqueChildren.hasOwnProperty(key)) {
466
+ POSSIBLE_FLEX_CHILDREN.push(uniqueChildren[key]);
467
+ }
468
+ }
469
+
470
+ return {
471
+ boxes : FLEX_BOXES,
472
+ children : POSSIBLE_FLEX_CHILDREN
473
+ };
474
+ }
475
+
476
+ function matchFlexChildren(parent, lib, possibleChildren) {
477
+ var caller, unique, matches = [],
478
+ i, j, child,
479
+ k, l, node,
480
+ key;
481
+
482
+ for (i = 0, j = possibleChildren.length; i < j; i++) {
483
+ child = possibleChildren[i];
484
+
485
+ if (child.selector) {
486
+ caller = lib(child.selector);
487
+ caller = caller[0] ? caller : [caller];
488
+
489
+ if (caller[0]) {
490
+
491
+ for (k = 0, l = caller.length; k < l; k++) {
492
+ node = caller[k];
493
+
494
+ if (node.nodeName !== UNDEFINED) {
495
+ switch (node.nodeName.toLowerCase()) {
496
+ case "script" :
497
+ case "style" :
498
+ case "link" :
499
+ break;
500
+
501
+ default :
502
+ if (node.parentNode === parent) {
503
+ // Flag each unique node with FLX_DOM_ID
504
+ setFlexieId(node);
505
+
506
+ unique = {};
507
+
508
+ for (key in child) {
509
+ if (child.hasOwnProperty(key)) {
510
+ unique[key] = child[key];
511
+ }
512
+ }
513
+
514
+ unique.match = node;
515
+ matches.push(unique);
516
+ }
517
+ break;
518
+ }
519
+ }
520
+ }
521
+ }
522
+ } else {
523
+ // Flag each unique node with FLX_DOM_ID
524
+ setFlexieId(child);
525
+
526
+ matches.push({
527
+ match : child,
528
+ selector : buildSelector(child)
529
+ });
530
+ }
531
+ }
532
+
533
+ return matches;
534
+ }
535
+
536
+ function getParams(params) {
537
+ var key;
538
+
539
+ for (key in params) {
540
+ if (params.hasOwnProperty(key)) {
541
+ params[key] = params[key] || DEFAULTS[key];
542
+ }
543
+ }
544
+
545
+ return params;
546
+ }
547
+
548
+ function buildFlexieCall(flexers) {
549
+ var selector, properties, property, value, shortProp,
550
+ display, orient, align, direction, pack,
551
+ lib, caller, children,
552
+ box, params, flexboxes = {},
553
+ match, childMatch, nestedFlexboxes,
554
+ flexieParentSelector = "[" + FLX_PARENT_ATTR + "]",
555
+ i, j, flex, k, l, prop,
556
+ target, key, m, n, child, o, p, existing;
557
+
558
+ // No boxflex? No dice.
559
+ if (!flexers) {
560
+ return;
561
+ }
562
+
563
+ for (i = 0, j = flexers.boxes.length; i < j; i++) {
564
+ flex = flexers.boxes[i];
565
+ flex.selector = trim(flex.selector);
566
+
567
+ selector = flex.selector;
568
+ properties = flex.properties;
569
+
570
+ display = orient = align = direction = pack = NULL;
571
+
572
+ for (k = 0, l = properties.length; k < l; k++) {
573
+ prop = properties[k];
574
+
575
+ property = trim(prop.property);
576
+ value = trim(prop.value);
577
+
578
+ if (property) {
579
+ shortProp = property.replace("box-", EMPTY_STRING);
580
+
581
+ switch (shortProp) {
582
+ case "display" :
583
+ if (value === "box") {
584
+ display = value;
585
+ }
586
+ break;
587
+
588
+ case "orient" :
589
+ orient = value;
590
+ break;
591
+
592
+ case "align" :
593
+ align = value;
594
+ break;
595
+
596
+ case "direction" :
597
+ direction = value;
598
+ break;
599
+
600
+ case "pack" :
601
+ pack = value;
602
+ break;
603
+ }
604
+ }
605
+ }
606
+
607
+ // Determine library
608
+ lib = LIBRARY;
609
+
610
+ // Call it.
611
+ caller = lib(flex.selector);
612
+
613
+ // In an array?
614
+ caller = caller[0] ? caller : [caller];
615
+
616
+ for (k = 0, l = caller.length; k < l; k++) {
617
+ target = caller[k];
618
+
619
+ // If is DOM object
620
+ if (target.nodeType) {
621
+ // Flag each unique node with FLX_DOM_ID
622
+ setFlexieId(target);
623
+
624
+ // Find possible child node matches
625
+ children = matchFlexChildren(target, lib, flexers.children);
626
+
627
+ // Find any nested flexbox elements
628
+ nestedFlexboxes = selector + " " + flexieParentSelector;
629
+
630
+ // Make sure there is some value associated with box properties
631
+ params = {
632
+ target : target,
633
+ selector : selector,
634
+ properties : properties,
635
+ children : children,
636
+ display : display,
637
+ orient : orient,
638
+ align : align,
639
+ direction: direction,
640
+ pack : pack,
641
+ nested : nestedFlexboxes
642
+ };
643
+
644
+ match = flexboxes[target.FLX_DOM_ID];
645
+
646
+ if (match) {
647
+ for (key in params) {
648
+ if (params.hasOwnProperty(key)) {
649
+ value = params[key];
650
+
651
+ switch (key) {
652
+ case "selector" :
653
+ if (value && !(new RegExp(value).test(match[key]))) {
654
+ match[key] += ", " + value;
655
+ }
656
+ break;
657
+
658
+ case "children" :
659
+ for (m = 0, n = params[key].length; m < n; m++) {
660
+ child = params[key][m];
661
+ childMatch = FALSE;
662
+
663
+ for (o = 0, p = match[key].length; o < p; o++) {
664
+ existing = match[key][o];
665
+
666
+ if (child.match.FLX_DOM_ID === existing.match.FLX_DOM_ID) {
667
+ childMatch = TRUE;
668
+ }
669
+ }
670
+
671
+ if (!childMatch) {
672
+ match[key].push(child);
673
+ }
674
+ }
675
+ break;
676
+
677
+ default :
678
+ if (value) {
679
+ match[key] = value;
680
+ }
681
+ break;
682
+ }
683
+ }
684
+ }
685
+ } else {
686
+ flexboxes[target.FLX_DOM_ID] = getParams(params);
687
+ flexboxes[target.FLX_DOM_ID].target.setAttribute(FLX_PARENT_ATTR, TRUE);
688
+ }
689
+ }
690
+ }
691
+ }
692
+
693
+ DOM_ORDERED = LIBRARY(flexieParentSelector);
694
+ FLEX_BOXES = {};
695
+
696
+ for (i = 0, j = DOM_ORDERED.length; i < j; i++) {
697
+ target = DOM_ORDERED[i];
698
+
699
+ FLEX_BOXES[target.FLX_DOM_ID] = flexboxes[target.FLX_DOM_ID];
700
+ }
701
+
702
+ // Loop through each match, initialize constructor
703
+ for (key in FLEX_BOXES) {
704
+ if (FLEX_BOXES.hasOwnProperty(key)) {
705
+ flex = FLEX_BOXES[key];
706
+
707
+ // One final check to ensure each flexbox has a display property
708
+ if (flex.display === "box") {
709
+ // Constructor
710
+ box = new FLX.box(flex);
711
+ }
712
+ }
713
+ }
714
+ }
715
+
716
+ function calcPx(element, props, dir) {
717
+ var dim = dir.replace(dir.charAt(0), dir.charAt(0).toUpperCase()),
718
+ value = element["offset" + dim] || 0,
719
+ i, j, prop;
720
+
721
+ if (value) {
722
+ for (i = 0, j = props.length; i < j; i++) {
723
+ prop = parseFloat(element.currentStyle[props[i]]);
724
+
725
+ if (!isNaN(prop)) {
726
+ value -= prop;
727
+ }
728
+ }
729
+ }
730
+
731
+ return value;
732
+ }
733
+
734
+ function getTrueValue(element, name) {
735
+ var left, rsLeft,
736
+ ret = element.currentStyle && element.currentStyle[name],
737
+ style = element.style;
738
+
739
+ if (!PIXEL.test(ret) && NUMBER.test(ret)) {
740
+
741
+ // Remember the original values
742
+ left = style.left;
743
+ rsLeft = element.runtimeStyle.left;
744
+
745
+ // Put in the new values to get a computed value out
746
+ element.runtimeStyle.left = element.currentStyle.left;
747
+ style.left = ret || 0;
748
+ ret = style.pixelLeft + "px";
749
+
750
+ // Revert the changed values
751
+ style.left = left || 0;
752
+ element.runtimeStyle.left = rsLeft;
753
+ }
754
+
755
+ return ret;
756
+ }
757
+
758
+ function unAuto(element, prop, name) {
759
+ var props;
760
+
761
+ switch (name) {
762
+ case "width" :
763
+ props = [PADDING_LEFT, PADDING_RIGHT, BORDER_LEFT, BORDER_RIGHT];
764
+ prop = calcPx(element, props, name);
765
+ break;
766
+
767
+ case "height" :
768
+ props = [PADDING_TOP, PADDING_BOTTOM, BORDER_TOP, BORDER_BOTTOM];
769
+ prop = calcPx(element, props, name);
770
+ break;
771
+
772
+ default :
773
+ prop = getTrueValue(element, name);
774
+ break;
775
+ }
776
+
777
+ return prop;
778
+ }
779
+
780
+ function getPixelValue(element, prop, name) {
781
+ if (PIXEL.test(prop)) {
782
+ return prop;
783
+ }
784
+
785
+ // if property is auto, do some messy appending
786
+ if (prop === "auto" || prop === "medium") {
787
+ prop = unAuto(element, prop, name);
788
+ } else {
789
+ prop = getTrueValue(element, name);
790
+ }
791
+
792
+ return prop;
793
+ }
794
+
795
+ function getComputedStyle(element, property, returnAsInt) {
796
+ var value;
797
+
798
+ if (element === UNDEFINED) {
799
+ return;
800
+ }
801
+
802
+ if (win.getComputedStyle) {
803
+ value = win.getComputedStyle(element, NULL)[property];
804
+ } else {
805
+ if (SIZES.test(property)) {
806
+ value = getPixelValue(element, (element && element.currentStyle) ? element.currentStyle[property] : 0, property);
807
+ } else {
808
+ value = element.currentStyle[property];
809
+ }
810
+ }
811
+
812
+ if (returnAsInt) {
813
+ value = parseInt(value, 10);
814
+
815
+ if (isNaN(value)) {
816
+ value = 0;
817
+ }
818
+ }
819
+
820
+ return value;
821
+ }
822
+
823
+ function clientWidth(element) {
824
+ return element.innerWidth || element.clientWidth;
825
+ }
826
+
827
+ function clientHeight(element) {
828
+ return element.innerHeight || element.clientHeight;
829
+ }
830
+
831
+ function appendProperty(target, prop, value, prefixName) {
832
+ var cssText = [],
833
+ i, j, prefix;
834
+
835
+ for (i = 0, j = PREFIXES.length; i < j; i++) {
836
+ prefix = PREFIXES[i];
837
+ cssText.push((prefixName ? prefix : EMPTY_STRING) + prop + ":" + (!prefixName ? prefix : EMPTY_STRING) + value);
838
+ }
839
+
840
+ target.style.cssText += cssText.join(";");
841
+ return target;
842
+ }
843
+
844
+ function appendPixelValue(target, prop, value) {
845
+ var targets = target && target[0] ? target : [target],
846
+ i, j;
847
+
848
+ for (i = 0, j = targets.length; i < j; i++) {
849
+ target = targets[i];
850
+
851
+ if (target && target.style) {
852
+ target.style[prop] = (value ? (value + "px") : EMPTY_STRING);
853
+ }
854
+ }
855
+ }
856
+
857
+ function calculateSpecificity (selector) {
858
+ var selectorGrid, matrix, total,
859
+ i, j, chunk;
860
+
861
+ selectorGrid = selector.replace(CSS_SELECTOR, function (e, f) {
862
+ return "%" + f;
863
+ }).replace(/\s|\>|\+|\~/g, "%").split(/%/g);
864
+
865
+ matrix = {
866
+ _id : 100,
867
+ _class : 10,
868
+ _tag : 1
869
+ };
870
+
871
+ // Start with rule index position
872
+ total = 0;
873
+
874
+ // Add each selector value to total.
875
+ for (i = 0, j = selectorGrid.length; i < j; i++) {
876
+ chunk = selectorGrid[i];
877
+
878
+ if ((/#/).test(chunk)) {
879
+ total += matrix._id;
880
+ } else if ((/\.|\[|\:/).test(chunk)) {
881
+ total += matrix._class;
882
+ } else if ((/[a-zA-Z]+/).test(chunk)) {
883
+ total += matrix._tag;
884
+ }
885
+ }
886
+
887
+ return total;
888
+ }
889
+
890
+ function filterDuplicates (matches, children, type) {
891
+ var filteredMatches = [], exists,
892
+ spec = (type ? "ordinal" : "flex") + "Specificity",
893
+ i, j, x, k, l, f;
894
+
895
+ for (i = 0, j = matches.length; i < j; i++) {
896
+ x = matches[i];
897
+
898
+ if ((!type && x.flex) || (type && x["ordinal-group"])) {
899
+ x[spec] = x[spec] || calculateSpecificity(x.selector);
900
+
901
+ exists = FALSE;
902
+
903
+ for (k = 0, l = filteredMatches.length; k < l; k++) {
904
+ f = filteredMatches[k];
905
+
906
+ if (f.match === x.match) {
907
+ if (f[spec] < x[spec]) {
908
+ filteredMatches[j] = x;
909
+ }
910
+
911
+ exists = TRUE;
912
+ return FALSE;
913
+ }
914
+ }
915
+
916
+ if (!exists) {
917
+ filteredMatches.push(x);
918
+ }
919
+ }
920
+ }
921
+
922
+ return filteredMatches;
923
+ }
924
+
925
+ function createMatchMatrix(matches, children, type) {
926
+ var groups = {}, keys = [], totalRatio = 0,
927
+ group, order = "ordinal-group",
928
+ BoxOrdinalAttr = "data-" + order,
929
+ i, j, kid, k, l, x, key;
930
+
931
+ // Filter dupes
932
+ matches = filterDuplicates(matches, children, type);
933
+
934
+ for (i = 0, j = children.length; i < j; i++) {
935
+ kid = children[i];
936
+
937
+ for (k = 0, l = matches.length; k < l; k++) {
938
+ x = matches[k];
939
+
940
+ if (type) {
941
+ // If no value declared, it's the default.
942
+ group = x[order] || "1";
943
+
944
+ if (x.match === kid) {
945
+ x.match.setAttribute(BoxOrdinalAttr, group);
946
+
947
+ groups[group] = groups[group] || [];
948
+ groups[group].push(x);
949
+ }
950
+ } else {
951
+ // If no value declared, it's the default.
952
+ group = x.flex || "0";
953
+
954
+ if (x.match === kid && (!x[group] || (x[group] && parseInt(x[group], 10) <= 1))) {
955
+ totalRatio += parseInt(group, 10);
956
+
957
+ groups[group] = groups[group] || [];
958
+ groups[group].push(x);
959
+ }
960
+ }
961
+ }
962
+
963
+ if (type && !kid.getAttribute(BoxOrdinalAttr)) {
964
+ group = "1";
965
+ kid.setAttribute(BoxOrdinalAttr, group);
966
+
967
+ groups[group] = groups[group] || [];
968
+ groups[group].push({
969
+ match : kid
970
+ });
971
+ }
972
+ }
973
+
974
+ for (key in groups) {
975
+ if (groups.hasOwnProperty(key)) {
976
+ keys.push(key);
977
+ }
978
+ }
979
+
980
+ keys.sort(function (a, b) {
981
+ return b - a;
982
+ });
983
+
984
+ return {
985
+ keys : keys,
986
+ groups : groups,
987
+ total : totalRatio
988
+ };
989
+ }
990
+
991
+ function attachResizeListener(construct, params) {
992
+ if (!RESIZE_LISTENER) {
993
+ var storedWidth, storedHeight,
994
+ currentWidth, currentHeight,
995
+ docBody = doc.body,
996
+ docEl = doc.documentElement,
997
+ resizeTimer,
998
+ innerWidth = "innerWidth", innerHeight = "innerHeight",
999
+ clientWidth = "clientWidth", clientHeight = "clientHeight";
1000
+
1001
+ addEvent("resize", function () {
1002
+ if (resizeTimer) {
1003
+ window.clearTimeout(resizeTimer);
1004
+ }
1005
+
1006
+ resizeTimer = window.setTimeout(function () {
1007
+ currentWidth = win[innerWidth] || docEl[innerWidth] || docEl[clientWidth] || docBody[clientWidth];
1008
+ currentHeight = win[innerHeight] || docEl[innerHeight] || docEl[clientHeight] || docBody[clientHeight];
1009
+
1010
+ if (storedWidth !== currentWidth || storedHeight !== currentHeight) {
1011
+ FLX.updateInstance(NULL, NULL);
1012
+
1013
+ storedWidth = currentWidth;
1014
+ storedHeight = currentHeight;
1015
+ }
1016
+ }, 250);
1017
+ });
1018
+
1019
+ RESIZE_LISTENER = TRUE;
1020
+ }
1021
+ }
1022
+
1023
+ function cleanPositioningProperties (children) {
1024
+ var i, j, kid, w, h;
1025
+
1026
+ for (i = 0, j = children.length; i < j; i++) {
1027
+ kid = children[i];
1028
+
1029
+ w = kid.style.width;
1030
+ h = kid.style.height;
1031
+
1032
+ kid.style.cssText = EMPTY_STRING;
1033
+
1034
+ kid.style.width = w;
1035
+ kid.style.height = h;
1036
+ }
1037
+ }
1038
+
1039
+ function sanitizeChildren (target, nodes) {
1040
+ var children = [], node, i, j;
1041
+
1042
+ for (i = 0, j = nodes.length; i < j; i++) {
1043
+ node = nodes[i];
1044
+
1045
+ if (node) {
1046
+ switch (node.nodeName.toLowerCase()) {
1047
+ case "script" :
1048
+ case "style" :
1049
+ case "link" :
1050
+ break;
1051
+
1052
+ default :
1053
+ if (node.nodeType === 1) {
1054
+ children.push(node);
1055
+ } else if ((node.nodeType === 3) && (node.isElementContentWhitespace || (ONLY_WHITESPACE).test(node.data))) {
1056
+ target.removeChild(node);
1057
+ i--;
1058
+ }
1059
+ break;
1060
+ }
1061
+ }
1062
+ }
1063
+
1064
+ return children;
1065
+ }
1066
+
1067
+ function parentFlex (target) {
1068
+ var totalFlex = 0,
1069
+ parent = target.parentNode,
1070
+ obj,
1071
+ matrix,
1072
+ isNested;
1073
+
1074
+ while (parent.FLX_DOM_ID) {
1075
+ if (FLEX_BOXES[parent.FLX_DOM_ID]) {
1076
+ obj = FLEX_BOXES[parent.FLX_DOM_ID];
1077
+ matrix = createMatchMatrix(obj.children, sanitizeChildren(parent, parent.childNodes), NULL);
1078
+ totalFlex += matrix.total;
1079
+ isNested = TRUE;
1080
+ }
1081
+ parent = parent.parentNode;
1082
+ }
1083
+
1084
+ return {
1085
+ nested : isNested,
1086
+ flex : totalFlex
1087
+ };
1088
+ }
1089
+
1090
+ function dimensionValues (target, prop) {
1091
+ var parent = target.parentNode,
1092
+ obj, dimension, i, j, rule;
1093
+
1094
+ if (parent.FLX_DOM_ID) {
1095
+ obj = FLEX_BOXES[parent.FLX_DOM_ID];
1096
+
1097
+ for (i = 0, j = obj.properties.length; i < j; i++) {
1098
+ rule = obj.properties[i];
1099
+
1100
+ if ((new RegExp(prop)).test(rule.property)) {
1101
+ dimension = TRUE;
1102
+ return FALSE;
1103
+ }
1104
+ }
1105
+ }
1106
+
1107
+ return dimension;
1108
+ }
1109
+
1110
+ function updateChildValues (params) {
1111
+ var i, j, x;
1112
+
1113
+ if (params.flexMatrix) {
1114
+ for (i = 0, j = params.children.length; i < j; i++) {
1115
+ x = params.children[i];
1116
+ x.flex = params.flexMatrix[i];
1117
+ }
1118
+ }
1119
+
1120
+ if (params.ordinalMatrix) {
1121
+ for (i = 0, j = params.children.length; i < j; i++) {
1122
+ x = params.children[i];
1123
+ x["ordinal-group"] = params.ordinalMatrix[i];
1124
+ }
1125
+ }
1126
+
1127
+ return params;
1128
+ }
1129
+
1130
+ function ensureStructuralIntegrity (params, instance) {
1131
+ var target = params.target;
1132
+
1133
+ if (!target.FLX_DOM_ID) {
1134
+ target.FLX_DOM_ID = target.FLX_DOM_ID || (++FLX_DOM_ID);
1135
+ }
1136
+
1137
+ if (!params.nodes) {
1138
+ params.nodes = sanitizeChildren(target, target.childNodes);
1139
+ }
1140
+
1141
+ if (!params.selector) {
1142
+ params.selector = buildSelector(target);
1143
+ target.setAttribute(FLX_PARENT_ATTR, TRUE);
1144
+ }
1145
+
1146
+ if (!params.properties) {
1147
+ params.properties = [];
1148
+ }
1149
+
1150
+ if (!params.children) {
1151
+ params.children = matchFlexChildren(target, LIBRARY, sanitizeChildren(target, target.childNodes));
1152
+ }
1153
+
1154
+ if (!params.nested) {
1155
+ params.nested = params.selector + " [" + FLX_PARENT_ATTR + "]";
1156
+ }
1157
+
1158
+ params.target = target;
1159
+ params._instance = instance;
1160
+
1161
+ return params;
1162
+ }
1163
+
1164
+ selectivizrEngine = (function () {
1165
+ var RE_COMMENT = /(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)\s*?/g,
1166
+ RE_IMPORT = /@import\s*(?:(?:(?:url\(\s*(['"]?)(.*)\1)\s*\))|(?:(['"])(.*)\3))\s*([^;]*);/g,
1167
+ RE_ASSET_URL = /(behavior\s*?:\s*)?\burl\(\s*(["']?)(?!data:)([^"')]+)\2\s*\)/g,
1168
+ RE_SELECTOR_GROUP = /((?:^|(?:\s*\})+)(?:\s*@media[^\{]+\{)?)\s*([^\{]*?[\[:][^{]+)/g,
1169
+
1170
+ // Whitespace normalization regexp's
1171
+ RE_TIDY_TRAILING_WHITESPACE = /([(\[+~])\s+/g,
1172
+ RE_TIDY_LEADING_WHITESPACE = /\s+([)\]+~])/g,
1173
+ RE_TIDY_CONSECUTIVE_WHITESPACE = /\s+/g,
1174
+ RE_TIDY_TRIM_WHITESPACE = /^\s*((?:[\S\s]*\S)?)\s*$/;
1175
+
1176
+ // --[ trim() ]---------------------------------------------------------
1177
+ // removes leading, trailing whitespace from a string
1178
+ function trim(text) {
1179
+ return text.replace(RE_TIDY_TRIM_WHITESPACE, PLACEHOLDER_STRING);
1180
+ }
1181
+
1182
+ // --[ normalizeWhitespace() ]------------------------------------------
1183
+ // removes leading, trailing and consecutive whitespace from a string
1184
+ function normalizeWhitespace(text) {
1185
+ return trim(text).replace(RE_TIDY_CONSECUTIVE_WHITESPACE, SPACE_STRING);
1186
+ }
1187
+
1188
+ // --[ normalizeSelectorWhitespace() ]----------------------------------
1189
+ // tidys whitespace around selector brackets and combinators
1190
+ function normalizeSelectorWhitespace(selectorText) {
1191
+ return normalizeWhitespace(selectorText.replace(RE_TIDY_TRAILING_WHITESPACE, PLACEHOLDER_STRING).replace(RE_TIDY_LEADING_WHITESPACE, PLACEHOLDER_STRING));
1192
+ }
1193
+
1194
+ // --[ patchStyleSheet() ]----------------------------------------------
1195
+ // Scans the passed cssText for selectors that require emulation and
1196
+ // creates one or more patches for each matched selector.
1197
+ function patchStyleSheet(cssText) {
1198
+ return cssText.replace(RE_SELECTOR_GROUP, function (m, prefix, selectorText) {
1199
+ var selectorGroups, selector,
1200
+ i, j, group;
1201
+
1202
+ selectorGroups = selectorText.split(",");
1203
+
1204
+ for (i = 0, j = selectorGroups.length; i < j; i++) {
1205
+ group = selectorGroups[i];
1206
+ selector = normalizeSelectorWhitespace(group) + SPACE_STRING;
1207
+ }
1208
+
1209
+ return prefix + selectorGroups.join(",");
1210
+ });
1211
+ }
1212
+
1213
+ // --[ getXHRObject() ]-------------------------------------------------
1214
+ function getXHRObject() {
1215
+ if (win.XMLHttpRequest) {
1216
+ return new win.XMLHttpRequest();
1217
+ }
1218
+
1219
+ try {
1220
+ return new win.ActiveXObject("Microsoft.XMLHTTP");
1221
+ } catch (e) {
1222
+ return NULL;
1223
+ }
1224
+ }
1225
+
1226
+ function parseInlineStyles ( text ) {
1227
+ var reg = /<style[^<>]*>([^<>]*)<\/style[\s]?>/img,
1228
+ match = reg.exec(text),
1229
+ stylesheets = [],
1230
+ rawCSSText;
1231
+
1232
+ while (match) {
1233
+ rawCSSText = match[1];
1234
+
1235
+ if (rawCSSText) {
1236
+ stylesheets.push(rawCSSText);
1237
+ }
1238
+
1239
+ match = reg.exec(text);
1240
+ }
1241
+
1242
+ return stylesheets.join("\n\n");
1243
+ }
1244
+
1245
+ // --[ loadStyleSheet() ]-----------------------------------------------
1246
+ function loadStyleSheet(url) {
1247
+ var xhr = getXHRObject(),
1248
+ responseText;
1249
+
1250
+ xhr.open("GET", url, FALSE);
1251
+ xhr.send();
1252
+
1253
+ responseText = (xhr.status === 200) ? xhr.responseText : EMPTY_STRING;
1254
+
1255
+ if (url === window.location.href) {
1256
+ responseText = parseInlineStyles(responseText);
1257
+ }
1258
+
1259
+ return responseText;
1260
+ }
1261
+
1262
+ // --[ resolveUrl() ]---------------------------------------------------
1263
+ // Converts a URL fragment to a fully qualified URL using the specified
1264
+ // context URL. Returns null if same-origin policy is broken
1265
+ function resolveUrl(url, contextUrl) {
1266
+
1267
+ // IE9 returns a false positive sometimes(?)
1268
+ if (!url) {
1269
+ return;
1270
+ }
1271
+
1272
+ function getProtocolAndHost(url) {
1273
+ return url.substring(0, url.indexOf("/", 8));
1274
+ }
1275
+
1276
+ // absolute path
1277
+ if (PROTOCOL.test(url)) {
1278
+ return getProtocolAndHost(contextUrl) === getProtocolAndHost(url) ? url : NULL;
1279
+ }
1280
+
1281
+ // root-relative path
1282
+ if (url.charAt(0) === "/") {
1283
+ return getProtocolAndHost(contextUrl) + url;
1284
+ }
1285
+
1286
+ // relative path
1287
+ var contextUrlPath = contextUrl.split("?")[0]; // ignore query string in the contextUrl
1288
+ if (url.charAt(0) !== "?" && contextUrlPath.charAt(contextUrlPath.length - 1) !== "/") {
1289
+ contextUrlPath = contextUrlPath.substring(0, contextUrlPath.lastIndexOf("/") + 1);
1290
+ }
1291
+
1292
+ return contextUrlPath + url;
1293
+ }
1294
+
1295
+ // --[ parseStyleSheet() ]----------------------------------------------
1296
+ // Downloads the stylesheet specified by the URL, removes it's comments
1297
+ // and recursivly replaces @import rules with their contents, ultimately
1298
+ // returning the full cssText.
1299
+ function parseStyleSheet( url ) {
1300
+ if (url) {
1301
+ return loadStyleSheet(url).replace(RE_COMMENT, EMPTY_STRING).
1302
+ replace(RE_IMPORT, function( match, quoteChar, importUrl, quoteChar2, importUrl2, media ) {
1303
+ var cssText = parseStyleSheet(resolveUrl(importUrl || importUrl2, url));
1304
+ return (media) ? "@media " + media + " {" + cssText + "}" : cssText;
1305
+ }).
1306
+ replace(RE_ASSET_URL, function( match, isBehavior, quoteChar, assetUrl ) {
1307
+ quoteChar = quoteChar || EMPTY_STRING;
1308
+ return isBehavior ? match : " url(" + quoteChar + resolveUrl(assetUrl, url, true) + quoteChar + ") ";
1309
+ });
1310
+ }
1311
+ return EMPTY_STRING;
1312
+ }
1313
+
1314
+ // --[ init() ]---------------------------------------------------------
1315
+ return function () {
1316
+ // honour the <base> tag
1317
+ var url, stylesheets = [], stylesheet, i, j,
1318
+ baseTags = doc.getElementsByTagName("BASE"),
1319
+ baseUrl = (baseTags.length > 0) ? baseTags[0].href : doc.location.href,
1320
+ externalStyles = doc.styleSheets,
1321
+ cssText, tree, flexers;
1322
+
1323
+ for (i = 0, j = externalStyles.length; i < j; i++) {
1324
+ stylesheet = externalStyles[i];
1325
+
1326
+ if (stylesheet != NULL) {
1327
+ stylesheets.push(stylesheet);
1328
+ }
1329
+ }
1330
+
1331
+ // Add self to test for inline styles
1332
+ stylesheets.push(window.location);
1333
+
1334
+ for (i = 0, j = stylesheets.length; i < j; i++) {
1335
+ stylesheet = stylesheets[i];
1336
+
1337
+ if (stylesheet) {
1338
+ url = resolveUrl(stylesheet.href, baseUrl);
1339
+
1340
+ if (url) {
1341
+ cssText = patchStyleSheet(parseStyleSheet(url));
1342
+ }
1343
+
1344
+ if (cssText) {
1345
+ tree = buildSelectorTree(cssText);
1346
+ flexers = findFlexboxElements(tree);
1347
+ }
1348
+ }
1349
+ }
1350
+
1351
+ buildFlexieCall(flexers);
1352
+ };
1353
+ }());
1354
+
1355
+ // Flexie box constructor
1356
+ FLX.box = function (params) {
1357
+ return this.renderModel(params);
1358
+ };
1359
+
1360
+ FLX.box.prototype = {
1361
+ properties : {
1362
+ boxModel : function (target, children, params) {
1363
+ var selectors, stylesheet, paddingFix, generatedRules,
1364
+ i, j, selector;
1365
+
1366
+ target.style.display = "block";
1367
+
1368
+ if (BROWSER.IE === 8) {
1369
+ target.style.overflow = "hidden";
1370
+ }
1371
+
1372
+ // We'll be using floats, so the easiest way to retain layout
1373
+ // is the dreaded clear fix:
1374
+ if (!params.cleared) {
1375
+ selectors = params.selector.split(/\s?,\s?/);
1376
+ stylesheet = doc.styleSheets;
1377
+ stylesheet = stylesheet[stylesheet.length - 1];
1378
+ paddingFix = "padding-top:" + (getComputedStyle(target, PADDING_TOP, NULL) || "0.1px;");
1379
+
1380
+ generatedRules = [
1381
+ "content: '.'",
1382
+ "display: block",
1383
+ "height: 0",
1384
+ "overflow: hidden"
1385
+ ].join(";");
1386
+
1387
+ for (i = 0, j = selectors.length; i < j; i++) {
1388
+ selector = selectors[i];
1389
+
1390
+ if (stylesheet.addRule) {
1391
+ if (BROWSER.IE < 8) {
1392
+ target.style.zoom = "1";
1393
+
1394
+ if (BROWSER.IE === 6) {
1395
+ stylesheet.addRule(selector.replace(/\>|\+|\~/g, ""), paddingFix + "zoom:1;", 0);
1396
+ } else if (BROWSER.IE === 7) {
1397
+ stylesheet.addRule(selector, paddingFix + "display:inline-block;", 0);
1398
+ }
1399
+ } else {
1400
+ stylesheet.addRule(selector, paddingFix, 0);
1401
+ stylesheet.addRule(selector + ":before", generatedRules, 0);
1402
+ stylesheet.addRule(selector + ":after", generatedRules + ";clear:both;", 0);
1403
+ }
1404
+ } else if (stylesheet.insertRule) {
1405
+ stylesheet.insertRule(selector + "{" + paddingFix + "}", 0);
1406
+ stylesheet.insertRule(selector + ":after{" + generatedRules + ";clear:both;}", 0);
1407
+ }
1408
+ }
1409
+
1410
+ params.cleared = TRUE;
1411
+ }
1412
+ },
1413
+
1414
+ boxDirection : function (target, children, params) {
1415
+ var nestedSelector, nested,
1416
+ i, j, kid, node;
1417
+
1418
+ if ((params.direction === "reverse" && !params.reversed) || (params.direction === "normal" && params.reversed)) {
1419
+ children = children.reverse();
1420
+
1421
+ for (i = 0, j = children.length; i < j; i++) {
1422
+ kid = children[i];
1423
+ target.appendChild(kid);
1424
+ }
1425
+
1426
+ // box-direction is inheritable.
1427
+ // We need to see if there are any nested flexbox elements
1428
+ nestedSelector = LIBRARY(params.nested);
1429
+
1430
+ for (i = 0, j = nestedSelector.length; i < j; i++) {
1431
+ node = nestedSelector[i];
1432
+
1433
+ nested = FLEX_BOXES[node.FLX_DOM_ID];
1434
+
1435
+ if (nested && nested.direction === INHERIT) {
1436
+ nested.direction = params.direction;
1437
+ }
1438
+ }
1439
+
1440
+ params.reversed = !params.reversed;
1441
+ }
1442
+ },
1443
+
1444
+ boxOrient : function (target, children, params) {
1445
+ var self = this, wide, high,
1446
+ i, j, kid;
1447
+
1448
+ wide = {
1449
+ pos : "marginLeft",
1450
+ opp : "marginRight",
1451
+ dim : "width",
1452
+ out : "offsetWidth",
1453
+ func : clientWidth,
1454
+ pad : [PADDING_LEFT, PADDING_RIGHT, BORDER_LEFT, BORDER_RIGHT]
1455
+ };
1456
+
1457
+ high = {
1458
+ pos : "marginTop",
1459
+ opp : "marginBottom",
1460
+ dim : "height",
1461
+ out : "offsetHeight",
1462
+ func : clientHeight,
1463
+ pad : [PADDING_TOP, PADDING_BOTTOM, BORDER_TOP, BORDER_BOTTOM]
1464
+ };
1465
+
1466
+ if (!SUPPORT) {
1467
+ for (i = 0, j = children.length; i < j; i++) {
1468
+ kid = children[i];
1469
+
1470
+ kid.style[(BROWSER.IE >= 9) ? "cssFloat" : "styleFloat"] = LEFT;
1471
+
1472
+ if (params.orient === VERTICAL || params.orient === BLOCK_AXIS) {
1473
+ kid.style.clear = LEFT;
1474
+ }
1475
+
1476
+ if (BROWSER.IE === 6) {
1477
+ kid.style.display = "inline";
1478
+ }
1479
+ }
1480
+ }
1481
+
1482
+ switch (params.orient) {
1483
+ case VERTICAL :
1484
+ case BLOCK_AXIS:
1485
+ self.props = high;
1486
+ self.anti = wide;
1487
+ break;
1488
+
1489
+ default :
1490
+ self.props = wide;
1491
+ self.anti = high;
1492
+ break;
1493
+ }
1494
+ },
1495
+
1496
+ boxOrdinalGroup : function (target, children, params) {
1497
+ var organizeChildren,
1498
+ matrix;
1499
+
1500
+ if (!children.length) {
1501
+ return;
1502
+ }
1503
+
1504
+ organizeChildren = function (matrix) {
1505
+ var keys = matrix.keys,
1506
+ iterator = params.reversed ? keys : keys.reverse(),
1507
+ i, j, key, k, l, kid;
1508
+
1509
+ for (i = 0, j = iterator.length; i < j; i++) {
1510
+ key = iterator[i];
1511
+
1512
+ for (k = 0, l = children.length; k < l; k++) {
1513
+ kid = children[k];
1514
+
1515
+ if (key === kid.getAttribute("data-ordinal-group")) {
1516
+ target.appendChild(kid);
1517
+ }
1518
+ }
1519
+ }
1520
+ };
1521
+
1522
+ matrix = createMatchMatrix(params.children, children, TRUE);
1523
+
1524
+ if (matrix.keys.length > 1) {
1525
+ organizeChildren(matrix);
1526
+ }
1527
+ },
1528
+
1529
+ boxFlex : function (target, children, params) {
1530
+ var self = this,
1531
+ testForRestrictiveProperties,
1532
+ findTotalWhitespace,
1533
+ distributeRatio,
1534
+ matrix,
1535
+ restrict,
1536
+ whitespace,
1537
+ distro;
1538
+
1539
+ if (!children.length) {
1540
+ return;
1541
+ }
1542
+
1543
+ testForRestrictiveProperties = function (matrix) {
1544
+ var flexers = matrix.groups,
1545
+ keys = matrix.keys,
1546
+ max, i, j, key,
1547
+ k, l, x, m, n, rule;
1548
+
1549
+ for (i = 0, j = keys.length; i < j; i++) {
1550
+ key = keys[i];
1551
+
1552
+ for (k = 0, l = flexers[key].length; k < l; k++) {
1553
+ x = flexers[key][k];
1554
+ max = NULL;
1555
+
1556
+ for (m = 0, n = x.properties.length; m < n; m++) {
1557
+ rule = x.properties[m];
1558
+
1559
+ if ((RESTRICTIVE_PROPERTIES).test(rule.property)) {
1560
+ max = parseFloat(rule.value);
1561
+ }
1562
+ }
1563
+
1564
+ if (!max || x.match[self.props.out] > max) {
1565
+ appendPixelValue(x.match, self.props.pos, NULL);
1566
+ }
1567
+
1568
+ }
1569
+ }
1570
+ };
1571
+
1572
+ findTotalWhitespace = function (matrix) {
1573
+ var groupDimension = 0,
1574
+ whitespace,
1575
+ ration,
1576
+ i, j, kid,
1577
+ k, l, pad;
1578
+
1579
+ for (i = 0, j = children.length; i < j; i++) {
1580
+ kid = children[i];
1581
+
1582
+ groupDimension += getComputedStyle(kid, self.props.dim, TRUE);
1583
+
1584
+ for (k = 0, l = self.props.pad.length; k < l; k++) {
1585
+ pad = self.props.pad[k];
1586
+
1587
+ groupDimension += getComputedStyle(kid, pad, TRUE);
1588
+ }
1589
+
1590
+ groupDimension += getComputedStyle(kid, self.props.pos, TRUE);
1591
+ groupDimension += getComputedStyle(kid, self.props.opp, TRUE);
1592
+ }
1593
+
1594
+ whitespace = target[self.props.out] - groupDimension;
1595
+
1596
+ for (i = 0, j = self.props.pad.length; i < j; i++) {
1597
+ pad = self.props.pad[i];
1598
+ whitespace -= getComputedStyle(target, pad, TRUE);
1599
+ }
1600
+
1601
+ ration = (whitespace / matrix.total);
1602
+
1603
+ return {
1604
+ whitespace : whitespace,
1605
+ ration : ration
1606
+ };
1607
+ };
1608
+
1609
+ distributeRatio = function (matrix, whitespace) {
1610
+ var flexers = matrix.groups,
1611
+ keys = matrix.keys,
1612
+ flex, specificity,
1613
+ ration = whitespace.ration,
1614
+ widthRation, trueDim, newDimension,
1615
+ i, j, key, k, l, x;
1616
+
1617
+ for (i = 0, j = keys.length; i < j; i++) {
1618
+ key = keys[i];
1619
+ widthRation = (ration * key);
1620
+
1621
+ for (k = 0, l = flexers[key].length; k < l; k++) {
1622
+ x = flexers[key][k];
1623
+
1624
+ if (x.match) {
1625
+ flex = x.match.getAttribute("data-flex");
1626
+ specificity = x.match.getAttribute("data-specificity");
1627
+
1628
+ if (!flex || (specificity <= x.flexSpecificity)) {
1629
+ x.match.setAttribute("data-flex", key);
1630
+ x.match.setAttribute("data-specificity", x.flexSpecificity);
1631
+
1632
+ trueDim = getComputedStyle(x.match, self.props.dim, TRUE);
1633
+ newDimension = Math.max(0, (trueDim + widthRation));
1634
+ appendPixelValue(x.match, self.props.dim, newDimension);
1635
+ }
1636
+ }
1637
+ }
1638
+ }
1639
+ };
1640
+
1641
+ matrix = createMatchMatrix(params.children, children, NULL);
1642
+
1643
+ if (matrix.total) {
1644
+ params.hasFlex = TRUE;
1645
+
1646
+ restrict = testForRestrictiveProperties(matrix);
1647
+ whitespace = findTotalWhitespace(matrix);
1648
+
1649
+ // Distribute the calculated ratios among the children
1650
+ distro = distributeRatio(matrix, whitespace);
1651
+ }
1652
+ },
1653
+
1654
+ boxAlign : function (target, children, params) {
1655
+ var self = this,
1656
+ targetDimension,
1657
+ kidDimension,
1658
+ flexCheck = parentFlex(target),
1659
+ i, j, pad, k, l, kid;
1660
+
1661
+ if (!SUPPORT && !flexCheck.flex && (params.orient === VERTICAL || params.orient === BLOCK_AXIS)) {
1662
+ if (!dimensionValues(target, self.anti.dim)) {
1663
+ appendPixelValue(target, self.anti.dim, NULL);
1664
+ }
1665
+ appendPixelValue(children, self.anti.dim, NULL);
1666
+ }
1667
+
1668
+ // Remove padding / border from target dimension
1669
+ targetDimension = target[self.anti.out];
1670
+
1671
+ for (i = 0, j = self.anti.pad.length; i < j; i++) {
1672
+ pad = self.anti.pad[i];
1673
+ targetDimension -= getComputedStyle(target, pad, TRUE);
1674
+ }
1675
+
1676
+ switch (params.align) {
1677
+ case "start" :
1678
+ break;
1679
+
1680
+ case "end" :
1681
+ for (i = 0, j = children.length; i < j; i++) {
1682
+ kid = children[i];
1683
+
1684
+ kidDimension = targetDimension - kid[self.anti.out];
1685
+ kidDimension -= getComputedStyle(kid, self.anti.opp, TRUE);
1686
+ appendPixelValue(kid, self.anti.pos, kidDimension);
1687
+ }
1688
+ break;
1689
+
1690
+ case "center" :
1691
+ for (i = 0, j = children.length; i < j; i++) {
1692
+ kid = children[i];
1693
+
1694
+ kidDimension = (targetDimension - kid[self.anti.out]) / 2;
1695
+ appendPixelValue(kid, self.anti.pos, kidDimension);
1696
+ }
1697
+ break;
1698
+
1699
+ default :
1700
+ for (i = 0, j = children.length; i < j; i++) {
1701
+ kid = children[i];
1702
+
1703
+ switch (kid.nodeName.toLowerCase()) {
1704
+ case "button" :
1705
+ case "input" :
1706
+ case "select" :
1707
+ break;
1708
+
1709
+ default :
1710
+ var subtract = 0;
1711
+
1712
+ for (k = 0, l = self.anti.pad.length; k < l; k++) {
1713
+ pad = self.anti.pad[k];
1714
+
1715
+ subtract += getComputedStyle(kid, pad, TRUE);
1716
+ subtract += getComputedStyle(target, pad, TRUE);
1717
+ }
1718
+
1719
+ kid.style[self.anti.dim] = "100%";
1720
+ kidDimension = kid[self.anti.out] - subtract;
1721
+ appendPixelValue(kid, self.anti.dim, NULL);
1722
+
1723
+ kidDimension = targetDimension;
1724
+ kidDimension -= getComputedStyle(kid, self.anti.pos, TRUE);
1725
+
1726
+ for (k = 0, l = self.anti.pad.length; k < l; k++) {
1727
+ pad = self.anti.pad[k];
1728
+
1729
+ kidDimension -= getComputedStyle(kid, pad, TRUE);
1730
+ }
1731
+
1732
+ kidDimension -= getComputedStyle(kid, self.anti.opp, TRUE);
1733
+ kidDimension = Math.max(0, kidDimension);
1734
+
1735
+ appendPixelValue(kid, self.anti.dim, kidDimension);
1736
+ break;
1737
+ }
1738
+ }
1739
+ break;
1740
+ }
1741
+ },
1742
+
1743
+ boxPack : function (target, children, params) {
1744
+ var self = this,
1745
+ groupDimension = 0,
1746
+ firstComputedMargin = 0,
1747
+ targetPadding = 0,
1748
+ totalDimension,
1749
+ fractionedDimension,
1750
+ currentDimension,
1751
+ remainder,
1752
+ length = children.length - 1,
1753
+ kid, i, j, value, pad;
1754
+
1755
+ for (i = 0, j = children.length; i < j; i++) {
1756
+ kid = children[i];
1757
+
1758
+ groupDimension += kid[self.props.out];
1759
+ groupDimension += getComputedStyle(kid, self.props.pos, TRUE);
1760
+ groupDimension += getComputedStyle(kid, self.props.opp, TRUE);
1761
+ }
1762
+
1763
+ firstComputedMargin = getComputedStyle(children[0], self.props.pos, TRUE);
1764
+ totalDimension = target[self.props.out] - groupDimension;
1765
+
1766
+ // Remove padding / border from target dimension
1767
+ for (i = 0, j = self.props.pad.length; i < j; i++) {
1768
+ pad = self.props.pad[i];
1769
+ totalDimension -= getComputedStyle(target, pad, TRUE);
1770
+ }
1771
+
1772
+ // If totalDimension is less than 0, we have a problem...
1773
+ if (totalDimension < 0) {
1774
+ totalDimension = Math.max(0, totalDimension);
1775
+ }
1776
+
1777
+ switch (params.pack) {
1778
+ case "end" :
1779
+ appendPixelValue(children[0], self.props.pos, targetPadding + firstComputedMargin + totalDimension);
1780
+ break;
1781
+
1782
+ case "center" :
1783
+ if (targetPadding) {
1784
+ targetPadding /= 2;
1785
+ }
1786
+
1787
+ appendPixelValue(children[0], self.props.pos, targetPadding + firstComputedMargin + Math.floor(totalDimension / 2));
1788
+ break;
1789
+
1790
+ case "justify" :
1791
+ fractionedDimension = Math.floor((targetPadding + totalDimension) / length);
1792
+ remainder = (fractionedDimension * length) - totalDimension;
1793
+
1794
+ i = children.length - 1;
1795
+
1796
+ while (i) {
1797
+ kid = children[i];
1798
+ currentDimension = fractionedDimension;
1799
+
1800
+ if (remainder) {
1801
+ currentDimension++;
1802
+ remainder++;
1803
+ }
1804
+
1805
+ value = getComputedStyle(kid, self.props.pos, TRUE) + currentDimension;
1806
+ appendPixelValue(kid, self.props.pos, value);
1807
+
1808
+ i--;
1809
+ }
1810
+
1811
+ break;
1812
+ }
1813
+
1814
+ target.style.overflow = "";
1815
+ }
1816
+ },
1817
+
1818
+ setup : function (target, children, params) {
1819
+ var self = this, matrix, flexCheck,
1820
+ key, func;
1821
+
1822
+ if (!target || !children || !params) {
1823
+ return;
1824
+ }
1825
+
1826
+ if (SUPPORT && SUPPORT.partialSupport) {
1827
+ matrix = createMatchMatrix(params.children, children, NULL);
1828
+ flexCheck = parentFlex(target);
1829
+ children = sanitizeChildren(target, target.childNodes);
1830
+
1831
+ self.properties.boxOrient.call(self, target, children, params);
1832
+
1833
+ if (!matrix.total || !LIBRARY(params.nested).length) {
1834
+ if ((params.align === "stretch") && !SUPPORT.boxAlignStretch && (!flexCheck.nested || !flexCheck.flex)) {
1835
+ self.properties.boxAlign.call(self, target, children, params);
1836
+ }
1837
+
1838
+ if ((params.pack === "justify") && !SUPPORT.boxPackJustify && !matrix.total) {
1839
+ self.properties.boxPack.call(self, target, children, params);
1840
+ }
1841
+ }
1842
+ } else if (!SUPPORT) {
1843
+ for (key in self.properties) {
1844
+ if (self.properties.hasOwnProperty(key)) {
1845
+ func = self.properties[key];
1846
+ func.call(self, target, sanitizeChildren(target, target.childNodes), params);
1847
+ }
1848
+ }
1849
+ }
1850
+ },
1851
+
1852
+ trackDOM : function (params) {
1853
+ attachResizeListener(this, params);
1854
+ },
1855
+
1856
+ updateModel : function (params) {
1857
+ var self = this,
1858
+ target = params.target,
1859
+ children = params.nodes;
1860
+
1861
+ // Null properties
1862
+ cleanPositioningProperties(children);
1863
+
1864
+ if (params.flexMatrix || params.ordinalMatrix) {
1865
+ params = updateChildValues(params);
1866
+ }
1867
+
1868
+ self.setup(target, children, params);
1869
+ self.bubbleUp(target, params);
1870
+ },
1871
+
1872
+ renderModel : function (params) {
1873
+ var self = this,
1874
+ target = params.target,
1875
+ nodes = target.childNodes;
1876
+
1877
+ // Sanity check.
1878
+ if (!target.length && !nodes) {
1879
+ return false;
1880
+ }
1881
+
1882
+ params = ensureStructuralIntegrity(params, this);
1883
+
1884
+ // Setup properties
1885
+ self.updateModel(params);
1886
+
1887
+ // Resize / DOM Polling Events
1888
+ // Delay for an instant because IE6 is insane.
1889
+ win.setTimeout(function () {
1890
+ self.trackDOM(params);
1891
+ }, 0);
1892
+
1893
+ return self;
1894
+ },
1895
+
1896
+ bubbleUp : function (target, params) {
1897
+ var self = this, flex,
1898
+ parent = params.target.parentNode;
1899
+
1900
+ while (parent) {
1901
+ flex = FLEX_BOXES[parent.FLX_DOM_ID];
1902
+
1903
+ if (flex && flex.nodes) {
1904
+ cleanPositioningProperties(flex.nodes);
1905
+ self.setup(flex.target, flex.nodes, flex);
1906
+ }
1907
+
1908
+ parent = parent.parentNode;
1909
+ }
1910
+ }
1911
+ };
1912
+
1913
+ FLX.updateInstance = function (target, params) {
1914
+ var box, key;
1915
+
1916
+ if (target) {
1917
+ box = FLEX_BOXES[target.FLX_DOM_ID];
1918
+
1919
+ if (box && box._instance) {
1920
+ box._instance.updateModel(box);
1921
+ } else if (!box) {
1922
+ box = new FLX.box(params);
1923
+ }
1924
+ } else {
1925
+ for (key in FLEX_BOXES) {
1926
+ if (FLEX_BOXES.hasOwnProperty(key)) {
1927
+ box = FLEX_BOXES[key];
1928
+
1929
+ if (box && box._instance) {
1930
+ box._instance.updateModel(box);
1931
+ }
1932
+ }
1933
+ }
1934
+ }
1935
+ };
1936
+
1937
+ FLX.getInstance = function (target) {
1938
+ return FLEX_BOXES[target.FLX_DOM_ID];
1939
+ };
1940
+
1941
+ FLX.destroyInstance = function (target) {
1942
+ var box, destroy, i, j, x, key;
1943
+
1944
+ destroy = function (box) {
1945
+ box.target.FLX_DOM_ID = NULL;
1946
+ box.target.style.cssText = EMPTY_STRING;
1947
+
1948
+ for (i = 0, j = box.children.length; i < j; i++) {
1949
+ x = box.children[i];
1950
+ x.match.style.cssText = EMPTY_STRING;
1951
+ }
1952
+ };
1953
+
1954
+ if (target) {
1955
+ box = FLEX_BOXES[target.FLX_DOM_ID];
1956
+
1957
+ if (box) {
1958
+ destroy(box);
1959
+ }
1960
+ } else {
1961
+ for (key in FLEX_BOXES) {
1962
+ if (FLEX_BOXES.hasOwnProperty(key)) {
1963
+ destroy(FLEX_BOXES[key]);
1964
+ }
1965
+ }
1966
+
1967
+ FLEX_BOXES = [];
1968
+ }
1969
+ };
1970
+
1971
+ FLX.flexboxSupport = function () {
1972
+ var partialSupportGrid = {},
1973
+ height = 100,
1974
+ childHeight,
1975
+ dummy = doc.createElement("flxbox"),
1976
+ child = '<b style="margin: 0; padding: 0; display:block; width: 10px; height:' + (height / 2) + 'px"></b>',
1977
+ tests, result, key, value;
1978
+
1979
+ dummy.style.width = dummy.style.height = height + "px";
1980
+ dummy.innerHTML = (child + child + child);
1981
+
1982
+ appendProperty(dummy, "display", "box", NULL);
1983
+ appendProperty(dummy, "box-align", "stretch", TRUE);
1984
+ appendProperty(dummy, "box-pack", "justify", TRUE);
1985
+
1986
+ doc.body.appendChild(dummy);
1987
+ childHeight = dummy.firstChild.offsetHeight;
1988
+
1989
+ tests = {
1990
+ boxAlignStretch : function () {
1991
+ return (childHeight === 100);
1992
+ },
1993
+
1994
+ boxPackJustify : function () {
1995
+ var totalOffset = 0,
1996
+ i, j;
1997
+
1998
+ for (i = 0, j = dummy.childNodes.length; i < j; i++) {
1999
+ totalOffset += dummy.childNodes[i].offsetLeft;
2000
+ }
2001
+
2002
+ return (totalOffset === 135);
2003
+ }
2004
+ };
2005
+
2006
+ for (key in tests) {
2007
+ if (tests.hasOwnProperty(key)) {
2008
+ value = tests[key];
2009
+
2010
+ result = value();
2011
+
2012
+ if (!result) {
2013
+ partialSupportGrid.partialSupport = TRUE;
2014
+ }
2015
+
2016
+ partialSupportGrid[key] = result;
2017
+ }
2018
+ }
2019
+
2020
+ doc.body.removeChild(dummy);
2021
+ return ~ (dummy.style.display).indexOf("box") ? partialSupportGrid : FALSE;
2022
+ };
2023
+
2024
+ FLX.init = function () {
2025
+ FLX.flexboxSupported = SUPPORT = FLX.flexboxSupport();
2026
+
2027
+ if ((!SUPPORT || SUPPORT.partialSupport) && LIBRARY) {
2028
+ selectivizrEngine();
2029
+ }
2030
+ };
2031
+
2032
+ // Flexie Version
2033
+ FLX.version = "1.0.3";
2034
+
2035
+ // Load when the DOM is ready
2036
+ attachLoadMethod(FLX.init);
2037
+
2038
+ return FLX;
2039
+ }(this, document));