planeui.patch.ie9.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896
  1. /*!
  2. * PlaneUI v0.1.0
  3. * @file planeui.patch.ie9.js
  4. * @description The Modern HTML5 Cross-Device Responsive Front-end UI Framework.
  5. * @license MIT License
  6. * @author Pandao
  7. * {@link https://github.com/pandao/planeui}
  8. * @updateTime 2015-06-27
  9. */
  10. /*
  11. File: flexie.js
  12. About: Version
  13. 1.0.3
  14. Project: Flexie
  15. Description:
  16. Legacy support for the CSS3 Flexible Box Model
  17. License:
  18. The MIT License
  19. Copyright (c) 2010 Richard Herrera
  20. Permission is hereby granted, free of charge, to any person obtaining a copy
  21. of this software and associated documentation files (the "Software"), to deal
  22. in the Software without restriction, including without limitation the rights
  23. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  24. copies of the Software, and to permit persons to whom the Software is
  25. furnished to do so, subject to the following conditions:
  26. The above copyright notice and this permission notice shall be included in
  27. all copies or substantial portions of the Software.
  28. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  29. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  30. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  31. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  32. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  33. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  34. THE SOFTWARE.
  35. */
  36. /*
  37. Class: Flexie
  38. Scoped to the Flexie Global Namespace
  39. */
  40. /*jslint evil: true, regexp: false, plusplus: false */
  41. /*global window, document */
  42. var Flexie = (function (win, doc) {
  43. // Scope public properties
  44. var FLX = {},
  45. // Each Flexie-modified DOM node gets a unique identifier
  46. FLX_DOM_ID = 0,
  47. FLX_DOM_ATTR = "data-flexie-id",
  48. FLX_PARENT_ATTR = "data-flexie-parent",
  49. // Store support for flexbox
  50. SUPPORT,
  51. // Store reference to engine
  52. ENGINE,
  53. ENGINES = {
  54. "NW" : {
  55. s : "*.Dom.select"
  56. },
  57. "DOMAssistant" : {
  58. s : "*.$",
  59. m : "*.DOMReady"
  60. },
  61. "Prototype" : {
  62. s : "$$",
  63. m : "document.observe",
  64. p : "dom:loaded",
  65. c : "document"
  66. },
  67. "YAHOO" : {
  68. s : "*.util.Selector.query",
  69. m : "*.util.Event.onDOMReady",
  70. c : "*.util.Event"
  71. },
  72. "MooTools" : {
  73. s : "$$",
  74. m : "window.addEvent",
  75. p : "domready"
  76. },
  77. "Sizzle" : {
  78. s : "*"
  79. },
  80. "jQuery" : {
  81. s : "*",
  82. m : "*(document).ready"
  83. },
  84. "dojo" : {
  85. s : "*.query",
  86. m : "*.addOnLoad"
  87. }
  88. },
  89. // Store reference to library
  90. LIBRARY,
  91. // Regular Expressions
  92. PIXEL = /^-?\d+(?:px)?$/i,
  93. NUMBER = /^-?\d/,
  94. SIZES = /width|height|margin|padding|border/,
  95. MSIE = /(msie) ([\w.]+)/,
  96. WHITESPACE_CHARACTERS = /\t|\n|\r/g,
  97. RESTRICTIVE_PROPERTIES = /^max\-([a-z]+)/,
  98. PROTOCOL = /^https?:\/\//i,
  99. LEADINGTRIM = /^\s\s*/,
  100. TRAILINGTRIM = /\s\s*$/,
  101. ONLY_WHITESPACE = /^\s*$/,
  102. CSS_SELECTOR = /\s?(\#|\.|\[|\:(\:)?[^first\-(line|letter)|before|after]+)/g,
  103. // String constants
  104. EMPTY_STRING = "",
  105. SPACE_STRING = " ",
  106. PLACEHOLDER_STRING = "$1",
  107. PADDING_RIGHT = "paddingRight",
  108. PADDING_BOTTOM = "paddingBottom",
  109. PADDING_LEFT = "paddingLeft",
  110. PADDING_TOP = "paddingTop",
  111. BORDER_RIGHT = "borderRightWidth",
  112. BORDER_BOTTOM = "borderBottomWidth",
  113. BORDER_LEFT = "borderLeftWidth",
  114. BORDER_TOP = "borderTopWidth",
  115. HORIZONTAL = "horizontal",
  116. VERTICAL = "vertical",
  117. INLINE_AXIS = "inline-axis",
  118. BLOCK_AXIS = "block-axis",
  119. INHERIT = "inherit",
  120. LEFT = "left",
  121. END_MUSTACHE = "}",
  122. PREFIXES = " -o- -moz- -ms- -webkit- -khtml- ".split(SPACE_STRING),
  123. DEFAULTS = {
  124. orient : HORIZONTAL,
  125. align : "stretch",
  126. direction : INHERIT,
  127. pack : "start"
  128. },
  129. // Global reference objects
  130. FLEX_BOXES = [],
  131. POSSIBLE_FLEX_CHILDREN = [],
  132. DOM_ORDERED,
  133. RESIZE_LISTENER,
  134. // Minification optimizations
  135. TRUE = true,
  136. FALSE = false,
  137. NULL = null,
  138. UNDEFINED,
  139. // If IE, which version?
  140. BROWSER = {
  141. IE : (function () {
  142. var ie, ua = win.navigator.userAgent,
  143. match = (MSIE).exec(ua.toLowerCase());
  144. if (match) {
  145. ie = parseInt(match[2], 10);
  146. }
  147. return ie;
  148. }())
  149. },
  150. /*
  151. selectivizr v1.0.0 - (c) Keith Clark, freely distributable under the terms
  152. of the MIT license.
  153. selectivizr.com
  154. */
  155. selectivizrEngine;
  156. function trim (string) {
  157. if (string) {
  158. string = string.replace(LEADINGTRIM, EMPTY_STRING).replace(TRAILINGTRIM, EMPTY_STRING);
  159. }
  160. return string;
  161. }
  162. // Via jQuery 1.4.3
  163. // http://github.com/jquery/jquery/blob/master/src/core.js#L593
  164. function forEach(object, callback) {
  165. var name, i = 0, value,
  166. length = object ? object.length : UNDEFINED,
  167. isObj = length === UNDEFINED;
  168. if (isObj) {
  169. for (name in object) {
  170. if (object.hasOwnProperty(name)) {
  171. if (callback.call(object[name], name, object[name]) === FALSE) {
  172. break;
  173. }
  174. }
  175. }
  176. } else {
  177. for (value = object[0]; i < length && callback.call(value, i, value) !== FALSE; value = object[++i]) {
  178. continue;
  179. }
  180. }
  181. }
  182. // --[ determineSelectorMethod() ]--------------------------------------
  183. // walks through the engines object testing for an suitable
  184. // selector engine.
  185. // Moving outside Selectivizr scope because detection is needed before running selectivizrEngine
  186. function determineSelectorMethod() {
  187. // compatiable selector engines in order of CSS3 support
  188. var engines = ENGINES, method;
  189. forEach(engines, function (engine, obj) {
  190. if (win[engine] && !method) {
  191. method = eval(obj.s.replace("*", engine));
  192. if (method) {
  193. ENGINE = engine;
  194. return false;
  195. }
  196. }
  197. });
  198. return method;
  199. }
  200. // Event handler for onload/onresize events
  201. function addEvent(type, func) {
  202. type = "on" + type;
  203. var oldevent = win[type];
  204. if (typeof win[type] !== "function") {
  205. win[type] = func;
  206. } else {
  207. win[type] = function () {
  208. if (oldevent) {
  209. oldevent();
  210. }
  211. func();
  212. };
  213. }
  214. }
  215. function attachLoadMethod(handler) {
  216. if (!ENGINE) {
  217. LIBRARY = determineSelectorMethod();
  218. }
  219. // compatiable selector engines in order of CSS3 support
  220. var engines = ENGINES,
  221. method, caller, args;
  222. forEach(engines, function (engine, obj) {
  223. if (win[engine] && !method && obj.m) {
  224. method = eval(obj.m.replace("*", engine));
  225. caller = obj.c ? eval(obj.c.replace("*", engine)) : win;
  226. args = [];
  227. if (method && caller) {
  228. if (obj.p) {
  229. args.push(obj.p);
  230. }
  231. args.push(handler);
  232. method.apply(caller, args);
  233. return false;
  234. }
  235. }
  236. });
  237. if (!method) {
  238. addEvent("load", handler);
  239. }
  240. }
  241. function buildSelector (node) {
  242. var selector = node.nodeName.toLowerCase();
  243. if (node.id) {
  244. selector += "#" + node.id;
  245. } else if (node.FLX_DOM_ID) {
  246. selector += "[" + FLX_DOM_ATTR + "='" + node.FLX_DOM_ID + "']";
  247. }
  248. return selector;
  249. }
  250. function setFlexieId (node) {
  251. if (!node.FLX_DOM_ID) {
  252. FLX_DOM_ID = (FLX_DOM_ID + 1);
  253. node.FLX_DOM_ID = FLX_DOM_ID;
  254. node.setAttribute(FLX_DOM_ATTR, node.FLX_DOM_ID);
  255. }
  256. }
  257. function buildSelectorTree(text) {
  258. var rules = [], ruletext, rule,
  259. match, selector, proptext, splitprop, properties;
  260. // Tabs, Returns
  261. text = text.replace(WHITESPACE_CHARACTERS, EMPTY_STRING);
  262. // Leading / Trailing Whitespace
  263. text = text.replace(/\s?(\{|\:|\})\s?/g, PLACEHOLDER_STRING);
  264. ruletext = text.split(END_MUSTACHE);
  265. forEach(ruletext, function (i, text) {
  266. if (text) {
  267. rule = [text, END_MUSTACHE].join(EMPTY_STRING);
  268. match = (/(\@media[^\{]+\{)?(.*)\{(.*)\}/).exec(rule);
  269. if (match && match[3]) {
  270. selector = match[2];
  271. proptext = match[3].split(";");
  272. properties = [];
  273. forEach(proptext, function (i, x) {
  274. splitprop = x.split(":");
  275. if (splitprop.length && splitprop[1]) {
  276. properties.push({
  277. property : splitprop[0],
  278. value : splitprop[1]
  279. });
  280. }
  281. });
  282. if (selector && properties.length) {
  283. rules.push({
  284. selector : selector,
  285. properties : properties
  286. });
  287. }
  288. }
  289. }
  290. });
  291. return rules;
  292. }
  293. function findFlexboxElements(rules) {
  294. var selectors, properties,
  295. property, value, shortProp,
  296. selectorSplit = /\s?,\s?/,
  297. createUniqueObject, addRules,
  298. uniqueChildren = {}, uniqueBoxes = {};
  299. createUniqueObject = function (selector, rules, prop, value) {
  300. var unique = {
  301. selector : trim(selector),
  302. properties : []
  303. };
  304. forEach(rules.properties, function (i, prop) {
  305. unique.properties.push({
  306. property : trim(prop.property),
  307. value : trim(prop.value)
  308. });
  309. });
  310. if (prop && value) {
  311. unique[prop] = value;
  312. }
  313. return unique;
  314. };
  315. addRules = function (selector, rules, prop, value) {
  316. var box = (prop && value) ? uniqueChildren[selector] : uniqueBoxes[selector],
  317. exists;
  318. if (box) {
  319. forEach(rules.properties, function (i, rule) {
  320. forEach(box.properties, function (j, x) {
  321. if (rule.property === x.property) {
  322. exists = j;
  323. return false;
  324. }
  325. });
  326. if (exists) {
  327. box.properties[exists] = rule;
  328. } else {
  329. box.properties.push(rule);
  330. }
  331. });
  332. if (prop && value) {
  333. box[prop] = value;
  334. }
  335. } else {
  336. if (prop && value) {
  337. uniqueChildren[selector] = createUniqueObject(selector, rules, prop, value);
  338. } else {
  339. uniqueBoxes[selector] = createUniqueObject(selector, rules, NULL, NULL);
  340. }
  341. }
  342. };
  343. forEach(rules, function (i, rule) {
  344. selectors = trim(rule.selector).replace(selectorSplit, ",").split(selectorSplit);
  345. forEach(selectors, function (i, selector) {
  346. selector = trim(selector);
  347. properties = rule.properties;
  348. forEach(properties, function (i, prop) {
  349. property = trim(prop.property);
  350. value = trim(prop.value);
  351. if (property) {
  352. shortProp = property.replace("box-", EMPTY_STRING);
  353. switch (shortProp) {
  354. case "display" :
  355. if (value === "box") {
  356. addRules(selector, rule, NULL, NULL);
  357. }
  358. break;
  359. case "orient" :
  360. case "align" :
  361. case "direction" :
  362. case "pack" :
  363. addRules(selector, rule, NULL, NULL);
  364. break;
  365. case "flex" :
  366. case "flex-group" :
  367. case "ordinal-group" :
  368. addRules(selector, rule, shortProp, value);
  369. break;
  370. }
  371. }
  372. });
  373. });
  374. });
  375. forEach(uniqueBoxes, function (key, box) {
  376. FLEX_BOXES.push(box);
  377. });
  378. forEach(uniqueChildren, function (key, child) {
  379. POSSIBLE_FLEX_CHILDREN.push(child);
  380. });
  381. return {
  382. boxes : FLEX_BOXES,
  383. children : POSSIBLE_FLEX_CHILDREN
  384. };
  385. }
  386. function matchFlexChildren(parent, lib, possibleChildren) {
  387. var caller, unique, matches = [];
  388. forEach(possibleChildren, function (i, child) {
  389. if (child.selector) {
  390. caller = lib(child.selector);
  391. caller = caller[0] ? caller : [caller];
  392. if (caller[0]) {
  393. forEach(caller, function (i, node) {
  394. if (node.nodeName !== UNDEFINED) {
  395. switch (node.nodeName.toLowerCase()) {
  396. case "script" :
  397. case "style" :
  398. case "link" :
  399. break;
  400. default :
  401. if (node.parentNode === parent) {
  402. // Flag each unique node with FLX_DOM_ID
  403. setFlexieId(node);
  404. unique = {};
  405. forEach(child, function (key) {
  406. unique[key] = child[key];
  407. });
  408. unique.match = node;
  409. matches.push(unique);
  410. }
  411. break;
  412. }
  413. }
  414. });
  415. }
  416. } else {
  417. // Flag each unique node with FLX_DOM_ID
  418. setFlexieId(child);
  419. matches.push({
  420. match : child,
  421. selector : buildSelector(child)
  422. });
  423. }
  424. });
  425. return matches;
  426. }
  427. function getParams(params) {
  428. forEach(params, function (key, value) {
  429. params[key] = value || DEFAULTS[key];
  430. });
  431. return params;
  432. }
  433. function buildFlexieCall(flexers) {
  434. var selector, properties, property, value, shortProp,
  435. display, orient, align, direction, pack,
  436. lib, caller, children,
  437. box, params, flexboxes = {},
  438. match, childMatch, nestedFlexboxes,
  439. flexieParentSelector = "[" + FLX_PARENT_ATTR + "]";
  440. // No boxflex? No dice.
  441. if (!flexers) {
  442. return;
  443. }
  444. forEach(flexers.boxes, function (i, flex) {
  445. flex.selector = trim(flex.selector);
  446. selector = flex.selector;
  447. properties = flex.properties;
  448. display = orient = align = direction = pack = NULL;
  449. forEach(properties, function (i, prop) {
  450. property = trim(prop.property);
  451. value = trim(prop.value);
  452. if (property) {
  453. shortProp = property.replace("box-", EMPTY_STRING);
  454. switch (shortProp) {
  455. case "display" :
  456. if (value === "box") {
  457. display = value;
  458. }
  459. break;
  460. case "orient" :
  461. orient = value;
  462. break;
  463. case "align" :
  464. align = value;
  465. break;
  466. case "direction" :
  467. direction = value;
  468. break;
  469. case "pack" :
  470. pack = value;
  471. break;
  472. }
  473. }
  474. });
  475. // Determine library
  476. lib = LIBRARY;
  477. // Call it.
  478. caller = lib(flex.selector);
  479. // In an array?
  480. caller = caller[0] ? caller : [caller];
  481. forEach(caller, function (i, target) {
  482. // If is DOM object
  483. if (target.nodeType) {
  484. // Flag each unique node with FLX_DOM_ID
  485. setFlexieId(target);
  486. // Find possible child node matches
  487. children = matchFlexChildren(target, lib, flexers.children);
  488. // Find any nested flexbox elements
  489. nestedFlexboxes = selector + " " + flexieParentSelector;
  490. // Make sure there is some value associated with box properties
  491. params = {
  492. target : target,
  493. selector : selector,
  494. properties : properties,
  495. children : children,
  496. display : display,
  497. orient : orient,
  498. align : align,
  499. direction: direction,
  500. pack : pack,
  501. nested : nestedFlexboxes
  502. };
  503. match = flexboxes[target.FLX_DOM_ID];
  504. if (match) {
  505. forEach(params, function (key, value) {
  506. switch (key) {
  507. case "selector" :
  508. if (value && !(new RegExp(value).test(match[key]))) {
  509. match[key] += ", " + value;
  510. }
  511. break;
  512. case "children" :
  513. forEach(params[key], function (k, child) {
  514. childMatch = FALSE;
  515. forEach(match[key], function (key, existing) {
  516. if (child.match.FLX_DOM_ID === existing.match.FLX_DOM_ID) {
  517. childMatch = TRUE;
  518. }
  519. });
  520. if (!childMatch) {
  521. match[key].push(child);
  522. }
  523. });
  524. break;
  525. default :
  526. if (value) {
  527. match[key] = value;
  528. }
  529. break;
  530. }
  531. });
  532. } else {
  533. flexboxes[target.FLX_DOM_ID] = getParams(params);
  534. flexboxes[target.FLX_DOM_ID].target.setAttribute(FLX_PARENT_ATTR, TRUE);
  535. }
  536. }
  537. });
  538. });
  539. DOM_ORDERED = LIBRARY(flexieParentSelector);
  540. FLEX_BOXES = {};
  541. forEach(DOM_ORDERED, function (i, target) {
  542. FLEX_BOXES[target.FLX_DOM_ID] = flexboxes[target.FLX_DOM_ID];
  543. });
  544. // Loop through each match, initialize constructor
  545. forEach(FLEX_BOXES, function (key, flex) {
  546. // One final check to ensure each flexbox has a display property
  547. if (flex.display === "box") {
  548. // Constructor
  549. box = new FLX.box(flex);
  550. }
  551. });
  552. }
  553. function calcPx(element, props, dir) {
  554. var dim = dir.replace(dir.charAt(0), dir.charAt(0).toUpperCase()),
  555. value = element["offset" + dim] || 0;
  556. if (value) {
  557. forEach(props, function (i, prop) {
  558. prop = parseFloat(element.currentStyle[prop]);
  559. if (!isNaN(prop)) {
  560. value -= prop;
  561. }
  562. });
  563. }
  564. return value;
  565. }
  566. function getTrueValue(element, name) {
  567. var left, rsLeft,
  568. ret = element.currentStyle && element.currentStyle[name],
  569. style = element.style;
  570. if (!PIXEL.test(ret) && NUMBER.test(ret)) {
  571. // Remember the original values
  572. left = style.left;
  573. rsLeft = element.runtimeStyle.left;
  574. // Put in the new values to get a computed value out
  575. element.runtimeStyle.left = element.currentStyle.left;
  576. style.left = ret || 0;
  577. ret = style.pixelLeft + "px";
  578. // Revert the changed values
  579. style.left = left || 0;
  580. element.runtimeStyle.left = rsLeft;
  581. }
  582. return ret;
  583. }
  584. function unAuto(element, prop, name) {
  585. var props;
  586. switch (name) {
  587. case "width" :
  588. props = [PADDING_LEFT, PADDING_RIGHT, BORDER_LEFT, BORDER_RIGHT];
  589. prop = calcPx(element, props, name);
  590. break;
  591. case "height" :
  592. props = [PADDING_TOP, PADDING_BOTTOM, BORDER_TOP, BORDER_BOTTOM];
  593. prop = calcPx(element, props, name);
  594. break;
  595. default :
  596. prop = getTrueValue(element, name);
  597. break;
  598. }
  599. return prop;
  600. }
  601. function getPixelValue(element, prop, name) {
  602. if (PIXEL.test(prop)) {
  603. return prop;
  604. }
  605. // if property is auto, do some messy appending
  606. if (prop === "auto" || prop === "medium") {
  607. prop = unAuto(element, prop, name);
  608. } else {
  609. prop = getTrueValue(element, name);
  610. }
  611. return prop;
  612. }
  613. function getComputedStyle(element, property, returnAsInt) {
  614. var value;
  615. if (element === UNDEFINED) {
  616. return;
  617. }
  618. if (win.getComputedStyle) {
  619. value = win.getComputedStyle(element, NULL)[property];
  620. } else {
  621. if (SIZES.test(property)) {
  622. value = getPixelValue(element, (element && element.currentStyle) ? element.currentStyle[property] : 0, property);
  623. } else {
  624. value = element.currentStyle[property];
  625. }
  626. }
  627. if (returnAsInt) {
  628. value = parseInt(value, 10);
  629. if (isNaN(value)) {
  630. value = 0;
  631. }
  632. }
  633. return value;
  634. }
  635. function clientWidth(element) {
  636. return element.innerWidth || element.clientWidth;
  637. }
  638. function clientHeight(element) {
  639. return element.innerHeight || element.clientHeight;
  640. }
  641. function appendProperty(target, prop, value, prefixName) {
  642. var cssText = [];
  643. forEach(PREFIXES, function (i, prefix) {
  644. cssText.push((prefixName ? prefix : EMPTY_STRING) + prop + ":" + (!prefixName ? prefix : EMPTY_STRING) + value);
  645. });
  646. target.style.cssText += cssText.join(";");
  647. return target;
  648. }
  649. function appendPixelValue(target, prop, value) {
  650. var targets = target && target[0] ? target : [target];
  651. forEach(targets, function (i, target) {
  652. if (target && target.style) {
  653. target.style[prop] = (value ? (value + "px") : EMPTY_STRING);
  654. }
  655. });
  656. }
  657. function calculateSpecificity (selector) {
  658. var selectorGrid, matrix, total;
  659. selectorGrid = selector.replace(CSS_SELECTOR, function (e, f) {
  660. return "%" + f;
  661. }).replace(/\s|\>|\+|\~/g, "%").split(/%/g);
  662. matrix = {
  663. _id : 100,
  664. _class : 10,
  665. _tag : 1
  666. };
  667. // Start with rule index position
  668. total = 0;
  669. // Add each selector value to total.
  670. forEach(selectorGrid, function (i, chunk) {
  671. if ((/#/).test(chunk)) {
  672. total += matrix._id;
  673. } else if ((/\.|\[|\:/).test(chunk)) {
  674. total += matrix._class;
  675. } else if ((/[a-zA-Z]+/).test(chunk)) {
  676. total += matrix._tag;
  677. }
  678. });
  679. return total;
  680. }
  681. function filterDuplicates (matches, children, type) {
  682. var filteredMatches = [], exists,
  683. spec = (type ? "ordinal" : "flex") + "Specificity";
  684. forEach(matches, function (i, x) {
  685. if ((!type && x.flex) || (type && x["ordinal-group"])) {
  686. x[spec] = x[spec] || calculateSpecificity(x.selector);
  687. exists = FALSE;
  688. forEach(filteredMatches, function (j, f) {
  689. if (f.match === x.match) {
  690. if (f[spec] < x[spec]) {
  691. filteredMatches[j] = x;
  692. }
  693. exists = TRUE;
  694. return FALSE;
  695. }
  696. });
  697. if (!exists) {
  698. filteredMatches.push(x);
  699. }
  700. }
  701. });
  702. return filteredMatches;
  703. }
  704. function createMatchMatrix(matches, children, type) {
  705. var groups = {}, keys = [], totalRatio = 0,
  706. group, order = "ordinal-group",
  707. BoxOrdinalAttr = "data-" + order;
  708. // Filter dupes
  709. matches = filterDuplicates(matches, children, type);
  710. forEach(children, function (i, kid) {
  711. forEach(matches, function (j, x) {
  712. if (type) {
  713. // If no value declared, it's the default.
  714. group = x[order] || "1";
  715. if (x.match === kid) {
  716. x.match.setAttribute(BoxOrdinalAttr, group);
  717. groups[group] = groups[group] || [];
  718. groups[group].push(x);
  719. }
  720. } else {
  721. // If no value declared, it's the default.
  722. group = x.flex || "0";
  723. if (x.match === kid && (!x[group] || (x[group] && parseInt(x[group], 10) <= 1))) {
  724. totalRatio += parseInt(group, 10);
  725. groups[group] = groups[group] || [];
  726. groups[group].push(x);
  727. }
  728. }
  729. });
  730. if (type && !kid.getAttribute(BoxOrdinalAttr)) {
  731. group = "1";
  732. kid.setAttribute(BoxOrdinalAttr, group);
  733. groups[group] = groups[group] || [];
  734. groups[group].push({
  735. match : kid
  736. });
  737. }
  738. });
  739. forEach(groups, function (key) {
  740. keys.push(key);
  741. });
  742. keys.sort(function (a, b) {
  743. return b - a;
  744. });
  745. return {
  746. keys : keys,
  747. groups : groups,
  748. total : totalRatio
  749. };
  750. }
  751. function attachResizeListener(construct, params) {
  752. if (!RESIZE_LISTENER) {
  753. var storedWidth, storedHeight,
  754. currentWidth, currentHeight,
  755. docBody = doc.body,
  756. docEl = doc.documentElement,
  757. resizeTimer,
  758. innerWidth = "innerWidth", innerHeight = "innerHeight",
  759. clientWidth = "clientWidth", clientHeight = "clientHeight";
  760. addEvent("resize", function () {
  761. if (resizeTimer) {
  762. window.clearTimeout(resizeTimer);
  763. }
  764. resizeTimer = window.setTimeout(function () {
  765. currentWidth = win[innerWidth] || docEl[innerWidth] || docEl[clientWidth] || docBody[clientWidth];
  766. currentHeight = win[innerHeight] || docEl[innerHeight] || docEl[clientHeight] || docBody[clientHeight];
  767. if (storedWidth !== currentWidth || storedHeight !== currentHeight) {
  768. FLX.updateInstance(NULL, NULL);
  769. storedWidth = currentWidth;
  770. storedHeight = currentHeight;
  771. }
  772. }, 250);
  773. });
  774. RESIZE_LISTENER = TRUE;
  775. }
  776. }
  777. function cleanPositioningProperties (children) {
  778. var w, h;
  779. forEach(children, function (i, kid) {
  780. w = kid.style.width;
  781. h = kid.style.height;
  782. kid.style.cssText = EMPTY_STRING;
  783. kid.style.width = w;
  784. kid.style.height = h;
  785. });
  786. }
  787. function sanitizeChildren (target, nodes) {
  788. var children = [], node, i, j;
  789. for (i = 0, j = nodes.length; i < j; i++) {
  790. node = nodes[i];
  791. if (node) {
  792. switch (node.nodeName.toLowerCase()) {
  793. case "script" :
  794. case "style" :
  795. case "link" :
  796. break;
  797. default :
  798. if (node.nodeType === 1) {
  799. children.push(node);
  800. } else if ((node.nodeType === 3) && (node.isElementContentWhitespace || (ONLY_WHITESPACE).test(node.data))) {
  801. target.removeChild(node);
  802. i--;
  803. }
  804. break;
  805. }
  806. }
  807. }
  808. return children;
  809. }
  810. function parentFlex (target) {
  811. var totalFlex = 0,
  812. parent = target.parentNode,
  813. obj,
  814. matrix,
  815. isNested;
  816. while (parent.FLX_DOM_ID) {
  817. obj = FLEX_BOXES[parent.FLX_DOM_ID];
  818. matrix = createMatchMatrix(obj.children, sanitizeChildren(parent, parent.childNodes), NULL);
  819. totalFlex += matrix.total;
  820. isNested = TRUE;
  821. parent = parent.parentNode;
  822. }
  823. return {
  824. nested : isNested,
  825. flex : totalFlex
  826. };
  827. }
  828. function dimensionValues (target, prop) {
  829. var parent = target.parentNode,
  830. obj,
  831. dimension;
  832. if (parent.FLX_DOM_ID) {
  833. obj = FLEX_BOXES[parent.FLX_DOM_ID];
  834. forEach(obj.properties, function (i, rule) {
  835. if ((new RegExp(prop)).test(rule.property)) {
  836. dimension = TRUE;
  837. return FALSE;
  838. }
  839. });
  840. }
  841. return dimension;
  842. }
  843. function updateChildValues (params) {
  844. if (params.flexMatrix) {
  845. forEach(params.children, function (i, x) {
  846. x.flex = params.flexMatrix[i];
  847. });
  848. }
  849. if (params.ordinalMatrix) {
  850. forEach(params.children, function (i, x) {
  851. x["ordinal-group"] = params.ordinalMatrix[i];
  852. });
  853. }
  854. return params;
  855. }
  856. function ensureStructuralIntegrity (params, instance) {
  857. var target = params.target;
  858. if (!target.FLX_DOM_ID) {
  859. target.FLX_DOM_ID = target.FLX_DOM_ID || (++FLX_DOM_ID);
  860. }
  861. if (!params.nodes) {
  862. params.nodes = sanitizeChildren(target, target.childNodes);
  863. }
  864. if (!params.selector) {
  865. params.selector = buildSelector(target);
  866. target.setAttribute(FLX_PARENT_ATTR, TRUE);
  867. }
  868. if (!params.properties) {
  869. params.properties = [];
  870. }
  871. if (!params.children) {
  872. params.children = matchFlexChildren(target, LIBRARY, sanitizeChildren(target, target.childNodes));
  873. }
  874. if (!params.nested) {
  875. params.nested = params.selector + " [" + FLX_PARENT_ATTR + "]";
  876. }
  877. params.target = target;
  878. params._instance = instance;
  879. return params;
  880. }
  881. selectivizrEngine = (function () {
  882. var RE_COMMENT = /(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)\s*?/g,
  883. RE_IMPORT = /@import\s*(?:(?:(?:url\(\s*(['"]?)(.*)\1)\s*\))|(?:(['"])(.*)\3))\s*([^;]*);/g,
  884. RE_ASSET_URL = /(behavior\s*?:\s*)?\burl\(\s*(["']?)(?!data:)([^"')]+)\2\s*\)/g,
  885. RE_SELECTOR_GROUP = /((?:^|(?:\s*})+)(?:\s*@media[^{]+{)?)\s*([^\{]*?[\[:][^{]+)/g,
  886. // Whitespace normalization regexp's
  887. RE_TIDY_TRAILING_WHITESPACE = /([(\[+~])\s+/g,
  888. RE_TIDY_LEADING_WHITESPACE = /\s+([)\]+~])/g,
  889. RE_TIDY_CONSECUTIVE_WHITESPACE = /\s+/g,
  890. RE_TIDY_TRIM_WHITESPACE = /^\s*((?:[\S\s]*\S)?)\s*$/;
  891. // --[ trim() ]---------------------------------------------------------
  892. // removes leading, trailing whitespace from a string
  893. function trim(text) {
  894. return text.replace(RE_TIDY_TRIM_WHITESPACE, PLACEHOLDER_STRING);
  895. }
  896. // --[ normalizeWhitespace() ]------------------------------------------
  897. // removes leading, trailing and consecutive whitespace from a string
  898. function normalizeWhitespace(text) {
  899. return trim(text).replace(RE_TIDY_CONSECUTIVE_WHITESPACE, SPACE_STRING);
  900. }
  901. // --[ normalizeSelectorWhitespace() ]----------------------------------
  902. // tidys whitespace around selector brackets and combinators
  903. function normalizeSelectorWhitespace(selectorText) {
  904. return normalizeWhitespace(selectorText.replace(RE_TIDY_TRAILING_WHITESPACE, PLACEHOLDER_STRING).replace(RE_TIDY_LEADING_WHITESPACE, PLACEHOLDER_STRING));
  905. }
  906. // --[ patchStyleSheet() ]----------------------------------------------
  907. // Scans the passed cssText for selectors that require emulation and
  908. // creates one or more patches for each matched selector.
  909. function patchStyleSheet(cssText) {
  910. return cssText.replace(RE_SELECTOR_GROUP, function (m, prefix, selectorText) {
  911. var selectorGroups, selector;
  912. selectorGroups = selectorText.split(",");
  913. forEach(selectorGroups, function (i, group) {
  914. selector = normalizeSelectorWhitespace(group) + SPACE_STRING;
  915. });
  916. return prefix + selectorGroups.join(",");
  917. });
  918. }
  919. // --[ getXHRObject() ]-------------------------------------------------
  920. function getXHRObject() {
  921. if (win.XMLHttpRequest) {
  922. return new win.XMLHttpRequest();
  923. }
  924. try {
  925. return new win.ActiveXObject("Microsoft.XMLHTTP");
  926. } catch (e) {
  927. return NULL;
  928. }
  929. }
  930. // --[ loadStyleSheet() ]-----------------------------------------------
  931. function loadStyleSheet(url) {
  932. var xhr = getXHRObject();
  933. xhr.open("GET", url, FALSE);
  934. xhr.send();
  935. return (xhr.status === 200) ? xhr.responseText : EMPTY_STRING;
  936. }
  937. // --[ resolveUrl() ]---------------------------------------------------
  938. // Converts a URL fragment to a fully qualified URL using the specified
  939. // context URL. Returns null if same-origin policy is broken
  940. function resolveUrl(url, contextUrl) {
  941. // IE9 returns a false positive sometimes(?)
  942. if (!url) {
  943. return;
  944. }
  945. function getProtocolAndHost(url) {
  946. return url.substring(0, url.indexOf("/", 8));
  947. }
  948. // absolute path
  949. if (PROTOCOL.test(url)) {
  950. return getProtocolAndHost(contextUrl) === getProtocolAndHost(url) ? url : NULL;
  951. }
  952. // root-relative path
  953. if (url.charAt(0) === "/") {
  954. return getProtocolAndHost(contextUrl) + url;
  955. }
  956. // relative path
  957. var contextUrlPath = contextUrl.split("?")[0]; // ignore query string in the contextUrl
  958. if (url.charAt(0) !== "?" && contextUrlPath.charAt(contextUrlPath.length - 1) !== "/") {
  959. contextUrlPath = contextUrlPath.substring(0, contextUrlPath.lastIndexOf("/") + 1);
  960. }
  961. return contextUrlPath + url;
  962. }
  963. // --[ parseStyleSheet() ]----------------------------------------------
  964. // Downloads the stylesheet specified by the URL, removes it's comments
  965. // and recursivly replaces @import rules with their contents, ultimately
  966. // returning the full cssText.
  967. function parseStyleSheet( url ) {
  968. if (url) {
  969. return loadStyleSheet(url).replace(RE_COMMENT, EMPTY_STRING).
  970. replace(RE_IMPORT, function( match, quoteChar, importUrl, quoteChar2, importUrl2, media ) {
  971. var cssText = parseStyleSheet(resolveUrl(importUrl || importUrl2, url));
  972. return (media) ? "@media " + media + " {" + cssText + "}" : cssText;
  973. }).
  974. replace(RE_ASSET_URL, function( match, isBehavior, quoteChar, assetUrl ) {
  975. quoteChar = quoteChar || EMPTY_STRING;
  976. return isBehavior ? match : " url(" + quoteChar + resolveUrl(assetUrl, url, true) + quoteChar + ") ";
  977. });
  978. }
  979. return EMPTY_STRING;
  980. }
  981. // --[ init() ]---------------------------------------------------------
  982. return function () {
  983. // honour the <base> tag
  984. var url, stylesheet, i, j,
  985. baseTags = doc.getElementsByTagName("BASE"),
  986. baseUrl = (baseTags.length > 0) ? baseTags[0].href : doc.location.href,
  987. cssText, tree, flexers;
  988. for (i = 0, j = doc.styleSheets.length; i < j; i++) {
  989. stylesheet = doc.styleSheets[i];
  990. if (stylesheet && stylesheet.href !== NULL) {
  991. url = resolveUrl(stylesheet.href, baseUrl);
  992. if (url) {
  993. cssText = patchStyleSheet(parseStyleSheet(url));
  994. tree = buildSelectorTree(cssText);
  995. flexers = findFlexboxElements(tree);
  996. }
  997. }
  998. }
  999. buildFlexieCall(flexers);
  1000. };
  1001. }());
  1002. // Flexie box constructor
  1003. FLX.box = function (params) {
  1004. return this.renderModel(params);
  1005. };
  1006. FLX.box.prototype = {
  1007. properties : {
  1008. boxModel : function (target, children, params) {
  1009. var selector, stylesheet, paddingFix, generatedRules;
  1010. target.style.display = "block";
  1011. if (BROWSER.IE === 8) {
  1012. target.style.overflow = "hidden";
  1013. }
  1014. // We'll be using floats, so the easiest way to retain layout
  1015. // is the dreaded clear fix:
  1016. if (!params.cleared) {
  1017. selectors = params.selector.split(/\s?,\s?/);
  1018. stylesheet = doc.styleSheets;
  1019. stylesheet = stylesheet[stylesheet.length - 1];
  1020. paddingFix = "padding-top:" + (getComputedStyle(target, PADDING_TOP, NULL) || "0.1px;");
  1021. generatedRules = [
  1022. "content: '.'",
  1023. "display: block",
  1024. "height: 0",
  1025. "overflow: hidden"
  1026. ].join(";");
  1027. forEach(selectors, function (i, selector) {
  1028. if (stylesheet.addRule) {
  1029. if (BROWSER.IE < 8) {
  1030. target.style.zoom = "1";
  1031. if (BROWSER.IE === 6) {
  1032. stylesheet.addRule(selector.replace(/\>|\+|\~/g, ""), paddingFix + "zoom:1;", 0);
  1033. } else if (BROWSER.IE === 7) {
  1034. stylesheet.addRule(selector, paddingFix + "display:inline-block;", 0);
  1035. }
  1036. } else {
  1037. stylesheet.addRule(selector, paddingFix, 0);
  1038. stylesheet.addRule(selector + ":before", generatedRules, 0);
  1039. stylesheet.addRule(selector + ":after", generatedRules + ";clear:both;", 0);
  1040. }
  1041. } else if (stylesheet.insertRule) {
  1042. stylesheet.insertRule(selector + "{" + paddingFix + "}", 0);
  1043. stylesheet.insertRule(selector + ":after{" + generatedRules + ";clear:both;}", 0);
  1044. }
  1045. });
  1046. params.cleared = TRUE;
  1047. }
  1048. },
  1049. boxDirection : function (target, children, params) {
  1050. var nestedSelector, nested;
  1051. if ((params.direction === "reverse" && !params.reversed) || (params.direction === "normal" && params.reversed)) {
  1052. children = children.reverse();
  1053. forEach(children, function (i, kid) {
  1054. target.appendChild(kid);
  1055. });
  1056. // box-direction is inheritable.
  1057. // We need to see if there are any nested flexbox elements
  1058. nestedSelector = LIBRARY(params.nested);
  1059. forEach(nestedSelector, function (i, node) {
  1060. nested = FLEX_BOXES[node.FLX_DOM_ID];
  1061. if (nested && nested.direction === INHERIT) {
  1062. nested.direction = params.direction;
  1063. }
  1064. });
  1065. params.reversed = !params.reversed;
  1066. }
  1067. },
  1068. boxOrient : function (target, children, params) {
  1069. var self = this, wide, high;
  1070. wide = {
  1071. pos : "marginLeft",
  1072. opp : "marginRight",
  1073. dim : "width",
  1074. out : "offsetWidth",
  1075. func : clientWidth,
  1076. pad : [PADDING_LEFT, PADDING_RIGHT, BORDER_LEFT, BORDER_RIGHT]
  1077. };
  1078. high = {
  1079. pos : "marginTop",
  1080. opp : "marginBottom",
  1081. dim : "height",
  1082. out : "offsetHeight",
  1083. func : clientHeight,
  1084. pad : [PADDING_TOP, PADDING_BOTTOM, BORDER_TOP, BORDER_BOTTOM]
  1085. };
  1086. if (!SUPPORT) {
  1087. forEach(children, function (i, kid) {
  1088. kid.style[(BROWSER.IE >= 9) ? "cssFloat" : "styleFloat"] = LEFT;
  1089. if (params.orient === VERTICAL || params.orient === BLOCK_AXIS) {
  1090. kid.style.clear = LEFT;
  1091. }
  1092. if (BROWSER.IE === 6) {
  1093. kid.style.display = "inline";
  1094. }
  1095. });
  1096. }
  1097. switch (params.orient) {
  1098. case VERTICAL :
  1099. case BLOCK_AXIS:
  1100. self.props = high;
  1101. self.anti = wide;
  1102. break;
  1103. default :
  1104. self.props = wide;
  1105. self.anti = high;
  1106. break;
  1107. }
  1108. },
  1109. boxOrdinalGroup : function (target, children, params) {
  1110. var organizeChildren,
  1111. matrix;
  1112. if (!children.length) {
  1113. return;
  1114. }
  1115. organizeChildren = function (matrix) {
  1116. var keys = matrix.keys;
  1117. forEach(params.reversed ? keys : keys.reverse(), function (i, key) {
  1118. forEach(children, function (i, kid) {
  1119. if (key === kid.getAttribute("data-ordinal-group")) {
  1120. target.appendChild(kid);
  1121. }
  1122. });
  1123. });
  1124. };
  1125. matrix = createMatchMatrix(params.children, children, TRUE);
  1126. if (matrix.keys.length > 1) {
  1127. organizeChildren(matrix);
  1128. }
  1129. },
  1130. boxFlex : function (target, children, params) {
  1131. var self = this,
  1132. testForRestrictiveProperties,
  1133. findTotalWhitespace,
  1134. distributeRatio,
  1135. matrix,
  1136. restrict,
  1137. whitespace,
  1138. distro;
  1139. if (!children.length) {
  1140. return;
  1141. }
  1142. testForRestrictiveProperties = function (matrix) {
  1143. var flexers = matrix.groups,
  1144. keys = matrix.keys,
  1145. max;
  1146. forEach(keys, function (i, key) {
  1147. forEach(flexers[key], function (i, x) {
  1148. max = NULL;
  1149. forEach(x.properties, function (i, rule) {
  1150. if ((RESTRICTIVE_PROPERTIES).test(rule.property)) {
  1151. max = parseFloat(rule.value);
  1152. }
  1153. });
  1154. if (!max || x.match[self.props.out] > max) {
  1155. appendPixelValue(x.match, self.props.pos, NULL);
  1156. }
  1157. });
  1158. });
  1159. };
  1160. findTotalWhitespace = function (matrix) {
  1161. var groupDimension = 0,
  1162. whitespace,
  1163. ration;
  1164. forEach(children, function (i, kid) {
  1165. groupDimension += getComputedStyle(kid, self.props.dim, TRUE);
  1166. forEach(self.props.pad, function (i, pad) {
  1167. groupDimension += getComputedStyle(kid, pad, TRUE);
  1168. });
  1169. groupDimension += getComputedStyle(kid, self.props.pos, TRUE);
  1170. groupDimension += getComputedStyle(kid, self.props.opp, TRUE);
  1171. });
  1172. whitespace = target[self.props.out] - groupDimension;
  1173. forEach(self.props.pad, function (i, pad) {
  1174. whitespace -= getComputedStyle(target, pad, TRUE);
  1175. });
  1176. ration = (whitespace / matrix.total);
  1177. return {
  1178. whitespace : whitespace,
  1179. ration : ration
  1180. };
  1181. };
  1182. distributeRatio = function (matrix, whitespace) {
  1183. var flexers = matrix.groups,
  1184. keys = matrix.keys,
  1185. flex,
  1186. specificity,
  1187. ration = whitespace.ration,
  1188. widthRation,
  1189. trueDim,
  1190. newDimension;
  1191. forEach(keys, function (i, key) {
  1192. widthRation = (ration * key);
  1193. forEach(flexers[key], function (i, x) {
  1194. if (x.match) {
  1195. flex = x.match.getAttribute("data-flex");
  1196. specificity = x.match.getAttribute("data-specificity");
  1197. if (!flex || (specificity <= x.flexSpecificity)) {
  1198. x.match.setAttribute("data-flex", key);
  1199. x.match.setAttribute("data-specificity", x.flexSpecificity);
  1200. trueDim = getComputedStyle(x.match, self.props.dim, TRUE);
  1201. newDimension = Math.max(0, (trueDim + widthRation));
  1202. appendPixelValue(x.match, self.props.dim, newDimension);
  1203. }
  1204. }
  1205. });
  1206. });
  1207. };
  1208. matrix = createMatchMatrix(params.children, children, NULL);
  1209. if (matrix.total) {
  1210. params.hasFlex = TRUE;
  1211. restrict = testForRestrictiveProperties(matrix);
  1212. whitespace = findTotalWhitespace(matrix);
  1213. // Distribute the calculated ratios among the children
  1214. distro = distributeRatio(matrix, whitespace);
  1215. }
  1216. },
  1217. boxAlign : function (target, children, params) {
  1218. var self = this,
  1219. targetDimension,
  1220. kidDimension,
  1221. flexCheck = parentFlex(target);
  1222. if (!SUPPORT && !flexCheck.flex && (params.orient === VERTICAL || params.orient === BLOCK_AXIS)) {
  1223. if (!dimensionValues(target, self.anti.dim)) {
  1224. appendPixelValue(target, self.anti.dim, NULL);
  1225. }
  1226. appendPixelValue(children, self.anti.dim, NULL);
  1227. }
  1228. // Remove padding / border from target dimension
  1229. targetDimension = target[self.anti.out];
  1230. forEach(self.anti.pad, function (i, pad) {
  1231. targetDimension -= getComputedStyle(target, pad, TRUE);
  1232. });
  1233. switch (params.align) {
  1234. case "start" :
  1235. break;
  1236. case "end" :
  1237. forEach(children, function (i, kid) {
  1238. kidDimension = targetDimension - kid[self.anti.out];
  1239. kidDimension -= getComputedStyle(kid, self.anti.opp, TRUE);
  1240. appendPixelValue(kid, self.anti.pos, kidDimension);
  1241. });
  1242. break;
  1243. case "center" :
  1244. forEach(children, function (i, kid) {
  1245. kidDimension = (targetDimension - kid[self.anti.out]) / 2;
  1246. appendPixelValue(kid, self.anti.pos, kidDimension);
  1247. });
  1248. break;
  1249. default :
  1250. forEach(children, function (i, kid) {
  1251. switch (kid.nodeName.toLowerCase()) {
  1252. case "button" :
  1253. case "input" :
  1254. case "select" :
  1255. break;
  1256. default :
  1257. var subtract = 0;
  1258. forEach(self.anti.pad, function (i, pad) {
  1259. subtract += getComputedStyle(kid, pad, TRUE);
  1260. subtract += getComputedStyle(target, pad, TRUE);
  1261. });
  1262. kid.style[self.anti.dim] = "100%";
  1263. kidDimension = kid[self.anti.out] - subtract;
  1264. appendPixelValue(kid, self.anti.dim, NULL);
  1265. kidDimension = targetDimension;
  1266. kidDimension -= getComputedStyle(kid, self.anti.pos, TRUE);
  1267. forEach(self.anti.pad, function (i, pad) {
  1268. kidDimension -= getComputedStyle(kid, pad, TRUE);
  1269. });
  1270. kidDimension -= getComputedStyle(kid, self.anti.opp, TRUE);
  1271. kidDimension = Math.max(0, kidDimension);
  1272. appendPixelValue(kid, self.anti.dim, kidDimension);
  1273. break;
  1274. }
  1275. });
  1276. break;
  1277. }
  1278. },
  1279. boxPack : function (target, children, params) {
  1280. var self = this,
  1281. groupDimension = 0,
  1282. firstComputedMargin = 0,
  1283. targetPadding = 0,
  1284. totalDimension,
  1285. fractionedDimension,
  1286. currentDimension,
  1287. remainder,
  1288. length = children.length - 1,
  1289. kid;
  1290. forEach(children, function (i, kid) {
  1291. groupDimension += kid[self.props.out];
  1292. groupDimension += getComputedStyle(kid, self.props.pos, TRUE);
  1293. groupDimension += getComputedStyle(kid, self.props.opp, TRUE);
  1294. });
  1295. firstComputedMargin = getComputedStyle(children[0], self.props.pos, TRUE);
  1296. totalDimension = target[self.props.out] - groupDimension;
  1297. // Remove padding / border from target dimension
  1298. forEach(self.props.pad, function (i, pad) {
  1299. totalDimension -= getComputedStyle(target, pad, TRUE);
  1300. });
  1301. // If totalDimension is less than 0, we have a problem...
  1302. if (totalDimension < 0) {
  1303. totalDimension = Math.max(0, totalDimension);
  1304. }
  1305. switch (params.pack) {
  1306. case "end" :
  1307. appendPixelValue(children[0], self.props.pos, targetPadding + firstComputedMargin + totalDimension);
  1308. break;
  1309. case "center" :
  1310. if (targetPadding) {
  1311. targetPadding /= 2;
  1312. }
  1313. appendPixelValue(children[0], self.props.pos, targetPadding + firstComputedMargin + Math.floor(totalDimension / 2));
  1314. break;
  1315. case "justify" :
  1316. fractionedDimension = Math.floor((targetPadding + totalDimension) / length);
  1317. remainder = (fractionedDimension * length) - totalDimension;
  1318. var i = children.length - 1,
  1319. value;
  1320. while (i) {
  1321. kid = children[i];
  1322. currentDimension = fractionedDimension;
  1323. if (remainder) {
  1324. currentDimension++;
  1325. remainder++;
  1326. }
  1327. value = getComputedStyle(kid, self.props.pos, TRUE) + currentDimension;
  1328. appendPixelValue(kid, self.props.pos, value);
  1329. i--;
  1330. }
  1331. break;
  1332. }
  1333. target.style.overflow = "";
  1334. }
  1335. },
  1336. setup : function (target, children, params) {
  1337. var self = this, matrix, flexCheck;
  1338. if (!target || !children || !params) {
  1339. return;
  1340. }
  1341. if (SUPPORT && SUPPORT.partialSupport) {
  1342. matrix = createMatchMatrix(params.children, children, NULL);
  1343. flexCheck = parentFlex(target);
  1344. children = sanitizeChildren(target, target.childNodes);
  1345. self.properties.boxOrient.call(self, target, children, params);
  1346. if (!matrix.total || !LIBRARY(params.nested).length) {
  1347. if ((params.align === "stretch") && !SUPPORT.boxAlignStretch && (!flexCheck.nested || !flexCheck.flex)) {
  1348. self.properties.boxAlign.call(self, target, children, params);
  1349. }
  1350. if ((params.pack === "justify") && !SUPPORT.boxPackJustify && !matrix.total) {
  1351. self.properties.boxPack.call(self, target, children, params);
  1352. }
  1353. }
  1354. } else if (!SUPPORT) {
  1355. forEach(self.properties, function (key, func) {
  1356. func.call(self, target, sanitizeChildren(target, target.childNodes), params);
  1357. });
  1358. }
  1359. },
  1360. trackDOM : function (params) {
  1361. attachResizeListener(this, params);
  1362. },
  1363. updateModel : function (params) {
  1364. var self = this,
  1365. target = params.target,
  1366. children = params.nodes;
  1367. // Null properties
  1368. cleanPositioningProperties(children);
  1369. if (params.flexMatrix || params.ordinalMatrix) {
  1370. params = updateChildValues(params);
  1371. }
  1372. self.setup(target, children, params);
  1373. self.bubbleUp(target, params);
  1374. },
  1375. renderModel : function (params) {
  1376. var self = this,
  1377. target = params.target,
  1378. nodes = target.childNodes;
  1379. // Sanity check.
  1380. if (!target.length && !nodes) {
  1381. return false;
  1382. }
  1383. params = ensureStructuralIntegrity(params, this);
  1384. // Setup properties
  1385. self.updateModel(params);
  1386. // Resize / DOM Polling Events
  1387. // Delay for an instant because IE6 is insane.
  1388. win.setTimeout(function () {
  1389. self.trackDOM(params);
  1390. }, 0);
  1391. return self;
  1392. },
  1393. bubbleUp : function (target, params) {
  1394. var self = this, flex,
  1395. parent = params.target.parentNode;
  1396. while (parent) {
  1397. flex = FLEX_BOXES[parent.FLX_DOM_ID];
  1398. if (flex) {
  1399. cleanPositioningProperties(flex.nodes);
  1400. self.setup(flex.target, flex.nodes, flex);
  1401. }
  1402. parent = parent.parentNode;
  1403. }
  1404. }
  1405. };
  1406. FLX.updateInstance = function (target, params) {
  1407. var box;
  1408. if (target) {
  1409. box = FLEX_BOXES[target.FLX_DOM_ID];
  1410. if (box) {
  1411. box._instance.updateModel(box);
  1412. } else {
  1413. box = new FLX.box(params);
  1414. }
  1415. } else {
  1416. forEach(FLEX_BOXES, function (i, box) {
  1417. box._instance.updateModel(box);
  1418. });
  1419. }
  1420. };
  1421. FLX.getInstance = function (target) {
  1422. return FLEX_BOXES[target.FLX_DOM_ID];
  1423. };
  1424. FLX.destroyInstance = function (target) {
  1425. var box,
  1426. destroy;
  1427. destroy = function (box) {
  1428. box.target.FLX_DOM_ID = NULL;
  1429. box.target.style.cssText = EMPTY_STRING;
  1430. forEach(box.children, function (i, x) {
  1431. x.match.style.cssText = EMPTY_STRING;
  1432. });
  1433. };
  1434. if (target) {
  1435. box = FLEX_BOXES[target.FLX_DOM_ID];
  1436. if (box) {
  1437. destroy(box);
  1438. }
  1439. } else {
  1440. forEach(FLEX_BOXES, function (i, box) {
  1441. destroy(box);
  1442. });
  1443. FLEX_BOXES = [];
  1444. }
  1445. };
  1446. FLX.flexboxSupport = function () {
  1447. var partialSupportGrid = {},
  1448. height = 100,
  1449. childHeight,
  1450. dummy = doc.createElement("flxbox"),
  1451. child = '<b style="margin: 0; padding: 0; display:block; width: 10px; height:' + (height / 2) + 'px"></b>',
  1452. tests,
  1453. result;
  1454. dummy.style.width = dummy.style.height = height + "px";
  1455. dummy.innerHTML = (child + child + child);
  1456. appendProperty(dummy, "display", "box", NULL);
  1457. appendProperty(dummy, "box-align", "stretch", TRUE);
  1458. appendProperty(dummy, "box-pack", "justify", TRUE);
  1459. doc.body.appendChild(dummy);
  1460. childHeight = dummy.firstChild.offsetHeight;
  1461. tests = {
  1462. boxAlignStretch : function () {
  1463. return (childHeight === 100);
  1464. },
  1465. boxPackJustify : function () {
  1466. var totalOffset = 0;
  1467. forEach(dummy.childNodes, function (i, child) {
  1468. totalOffset += child.offsetLeft;
  1469. });
  1470. return (totalOffset === 135);
  1471. }
  1472. };
  1473. forEach(tests, function (key, value) {
  1474. result = value();
  1475. if (!result) {
  1476. partialSupportGrid.partialSupport = TRUE;
  1477. }
  1478. partialSupportGrid[key] = result;
  1479. });
  1480. doc.body.removeChild(dummy);
  1481. return ~ (dummy.style.display).indexOf("box") ? partialSupportGrid : FALSE;
  1482. };
  1483. FLX.init = function () {
  1484. FLX.flexboxSupported = SUPPORT = FLX.flexboxSupport();
  1485. if ((!SUPPORT || SUPPORT.partialSupport) && LIBRARY) {
  1486. selectivizrEngine();
  1487. }
  1488. };
  1489. // Flexie Version
  1490. FLX.version = "1.0.3";
  1491. // Load when the DOM is ready
  1492. attachLoadMethod(FLX.init);
  1493. return FLX;
  1494. }(this, document));
  1495. /**
  1496. * PlaneUI IE9 and lte patch
  1497. */
  1498. (function ($) {
  1499. var btnGroupJustify = function() {
  1500. $(".pui-btn-group-justify").each(function() {
  1501. var $this = $(this);
  1502. var btn = $this.find('.pui-btn');
  1503. var total = btn.length;
  1504. btn.css({
  1505. display : "inline-block",
  1506. float : "left"
  1507. }).outerWidth($this.outerWidth() / total);
  1508. }).after("<div clas=\"clear\"></div>");
  1509. };
  1510. $(function() {
  1511. if($(".pui-btn-group-justify").length > 0) {
  1512. btnGroupJustify();
  1513. $(window).resize(btnGroupJustify);
  1514. }
  1515. });
  1516. })(jQuery);