From ffa64f6fd3a05c38725136c25f45ea961c788200 Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 11 Aug 2015 13:49:52 +0100 Subject: [PATCH 1/6] Added a grunt build This copies Layout.js to a dist folder, minifies and source-maps. --- Gruntfile.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 +++++ 2 files changed, 51 insertions(+) create mode 100644 Gruntfile.js diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000..6ff9a040 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,46 @@ +'use strict'; + +module.exports = function(grunt) { + + grunt.initConfig({ + + paths: { + distFolder: 'dist', + srcFolder: 'src' + }, + + clean: ['<%= paths.distFolder %>'], + + copy: { + main: { + expand: true, + src: ['<%= paths.srcFolder %>/Layout.js'], + dest: '<%= paths.distFolder %>', + rename: function(dest, src) { + return dest + '/css-layout.js'; + } + } + }, + + uglify: { + options: { + sourceMap: true, + sourceMapIncludeSources: true + }, + main: { + files: { + '<%= paths.distFolder %>/css-layout.min.js': ['<%= paths.srcFolder %>/Layout.js'] + } + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-copy'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + + grunt.registerTask('build', ['clean', 'copy', 'uglify']); + + grunt.registerTask('default', ['build']); + +}; diff --git a/package.json b/package.json index 83d927ae..64cd4ae6 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,11 @@ "homepage": "https://github.com/facebook/css-layout", "devDependencies": { "eslint": "^0.14.1", + "grunt": "^0.4.5", + "grunt-cli": "^0.1.13", + "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-copy": "^0.8.0", + "grunt-contrib-uglify": "^0.9.1", "jasmine-core": "^2.2.0", "karma": "^0.12.31", "karma-chrome-launcher": "^0.1.7", From 74925f443948a5f0230a6a3b9c3744dcc2c2ae0e Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 11 Aug 2015 14:42:21 +0100 Subject: [PATCH 2/6] Added karma testing to the gruntfile --- Gruntfile.js | 22 ++++++++++++++++++++-- karma.conf.js | 42 ------------------------------------------ package.json | 3 ++- 3 files changed, 22 insertions(+), 45 deletions(-) delete mode 100644 karma.conf.js diff --git a/Gruntfile.js b/Gruntfile.js index 6ff9a040..a374c39b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -6,7 +6,8 @@ module.exports = function(grunt) { paths: { distFolder: 'dist', - srcFolder: 'src' + srcFolder: 'src', + testFolder: 'src/__tests__', }, clean: ['<%= paths.distFolder %>'], @@ -32,14 +33,31 @@ module.exports = function(grunt) { '<%= paths.distFolder %>/css-layout.min.js': ['<%= paths.srcFolder %>/Layout.js'] } } + }, + + karma: { + main: { + options: { + files: [ + '<%= paths.srcFolder %>/Layout.js', + '<%= paths.srcFolder %>/Layout-test-utils.js', + '<%= paths.testFolder %>/Layout-test.js', + '<%= paths.testFolder %>/Layout-consts-test.js' + ], + browsers: ['Chrome'], + frameworks: ['jasmine'], + singleRun: true + } + } } }); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-karma'); - grunt.registerTask('build', ['clean', 'copy', 'uglify']); + grunt.registerTask('build', ['clean', 'karma' ,'copy', 'uglify']); grunt.registerTask('default', ['build']); diff --git a/karma.conf.js b/karma.conf.js deleted file mode 100644 index 61ca91f9..00000000 --- a/karma.conf.js +++ /dev/null @@ -1,42 +0,0 @@ -'use strict'; - -module.exports = function (config) { - config.set({ - - // base path, that will be used to resolve files and exclude - basePath: 'src', - - // frameworks to use - frameworks: ['jasmine'], - - // list of files / patterns to load in the browser - files: [ - 'Layout.js', - 'Layout-test-utils.js', - '__tests__/Layout-test.js', - '__tests__/Layout-consts-test.js' - ], - - plugins: [ - 'karma-chrome-launcher', - 'karma-jasmine' - ], - - // web server port - port: 9876, - - // enable / disable colors in the output (reporters and logs) - colors: true, - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - logLevel: config.LOG_INFO, - - browsers: ['Chrome'], - - // If browser does not capture in given timeout [ms], kill it - captureTimeout: 60000, - - singleRun: false - }); -}; diff --git a/package.json b/package.json index 64cd4ae6..6fc31ec1 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,9 @@ "grunt-contrib-clean": "^0.6.0", "grunt-contrib-copy": "^0.8.0", "grunt-contrib-uglify": "^0.9.1", + "grunt-karma": "^0.12.0", "jasmine-core": "^2.2.0", - "karma": "^0.12.31", + "karma": "^0.13.8", "karma-chrome-launcher": "^0.1.7", "karma-jasmine": "^0.3.5" } From 401f473449a7ebbae1ed87f9d5abbaa29af4b124 Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 11 Aug 2015 16:52:57 +0100 Subject: [PATCH 3/6] Added eslint to the build Fixes #102 --- .eslintrc | 6 +--- Gruntfile.js | 17 +++++----- package.json | 9 ++---- src/JavaTranspiler.js | 4 +-- src/Layout-test-utils.js | 6 ++-- src/__tests__/Layout-test.js | 60 ++++++++++++++++++------------------ src/transpile.js | 15 +++++---- 7 files changed, 56 insertions(+), 61 deletions(-) diff --git a/.eslintrc b/.eslintrc index 40bc7223..728f775e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -19,10 +19,6 @@ "define": true }, "rules": { - "quotes": "single", - "strict": 0, - "no-console": false, - "no-shadow": false, - "no-underscore-dangle": false + "quotes": [2, "single"] } } diff --git a/Gruntfile.js b/Gruntfile.js index a374c39b..e19a252a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -2,6 +2,8 @@ module.exports = function(grunt) { + require('load-grunt-tasks')(grunt); + grunt.initConfig({ paths: { @@ -12,6 +14,13 @@ module.exports = function(grunt) { clean: ['<%= paths.distFolder %>'], + eslint: { + options: { + configFile: '.eslintrc' + }, + target: ['<%= paths.srcFolder %>/Layout.js'] + }, + copy: { main: { expand: true, @@ -52,13 +61,7 @@ module.exports = function(grunt) { } }); - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-karma'); - - grunt.registerTask('build', ['clean', 'karma' ,'copy', 'uglify']); + grunt.registerTask('build', ['eslint', 'clean', 'karma' ,'copy', 'uglify']); grunt.registerTask('default', ['build']); - }; diff --git a/package.json b/package.json index 6fc31ec1..314516d6 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,6 @@ "version": "0.0.2", "description": "Reimplementation of CSS layout using pure JavaScript", "main": "src/main.js", - "scripts": { - "pretest": "./node_modules/eslint/bin/eslint.js src", - "test": "./node_modules/karma/bin/karma start ./karma.conf.js --single-run" - }, "repository": { "type": "git", "url": "https://github.com/facebook/css-layout.git" @@ -18,16 +14,17 @@ }, "homepage": "https://github.com/facebook/css-layout", "devDependencies": { - "eslint": "^0.14.1", "grunt": "^0.4.5", "grunt-cli": "^0.1.13", "grunt-contrib-clean": "^0.6.0", "grunt-contrib-copy": "^0.8.0", "grunt-contrib-uglify": "^0.9.1", + "grunt-eslint": "^17.1.0", "grunt-karma": "^0.12.0", "jasmine-core": "^2.2.0", "karma": "^0.13.8", "karma-chrome-launcher": "^0.1.7", - "karma-jasmine": "^0.3.5" + "karma-jasmine": "^0.3.5", + "load-grunt-tasks": "^3.2.0" } } diff --git a/src/JavaTranspiler.js b/src/JavaTranspiler.js index 8058c72c..455b826d 100644 --- a/src/JavaTranspiler.js +++ b/src/JavaTranspiler.js @@ -140,8 +140,8 @@ var JavaTranspiler = { var allTestsInJava = []; for (var i = 0; i < allTestsInC.length; i++) { allTestsInJava[i] = - " @Test\n" + - " public void testCase" + i + "()\n" + + ' @Test\n' + + ' public void testCase' + i + '()\n' + __transpileSingleTestToJava(allTestsInC[i]); } return allTestsInJava.join('\n\n'); diff --git a/src/Layout-test-utils.js b/src/Layout-test-utils.js index bb707763..c37e6b5b 100644 --- a/src/Layout-test-utils.js +++ b/src/Layout-test-utils.js @@ -6,7 +6,7 @@ * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ -/* globals document, computeLayout */ +/* globals document, computeLayout, navigator */ var layoutTestUtils = (function() { @@ -415,7 +415,7 @@ var layoutTestUtils = (function() { // Note(prenaux): Clearly not what I would like, but it seems to be the only // way :( My guess is that since the font on Windows is // different than on OSX it has a different size. - if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf("Windows NT") > -1) { + if (typeof navigator !== 'undefined' && navigator.userAgent.indexOf('Windows NT') > -1) { preDefinedTextSizes.bigHeight = 36; } @@ -450,7 +450,7 @@ var layoutTestUtils = (function() { testNamedLayout('expected-dom', expectedLayout, domLayout); testNamedLayout('layout-dom', layout, domLayout); }, - testLayoutAgainstDomOnly: function(node, expectedLayout) { + testLayoutAgainstDomOnly: function(node) { var layout = computeCSSLayout(node); var domLayout = computeDOMLayout(node); inplaceRoundNumbersInObject(layout); diff --git a/src/__tests__/Layout-test.js b/src/__tests__/Layout-test.js index 8db804c6..3c4c7bb9 100755 --- a/src/__tests__/Layout-test.js +++ b/src/__tests__/Layout-test.js @@ -2122,7 +2122,7 @@ describe('Layout', function() { {style: {width: 400, height: 400}, children: [ {style: {position: 'absolute', top: 100, left: 100, right: 100, bottom: 100, padding: 10}, children: [ {style: {position: 'absolute', top: 10, left: 10, right: 10, bottom: 10}} - ]}, + ]} ]}, {width: 400, height: 400, top: 0, left: 0, children: [ {width: 200, height: 200, top: 100, left: 100, children: [ @@ -2137,7 +2137,7 @@ describe('Layout', function() { {style: {width: 400, height: 400}, children: [ {style: {position: 'absolute', top: 100, left: 100, right: 100, bottom: 100, padding: 10, borderWidth: 1}, children: [ {style: {position: 'absolute', top: 10, left: 10, right: 10, bottom: 10}} - ]}, + ]} ]}, {width: 400, height: 400, top: 0, left: 0, children: [ {width: 200, height: 200, top: 100, left: 100, children: [ @@ -2152,7 +2152,7 @@ describe('Layout', function() { {style: {width: 400, height: 400}, children: [ {style: {flex: 1, padding: 10}, children: [ {style: {position: 'absolute', top: 10, left: 10, right: 10, bottom: 10}} - ]}, + ]} ]}, {width: 400, height: 400, top: 0, left: 0, children: [ {width: 400, height: 400, top: 0, left: 0, children: [ @@ -2195,7 +2195,7 @@ describe('Layout', function() { {style: {width: 100, height: 100}}, {style: {width: 100, height: 100}}, {style: {width: 100, height: 100}}, - {style: {width: 100, height: 100}}, + {style: {width: 100, height: 100}} ]}, {width: 320, height: 200, top: 0, left: 0, children: [ {width: 100, height: 100, top: 0, left: 0}, @@ -2203,7 +2203,7 @@ describe('Layout', function() { {width: 100, height: 100, top: 0, left: 220}, {width: 100, height: 100, top: 100, left: 0}, {width: 100, height: 100, top: 100, left: 110}, - {width: 100, height: 100, top: 100, left: 220}, + {width: 100, height: 100, top: 100, left: 220} ]} ); }); @@ -2330,24 +2330,24 @@ describe('Layout alignContent', function() { testLayout( {style: {width: 300, height: 380, flexDirection: 'row', flexWrap: 'wrap', alignContent: 'stretch', alignItems: 'flex-start'}, children: [ - /* 0 */ {style: {width: 50, height: 50, margin: 10}}, - /* 1 */ {style: {width: 50, height: 50, margin: 10}}, - /* 2 */ {style: {width: 50, height: 50, margin: 10}}, - /* 3 */ {style: {width: 50, height: 50, margin: 10}}, - /* 4 */ {style: {width: 50, height: 100, margin: 10}}, - /* 5 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start'}}, - /* 6 */ {style: {width: 50, height: 50, margin: 10}}, - /* 7 */ {style: {width: 50, height: 100, margin: 10}}, - /* 8 */ {style: {width: 50, height: 50, margin: 10}}, - /* 9 */ {style: {width: 50, height: 50, margin: 10}}, + /* 0 */ {style: {width: 50, height: 50, margin: 10}}, + /* 1 */ {style: {width: 50, height: 50, margin: 10}}, + /* 2 */ {style: {width: 50, height: 50, margin: 10}}, + /* 3 */ {style: {width: 50, height: 50, margin: 10}}, + /* 4 */ {style: {width: 50, height: 100, margin: 10}}, + /* 5 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start'}}, + /* 6 */ {style: {width: 50, height: 50, margin: 10}}, + /* 7 */ {style: {width: 50, height: 100, margin: 10}}, + /* 8 */ {style: {width: 50, height: 50, margin: 10}}, + /* 9 */ {style: {width: 50, height: 50, margin: 10}}, /* 10 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start' }}, /* 11 */ {style: {width: 50, height: 50, margin: 10}}, /* 12 */ {style: {width: 50, height: 50, margin: 10}}, /* 13 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start'}}, - /* 14 */ {style: {width: 50, height: 50, margin: 10}}, - ], + /* 14 */ {style: {width: 50, height: 50, margin: 10}} + ] }, - {width: 300, height: 380, top: 0, left: 0, children: [ + {width: 300, height: 380, top: 0, left: 0, children: [ {width: 50, height: 50, top: 10, left: 10}, {width: 50, height: 50, top: 10, left: 80}, {width: 50, height: 50, top: 10, left: 150}, @@ -2373,22 +2373,22 @@ describe('Layout alignContent', function() { testLayoutAgainstDomOnly( {style: {width: 300, height: 380, flexDirection: 'row', flexWrap: 'wrap', alignContent: alignContent, alignItems: alignItems}, children: [ - /* 0 */ {style: {width: 50, height: 50, margin: 10}}, - /* 1 */ {style: {width: 50, height: 50, margin: 10}}, - /* 2 */ {style: {width: 50, height: 50, margin: 10}}, - /* 3 */ {style: {width: 50, height: 50, margin: 10}}, - /* 4 */ {style: {width: 50, height: 100, margin: 10}}, - /* 5 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start'}}, - /* 6 */ {style: {width: 50, height: 50, margin: 10}}, - /* 7 */ {style: {width: 50, height: 100, margin: 10}}, - /* 8 */ {style: {width: 50, height: 50, margin: 10}}, - /* 9 */ {style: {width: 50, height: 50, margin: 10}}, + /* 0 */ {style: {width: 50, height: 50, margin: 10}}, + /* 1 */ {style: {width: 50, height: 50, margin: 10}}, + /* 2 */ {style: {width: 50, height: 50, margin: 10}}, + /* 3 */ {style: {width: 50, height: 50, margin: 10}}, + /* 4 */ {style: {width: 50, height: 100, margin: 10}}, + /* 5 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start'}}, + /* 6 */ {style: {width: 50, height: 50, margin: 10}}, + /* 7 */ {style: {width: 50, height: 100, margin: 10}}, + /* 8 */ {style: {width: 50, height: 50, margin: 10}}, + /* 9 */ {style: {width: 50, height: 50, margin: 10}}, /* 10 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start' }}, /* 11 */ {style: {width: 50, height: 50, margin: 10}}, /* 12 */ {style: {width: 50, height: 50, margin: 10}}, /* 13 */ {style: {width: 50, height: 50, margin: 10, alignSelf: 'flex-start'}}, - /* 14 */ {style: {width: 50, height: 50, margin: 10}}, - ], + /* 14 */ {style: {width: 50, height: 50, margin: 10}} + ] } ); }); diff --git a/src/transpile.js b/src/transpile.js index 7ce1bae2..32727bfe 100644 --- a/src/transpile.js +++ b/src/transpile.js @@ -20,7 +20,7 @@ global.layoutTestUtils = { testLayout: function(node, expectedLayout) { allTests.push({name: currentTest, node: node, expectedLayout: expectedLayout}); }, - testLayoutAgainstDomOnly: function(node) { + testLayoutAgainstDomOnly: function() { }, testRandomLayout: function(node, i) { allTests.push({name: 'Random #' + i, node: node, expectedLayout: computeDOMLayout(node)}); @@ -272,15 +272,14 @@ function transpileAnnotatedJStoC(jsCode) { } function makeConstDefs() { - /* eslint no-multi-spaces: 3 */ var lines = [ - '#define SMALL_WIDTH ' + layoutTestUtils.textSizes.smallWidth, - '#define SMALL_HEIGHT ' + layoutTestUtils.textSizes.smallHeight, - '#define BIG_WIDTH ' + layoutTestUtils.textSizes.bigWidth, - '#define BIG_HEIGHT ' + layoutTestUtils.textSizes.bigHeight, + '#define SMALL_WIDTH ' + layoutTestUtils.textSizes.smallWidth, + '#define SMALL_HEIGHT ' + layoutTestUtils.textSizes.smallHeight, + '#define BIG_WIDTH ' + layoutTestUtils.textSizes.bigWidth, + '#define BIG_HEIGHT ' + layoutTestUtils.textSizes.bigHeight, '#define BIG_MIN_WIDTH ' + layoutTestUtils.textSizes.bigMinWidth, - '#define SMALL_TEXT "' + layoutTestUtils.texts.small + '"', - '#define LONG_TEXT "' + layoutTestUtils.texts.big + '"' + '#define SMALL_TEXT "' + layoutTestUtils.texts.small + '"', + '#define LONG_TEXT "' + layoutTestUtils.texts.big + '"' ]; return lines.join('\n'); } From 3b406b30c232728df67d55755d0617b52fb0dadd Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 11 Aug 2015 17:21:09 +0100 Subject: [PATCH 4/6] Module pattern is now implemented via templating Previously two modules were defined, Layout.js, which is the internal implementation, and main.js, which depended on Layout.js and performed the fill / extract functionality required for a public JavaScript API. This simplifies the implementation by just exposing a single UMD module by directly including Layout.js within the module wrapper. Fixes #103 --- Gruntfile.js | 19 ++++++++++--------- package.json | 1 + src/{main.js => css-layout.js} | 11 ++++++----- 3 files changed, 17 insertions(+), 14 deletions(-) rename src/{main.js => css-layout.js} (74%) diff --git a/Gruntfile.js b/Gruntfile.js index e19a252a..40d66eda 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -21,14 +21,15 @@ module.exports = function(grunt) { target: ['<%= paths.srcFolder %>/Layout.js'] }, - copy: { + includereplace: { + options: { + prefix: '// @@', + }, main: { - expand: true, - src: ['<%= paths.srcFolder %>/Layout.js'], - dest: '<%= paths.distFolder %>', - rename: function(dest, src) { - return dest + '/css-layout.js'; - } + // Files to perform replacements and includes with + src: '<%= paths.srcFolder %>/css-layout.js', + // Destination directory to copy files to + dest: '<%= paths.distFolder %>/css-layout.js' } }, @@ -39,7 +40,7 @@ module.exports = function(grunt) { }, main: { files: { - '<%= paths.distFolder %>/css-layout.min.js': ['<%= paths.srcFolder %>/Layout.js'] + '<%= paths.distFolder %>/css-layout.min.js': ['<%= paths.distFolder %>/css-layout.js'] } } }, @@ -61,7 +62,7 @@ module.exports = function(grunt) { } }); - grunt.registerTask('build', ['eslint', 'clean', 'karma' ,'copy', 'uglify']); + grunt.registerTask('build', ['eslint', 'clean', 'karma' ,'includereplace', 'uglify']); grunt.registerTask('default', ['build']); }; diff --git a/package.json b/package.json index 314516d6..a3550da1 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "grunt-contrib-copy": "^0.8.0", "grunt-contrib-uglify": "^0.9.1", "grunt-eslint": "^17.1.0", + "grunt-include-replace": "^3.1.0", "grunt-karma": "^0.12.0", "jasmine-core": "^2.2.0", "karma": "^0.13.8", diff --git a/src/main.js b/src/css-layout.js similarity index 74% rename from src/main.js rename to src/css-layout.js index ac5c1084..14ebab19 100644 --- a/src/main.js +++ b/src/css-layout.js @@ -11,14 +11,15 @@ module.exports = factory(); } else { // Browser globals (root is window) - root.returnExports = factory(); + root.computeLayout = factory(); } }(this, function () { - var layout = require('./Layout.js'); + // @@include('./Layout.js') + return function(node) { - node = layout.fillNodes(node); - layout.computeLayout(node); - node = layout.extractNodes(node); + node = computeLayout.fillNodes(node); + computeLayout.computeLayout(node); + node = computeLayout.extractNodes(node); return node; }; })); From 7f9b3afe33a6940813f96b74678a251c24870139 Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 11 Aug 2015 17:53:47 +0100 Subject: [PATCH 5/6] Updated documentation (And added missing change from previous commit!) --- README.md | 17 +++++++++++++---- RunLayoutRandomTests.html | 31 ------------------------------- RunLayoutTests.html | 32 -------------------------------- src/Layout.js | 19 ------------------- src/css-layout.js | 3 +++ 5 files changed, 16 insertions(+), 86 deletions(-) delete mode 100644 RunLayoutRandomTests.html delete mode 100644 RunLayoutTests.html diff --git a/README.md b/README.md index 342151ae..1510eeaa 100644 --- a/README.md +++ b/README.md @@ -29,10 +29,7 @@ computeLayout( ]} ``` -To run the tests - -- For the JS tests: Open `RunLayoutTests.html` and `RunLayoutRandomTests.html` in Chrome or run `$ npm test` -- For the C and Java tests: run `make` in your terminal. It will also transpile the JS code +NOTE: You need to run the JavaScript build, as detailed below, before running this code. Supported Attributes -------------------- @@ -81,3 +78,15 @@ div, span { - Everything is `display: flex` by default. All the behaviors of `block` and `inline-block` can be expressed in term of `flex` but not the opposite. - All the flex elements are oriented from top to bottom, left to right and do not shrink. This is how things are laid out using the default CSS settings and what you'd expect. - Everything is `position: relative`. This makes `position: absolute` target the direct parent and not some parent which is either `relative` or `absolute`. If you want to position an element relative to something else, you should move it in the DOM instead of relying of CSS. It also makes `top, left, right, bottom` do something when not specifying `position: absolute`. + +Development +----------- + +The core logic resides with `Layout.js`, which is transpiled into equivalent C and Java implementations. + +To run the tests + +- For the JS tests: run `grunt karma` +- For the C and Java tests: run `make` in your terminal. It will also transpile the JS code. This build is also run via Travis CI. + +The JavaScript build process is managed via Grunt. The build performs linting, runs the tests and produce a minified version of the code within a `dist` folder. The build output uses the Universal Module Format (UMD) so that it can be used via AMD / RequireJS, CommonJS or included directly into an HTML page. diff --git a/RunLayoutRandomTests.html b/RunLayoutRandomTests.html deleted file mode 100644 index 0b99ae5a..00000000 --- a/RunLayoutRandomTests.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - Jasmine Spec Runner v2.0.0 - - - - - - - - - - - - - - - - - diff --git a/RunLayoutTests.html b/RunLayoutTests.html deleted file mode 100644 index ee31c822..00000000 --- a/RunLayoutTests.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - Jasmine Spec Runner v2.0.0 - - - - - - - - - - - - - - - - - - diff --git a/src/Layout.js b/src/Layout.js index 898b3186..4c1ca6f6 100755 --- a/src/Layout.js +++ b/src/Layout.js @@ -985,22 +985,3 @@ var computeLayout = (function() { extractNodes: extractNodes }; })(); - -// UMD (Universal Module Definition) -// See https://github.com/umdjs/umd for reference -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - // AMD. Register as an anonymous module. - define([], factory); - } else if (typeof exports === 'object') { - // Node. Does not work with strict CommonJS, but - // only CommonJS-like environments that support module.exports, - // like Node. - module.exports = factory(); - } else { - // Browser globals (root is window) - root.returnExports = factory(); - } -}(this, function () { - return computeLayout; -})); diff --git a/src/css-layout.js b/src/css-layout.js index 14ebab19..02514160 100644 --- a/src/css-layout.js +++ b/src/css-layout.js @@ -1,5 +1,8 @@ // UMD (Universal Module Definition) // See https://github.com/umdjs/umd for reference +// +// This file uses the following specific UMD implementation: +// https://github.com/umdjs/umd/blob/master/returnExports.js (function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD. Register as an anonymous module. From 5653e4ef82591aac2885af4f070e8c8f98c1959f Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Tue, 11 Aug 2015 21:01:03 +0100 Subject: [PATCH 6/6] Fixed build and added distribution files to the repo --- Gruntfile.js | 2 - README.md | 2 - dist/css-layout.js | 1018 ++++++++++++++++++++++++++++++++++++ dist/css-layout.min.js | 2 + dist/css-layout.min.js.map | 1 + src/Layout.js | 4 + 6 files changed, 1025 insertions(+), 4 deletions(-) create mode 100644 dist/css-layout.js create mode 100644 dist/css-layout.min.js create mode 100644 dist/css-layout.min.js.map diff --git a/Gruntfile.js b/Gruntfile.js index 40d66eda..ba9eab71 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -26,9 +26,7 @@ module.exports = function(grunt) { prefix: '// @@', }, main: { - // Files to perform replacements and includes with src: '<%= paths.srcFolder %>/css-layout.js', - // Destination directory to copy files to dest: '<%= paths.distFolder %>/css-layout.js' } }, diff --git a/README.md b/README.md index 1510eeaa..965aa6ff 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,6 @@ computeLayout( ]} ``` -NOTE: You need to run the JavaScript build, as detailed below, before running this code. - Supported Attributes -------------------- diff --git a/dist/css-layout.js b/dist/css-layout.js new file mode 100644 index 00000000..af198231 --- /dev/null +++ b/dist/css-layout.js @@ -0,0 +1,1018 @@ +// UMD (Universal Module Definition) +// See https://github.com/umdjs/umd for reference +// +// This file uses the following specific UMD implementation: +// https://github.com/umdjs/umd/blob/master/returnExports.js +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.computeLayout = factory(); + } +}(this, function () { + /** + * Copyright (c) 2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +var computeLayout = (function() { + + var CSS_UNDEFINED; + + var CSS_DIRECTION_INHERIT = 'inherit'; + var CSS_DIRECTION_LTR = 'ltr'; + var CSS_DIRECTION_RTL = 'rtl'; + + var CSS_FLEX_DIRECTION_ROW = 'row'; + var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse'; + var CSS_FLEX_DIRECTION_COLUMN = 'column'; + var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse'; + + // var CSS_JUSTIFY_FLEX_START = 'flex-start'; + var CSS_JUSTIFY_CENTER = 'center'; + var CSS_JUSTIFY_FLEX_END = 'flex-end'; + var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between'; + var CSS_JUSTIFY_SPACE_AROUND = 'space-around'; + + var CSS_ALIGN_FLEX_START = 'flex-start'; + var CSS_ALIGN_CENTER = 'center'; + var CSS_ALIGN_FLEX_END = 'flex-end'; + var CSS_ALIGN_STRETCH = 'stretch'; + + var CSS_POSITION_RELATIVE = 'relative'; + var CSS_POSITION_ABSOLUTE = 'absolute'; + + var leading = { + 'row': 'left', + 'row-reverse': 'right', + 'column': 'top', + 'column-reverse': 'bottom' + }; + var trailing = { + 'row': 'right', + 'row-reverse': 'left', + 'column': 'bottom', + 'column-reverse': 'top' + }; + var pos = { + 'row': 'left', + 'row-reverse': 'right', + 'column': 'top', + 'column-reverse': 'bottom' + }; + var dim = { + 'row': 'width', + 'row-reverse': 'width', + 'column': 'height', + 'column-reverse': 'height' + }; + + function capitalizeFirst(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + function getSpacing(node, type, suffix, locations) { + for (var i = 0; i < locations.length; ++i) { + var location = locations[i]; + + var key = type + capitalizeFirst(location) + suffix; + if (key in node.style) { + return node.style[key]; + } + + key = type + suffix; + if (key in node.style) { + return node.style[key]; + } + } + + return 0; + } + function fillNodes(node) { + node.layout = { + width: undefined, + height: undefined, + top: 0, + left: 0, + right: 0, + bottom: 0 + }; + if (!node.style) { + node.style = {}; + } + + if (!node.children || node.style.measure) { + node.children = []; + } + node.children.forEach(fillNodes); + return node; + } + + function extractNodes(node) { + var layout = node.layout; + delete node.layout; + if (node.children && node.children.length > 0) { + layout.children = node.children.map(extractNodes); + } else { + delete node.children; + } + + delete layout.right; + delete layout.bottom; + delete layout.direction; + + return layout; + } + + function getPositiveSpacing(node, type, suffix, locations) { + for (var i = 0; i < locations.length; ++i) { + var location = locations[i]; + + var key = type + capitalizeFirst(location) + suffix; + if (key in node.style && node.style[key] >= 0) { + return node.style[key]; + } + + key = type + suffix; + if (key in node.style && node.style[key] >= 0) { + return node.style[key]; + } + } + + return 0; + } + + function isUndefined(value) { + return value === undefined; + } + + function isRowDirection(flexDirection) { + return flexDirection === CSS_FLEX_DIRECTION_ROW || + flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE; + } + + function isColumnDirection(flexDirection) { + return flexDirection === CSS_FLEX_DIRECTION_COLUMN || + flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE; + } + + function getLeadingLocations(axis) { + var locations = [leading[axis]]; + if (isRowDirection(axis)) { + locations.unshift('start'); + } + + return locations; + } + + function getTrailingLocations(axis) { + var locations = [trailing[axis]]; + if (isRowDirection(axis)) { + locations.unshift('end'); + } + + return locations; + } + + function getMargin(node, locations) { + return getSpacing(node, 'margin', '', locations); + } + + function getLeadingMargin(node, axis) { + return getMargin(node, getLeadingLocations(axis)); + } + + function getTrailingMargin(node, axis) { + return getMargin(node, getTrailingLocations(axis)); + } + + function getPadding(node, locations) { + return getPositiveSpacing(node, 'padding', '', locations); + } + + function getLeadingPadding(node, axis) { + return getPadding(node, getLeadingLocations(axis)); + } + + function getTrailingPadding(node, axis) { + return getPadding(node, getTrailingLocations(axis)); + } + + function getBorder(node, locations) { + return getPositiveSpacing(node, 'border', 'Width', locations); + } + + function getLeadingBorder(node, axis) { + return getBorder(node, getLeadingLocations(axis)); + } + + function getTrailingBorder(node, axis) { + return getBorder(node, getTrailingLocations(axis)); + } + + function getLeadingPaddingAndBorder(node, axis) { + return getLeadingPadding(node, axis) + getLeadingBorder(node, axis); + } + + function getTrailingPaddingAndBorder(node, axis) { + return getTrailingPadding(node, axis) + getTrailingBorder(node, axis); + } + + function getBorderAxis(node, axis) { + return getLeadingBorder(node, axis) + getTrailingBorder(node, axis); + } + + function getMarginAxis(node, axis) { + return getLeadingMargin(node, axis) + getTrailingMargin(node, axis); + } + + function getPaddingAndBorderAxis(node, axis) { + return getLeadingPaddingAndBorder(node, axis) + + getTrailingPaddingAndBorder(node, axis); + } + + function getJustifyContent(node) { + if ('justifyContent' in node.style) { + return node.style.justifyContent; + } + return 'flex-start'; + } + + function getAlignContent(node) { + if ('alignContent' in node.style) { + return node.style.alignContent; + } + return 'flex-start'; + } + + function getAlignItem(node, child) { + if ('alignSelf' in child.style) { + return child.style.alignSelf; + } + if ('alignItems' in node.style) { + return node.style.alignItems; + } + return 'stretch'; + } + + function resolveAxis(axis, direction) { + if (direction === CSS_DIRECTION_RTL) { + if (axis === CSS_FLEX_DIRECTION_ROW) { + return CSS_FLEX_DIRECTION_ROW_REVERSE; + } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) { + return CSS_FLEX_DIRECTION_ROW; + } + } + + return axis; + } + + function resolveDirection(node, parentDirection) { + var direction; + if ('direction' in node.style) { + direction = node.style.direction; + } else { + direction = CSS_DIRECTION_INHERIT; + } + + if (direction === CSS_DIRECTION_INHERIT) { + direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection); + } + + return direction; + } + + function getFlexDirection(node) { + if ('flexDirection' in node.style) { + return node.style.flexDirection; + } + return CSS_FLEX_DIRECTION_COLUMN; + } + + function getCrossFlexDirection(flexDirection, direction) { + if (isColumnDirection(flexDirection)) { + return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction); + } else { + return CSS_FLEX_DIRECTION_COLUMN; + } + } + + function getPositionType(node) { + if ('position' in node.style) { + return node.style.position; + } + return 'relative'; + } + + function getFlex(node) { + return node.style.flex; + } + + function isFlex(node) { + return ( + getPositionType(node) === CSS_POSITION_RELATIVE && + getFlex(node) > 0 + ); + } + + function isFlexWrap(node) { + return node.style.flexWrap === 'wrap'; + } + + function getDimWithMargin(node, axis) { + return node.layout[dim[axis]] + getMarginAxis(node, axis); + } + + function isDimDefined(node, axis) { + return !isUndefined(node.style[dim[axis]]) && node.style[dim[axis]] >= 0; + } + + function isPosDefined(node, pos) { + return !isUndefined(node.style[pos]); + } + + function isMeasureDefined(node) { + return 'measure' in node.style; + } + + function getPosition(node, pos) { + if (pos in node.style) { + return node.style[pos]; + } + return 0; + } + + function boundAxis(node, axis, value) { + var min = { + 'row': node.style.minWidth, + 'row-reverse': node.style.minWidth, + 'column': node.style.minHeight, + 'column-reverse': node.style.minHeight + }[axis]; + + var max = { + 'row': node.style.maxWidth, + 'row-reverse': node.style.maxWidth, + 'column': node.style.maxHeight, + 'column-reverse': node.style.maxHeight + }[axis]; + + var boundValue = value; + if (!isUndefined(max) && max >= 0 && boundValue > max) { + boundValue = max; + } + if (!isUndefined(min) && min >= 0 && boundValue < min) { + boundValue = min; + } + return boundValue; + } + + function fmaxf(a, b) { + if (a > b) { + return a; + } + return b; + } + + // When the user specifically sets a value for width or height + function setDimensionFromStyle(node, axis) { + // The parent already computed us a width or height. We just skip it + if (!isUndefined(node.layout[dim[axis]])) { + return; + } + // We only run if there's a width or height defined + if (!isDimDefined(node, axis)) { + return; + } + + // The dimensions can never be smaller than the padding and border + node.layout[dim[axis]] = fmaxf( + boundAxis(node, axis, node.style[dim[axis]]), + getPaddingAndBorderAxis(node, axis) + ); + } + + function setTrailingPosition(node, child, axis) { + child.layout[trailing[axis]] = node.layout[dim[axis]] - + child.layout[dim[axis]] - child.layout[pos[axis]]; + } + + // If both left and right are defined, then use left. Otherwise return + // +left or -right depending on which is defined. + function getRelativePosition(node, axis) { + if (leading[axis] in node.style) { + return getPosition(node, leading[axis]); + } + return -getPosition(node, trailing[axis]); + } + + function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) { + var/*css_direction_t*/ direction = resolveDirection(node, parentDirection); + var/*css_flex_direction_t*/ mainAxis = resolveAxis(getFlexDirection(node), direction); + var/*css_flex_direction_t*/ crossAxis = getCrossFlexDirection(mainAxis, direction); + var/*css_flex_direction_t*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction); + + // Handle width and height style attributes + setDimensionFromStyle(node, mainAxis); + setDimensionFromStyle(node, crossAxis); + + // Set the resolved resolution in the node's layout + node.layout.direction = direction; + + // The position is set by the parent, but we need to complete it with a + // delta composed of the margin and left/top/right/bottom + node.layout[leading[mainAxis]] += getLeadingMargin(node, mainAxis) + + getRelativePosition(node, mainAxis); + node.layout[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) + + getRelativePosition(node, mainAxis); + node.layout[leading[crossAxis]] += getLeadingMargin(node, crossAxis) + + getRelativePosition(node, crossAxis); + node.layout[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) + + getRelativePosition(node, crossAxis); + + if (isMeasureDefined(node)) { + var/*float*/ width = CSS_UNDEFINED; + if (isDimDefined(node, resolvedRowAxis)) { + width = node.style.width; + } else if (!isUndefined(node.layout[dim[resolvedRowAxis]])) { + width = node.layout[dim[resolvedRowAxis]]; + } else { + width = parentMaxWidth - + getMarginAxis(node, resolvedRowAxis); + } + width -= getPaddingAndBorderAxis(node, resolvedRowAxis); + + // We only need to give a dimension for the text if we haven't got any + // for it computed yet. It can either be from the style attribute or because + // the element is flexible. + var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) && + isUndefined(node.layout[dim[resolvedRowAxis]]); + var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && + isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]); + + // Let's not measure the text if we already know both dimensions + if (isRowUndefined || isColumnUndefined) { + var/*css_dim_t*/ measureDim = node.style.measure( + /*(c)!node->context,*/ + /*(java)!layoutContext.measureOutput,*/ + width + ); + if (isRowUndefined) { + node.layout.width = measureDim.width + + getPaddingAndBorderAxis(node, resolvedRowAxis); + } + if (isColumnUndefined) { + node.layout.height = measureDim.height + + getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); + } + } + if (node.children.length === 0) { + return; + } + } + + var/*int*/ i; + var/*int*/ ii; + var/*css_node_t**/ child; + var/*css_flex_direction_t*/ axis; + + // Pre-fill some dimensions straight from the parent + for (i = 0; i < node.children.length; ++i) { + child = node.children[i]; + // Pre-fill cross axis dimensions when the child is using stretch before + // we call the recursive layout pass + if (getAlignItem(node, child) === CSS_ALIGN_STRETCH && + getPositionType(child) === CSS_POSITION_RELATIVE && + !isUndefined(node.layout[dim[crossAxis]]) && + !isDimDefined(child, crossAxis)) { + child.layout[dim[crossAxis]] = fmaxf( + boundAxis(child, crossAxis, node.layout[dim[crossAxis]] - + getPaddingAndBorderAxis(node, crossAxis) - + getMarginAxis(child, crossAxis)), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, crossAxis) + ); + } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) { + // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both + // left and right or top and bottom). + for (ii = 0; ii < 2; ii++) { + axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (!isUndefined(node.layout[dim[axis]]) && + !isDimDefined(child, axis) && + isPosDefined(child, leading[axis]) && + isPosDefined(child, trailing[axis])) { + child.layout[dim[axis]] = fmaxf( + boundAxis(child, axis, node.layout[dim[axis]] - + getPaddingAndBorderAxis(node, axis) - + getMarginAxis(child, axis) - + getPosition(child, leading[axis]) - + getPosition(child, trailing[axis])), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, axis) + ); + } + } + } + } + + var/*float*/ definedMainDim = CSS_UNDEFINED; + if (!isUndefined(node.layout[dim[mainAxis]])) { + definedMainDim = node.layout[dim[mainAxis]] - + getPaddingAndBorderAxis(node, mainAxis); + } + + // We want to execute the next two loops one per line with flex-wrap + var/*int*/ startLine = 0; + var/*int*/ endLine = 0; + // var/*int*/ nextOffset = 0; + var/*int*/ alreadyComputedNextLayout = 0; + // We aggregate the total dimensions of the container in those two variables + var/*float*/ linesCrossDim = 0; + var/*float*/ linesMainDim = 0; + var/*int*/ linesCount = 0; + while (endLine < node.children.length) { + // Layout non flexible children and count children by type + + // mainContentDim is accumulation of the dimensions and margin of all the + // non flexible children. This will be used in order to either set the + // dimensions of the node if none already exist, or to compute the + // remaining space left for the flexible children. + var/*float*/ mainContentDim = 0; + + // There are three kind of children, non flexible, flexible and absolute. + // We need to know how many there are in order to distribute the space. + var/*int*/ flexibleChildrenCount = 0; + var/*float*/ totalFlexible = 0; + var/*int*/ nonFlexibleChildrenCount = 0; + + var/*float*/ maxWidth; + for (i = startLine; i < node.children.length; ++i) { + child = node.children[i]; + var/*float*/ nextContentDim = 0; + + // It only makes sense to consider a child flexible if we have a computed + // dimension for the node. + if (!isUndefined(node.layout[dim[mainAxis]]) && isFlex(child)) { + flexibleChildrenCount++; + totalFlexible += getFlex(child); + + // Even if we don't know its exact size yet, we already know the padding, + // border and margin. We'll use this partial information, which represents + // the smallest possible size for the child, to compute the remaining + // available space. + nextContentDim = getPaddingAndBorderAxis(child, mainAxis) + + getMarginAxis(child, mainAxis); + + } else { + maxWidth = CSS_UNDEFINED; + if (!isRowDirection(mainAxis)) { + maxWidth = parentMaxWidth - + getMarginAxis(node, resolvedRowAxis) - + getPaddingAndBorderAxis(node, resolvedRowAxis); + + if (isDimDefined(node, resolvedRowAxis)) { + maxWidth = node.layout[dim[resolvedRowAxis]] - + getPaddingAndBorderAxis(node, resolvedRowAxis); + } + } + + // This is the main recursive call. We layout non flexible children. + if (alreadyComputedNextLayout === 0) { + layoutNode(/*(java)!layoutContext, */child, maxWidth, direction); + } + + // Absolute positioned elements do not take part of the layout, so we + // don't use them to compute mainContentDim + if (getPositionType(child) === CSS_POSITION_RELATIVE) { + nonFlexibleChildrenCount++; + // At this point we know the final size and margin of the element. + nextContentDim = getDimWithMargin(child, mainAxis); + } + } + + // The element we are about to add would make us go to the next line + if (isFlexWrap(node) && + !isUndefined(node.layout[dim[mainAxis]]) && + mainContentDim + nextContentDim > definedMainDim && + // If there's only one element, then it's bigger than the content + // and needs its own line + i !== startLine) { + nonFlexibleChildrenCount--; + alreadyComputedNextLayout = 1; + break; + } + alreadyComputedNextLayout = 0; + mainContentDim += nextContentDim; + endLine = i + 1; + } + + // Layout flexible children and allocate empty space + + // In order to position the elements in the main axis, we have two + // controls. The space between the beginning and the first element + // and the space between each two elements. + var/*float*/ leadingMainDim = 0; + var/*float*/ betweenMainDim = 0; + + // The remaining available space that needs to be allocated + var/*float*/ remainingMainDim = 0; + if (!isUndefined(node.layout[dim[mainAxis]])) { + remainingMainDim = definedMainDim - mainContentDim; + } else { + remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim; + } + + // If there are flexible children in the mix, they are going to fill the + // remaining space + if (flexibleChildrenCount !== 0) { + var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible; + var/*float*/ baseMainDim; + var/*float*/ boundMainDim; + + // Iterate over every child in the axis. If the flex share of remaining + // space doesn't meet min/max bounds, remove this child from flex + // calculations. + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + if (isFlex(child)) { + baseMainDim = flexibleMainDim * getFlex(child) + + getPaddingAndBorderAxis(child, mainAxis); + boundMainDim = boundAxis(child, mainAxis, baseMainDim); + + if (baseMainDim !== boundMainDim) { + remainingMainDim -= boundMainDim; + totalFlexible -= getFlex(child); + } + } + } + flexibleMainDim = remainingMainDim / totalFlexible; + + // The non flexible children can overflow the container, in this case + // we should just assume that there is no space available. + if (flexibleMainDim < 0) { + flexibleMainDim = 0; + } + // We iterate over the full array and only apply the action on flexible + // children. This is faster than actually allocating a new array that + // contains only flexible children. + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + if (isFlex(child)) { + // At this point we know the final size of the element in the main + // dimension + child.layout[dim[mainAxis]] = boundAxis(child, mainAxis, + flexibleMainDim * getFlex(child) + getPaddingAndBorderAxis(child, mainAxis) + ); + + maxWidth = CSS_UNDEFINED; + if (isDimDefined(node, resolvedRowAxis)) { + maxWidth = node.layout[dim[resolvedRowAxis]] - + getPaddingAndBorderAxis(node, resolvedRowAxis); + } else if (!isRowDirection(mainAxis)) { + maxWidth = parentMaxWidth - + getMarginAxis(node, resolvedRowAxis) - + getPaddingAndBorderAxis(node, resolvedRowAxis); + } + + // And we recursively call the layout algorithm for this child + layoutNode(/*(java)!layoutContext, */child, maxWidth, direction); + } + } + + // We use justifyContent to figure out how to allocate the remaining + // space available + } else { + var/*css_justify_t*/ justifyContent = getJustifyContent(node); + if (justifyContent === CSS_JUSTIFY_CENTER) { + leadingMainDim = remainingMainDim / 2; + } else if (justifyContent === CSS_JUSTIFY_FLEX_END) { + leadingMainDim = remainingMainDim; + } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) { + remainingMainDim = fmaxf(remainingMainDim, 0); + if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) { + betweenMainDim = remainingMainDim / + (flexibleChildrenCount + nonFlexibleChildrenCount - 1); + } else { + betweenMainDim = 0; + } + } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) { + // Space on the edges is half of the space between elements + betweenMainDim = remainingMainDim / + (flexibleChildrenCount + nonFlexibleChildrenCount); + leadingMainDim = betweenMainDim / 2; + } + } + + // Position elements in the main axis and compute dimensions + + // At this point, all the children have their dimensions set. We need to + // find their position. In order to do that, we accumulate data in + // variables that are also useful to compute the total dimensions of the + // container! + var/*float*/ crossDim = 0; + var/*float*/ mainDim = leadingMainDim + + getLeadingPaddingAndBorder(node, mainAxis); + + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + child.lineIndex = linesCount; + + if (getPositionType(child) === CSS_POSITION_ABSOLUTE && + isPosDefined(child, leading[mainAxis])) { + // In case the child is position absolute and has left/top being + // defined, we override the position to whatever the user said + // (and margin/border). + child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) + + getLeadingBorder(node, mainAxis) + + getLeadingMargin(child, mainAxis); + } else { + // If the child is position absolute (without top/left) or relative, + // we put it at the current accumulated offset. + child.layout[pos[mainAxis]] += mainDim; + + // Define the trailing position accordingly. + if (!isUndefined(node.layout[dim[mainAxis]])) { + setTrailingPosition(node, child, mainAxis); + } + } + + // Now that we placed the element, we need to update the variables + // We only need to do that for relative elements. Absolute elements + // do not take part in that phase. + if (getPositionType(child) === CSS_POSITION_RELATIVE) { + // The main dimension is the sum of all the elements dimension plus + // the spacing. + mainDim += betweenMainDim + getDimWithMargin(child, mainAxis); + // The cross dimension is the max of the elements dimension since there + // can only be one element in that cross dimension. + crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis))); + } + } + + var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]]; + if (isUndefined(node.layout[dim[crossAxis]])) { + containerCrossAxis = fmaxf( + // For the cross dim, we add both sides at the end because the value + // is aggregate via a max function. Intermediate negative values + // can mess this computation otherwise + boundAxis(node, crossAxis, crossDim + getPaddingAndBorderAxis(node, crossAxis)), + getPaddingAndBorderAxis(node, crossAxis) + ); + } + + // Position elements in the cross axis + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + + if (getPositionType(child) === CSS_POSITION_ABSOLUTE && + isPosDefined(child, leading[crossAxis])) { + // In case the child is absolutely positionned and has a + // top/left/bottom/right being set, we override all the previously + // computed positions to set it correctly. + child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) + + getLeadingBorder(node, crossAxis) + + getLeadingMargin(child, crossAxis); + + } else { + var/*float*/ leadingCrossDim = getLeadingPaddingAndBorder(node, crossAxis); + + // For a relative children, we're either using alignItems (parent) or + // alignSelf (child) in order to determine the position in the cross axis + if (getPositionType(child) === CSS_POSITION_RELATIVE) { + var/*css_align_t*/ alignItem = getAlignItem(node, child); + if (alignItem === CSS_ALIGN_STRETCH) { + // You can only stretch if the dimension has not already been set + // previously. + if (!isDimDefined(child, crossAxis)) { + child.layout[dim[crossAxis]] = fmaxf( + boundAxis(child, crossAxis, containerCrossAxis - + getPaddingAndBorderAxis(node, crossAxis) - + getMarginAxis(child, crossAxis)), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, crossAxis) + ); + } + } else if (alignItem !== CSS_ALIGN_FLEX_START) { + // The remaining space between the parent dimensions+padding and child + // dimensions+margin. + var/*float*/ remainingCrossDim = containerCrossAxis - + getPaddingAndBorderAxis(node, crossAxis) - + getDimWithMargin(child, crossAxis); + + if (alignItem === CSS_ALIGN_CENTER) { + leadingCrossDim += remainingCrossDim / 2; + } else { // CSS_ALIGN_FLEX_END + leadingCrossDim += remainingCrossDim; + } + } + } + + // And we apply the position + child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim; + + // Define the trailing position accordingly. + if (!isUndefined(node.layout[dim[crossAxis]])) { + setTrailingPosition(node, child, crossAxis); + } + } + } + + linesCrossDim += crossDim; + linesMainDim = fmaxf(linesMainDim, mainDim); + linesCount += 1; + startLine = endLine; + } + + // + // + // Note(prenaux): More than one line, we need to layout the crossAxis + // according to alignContent. + // + // Note that we could probably remove and handle the one line case + // here too, but for the moment this is safer since it won't interfere with + // previously working code. + // + // See specs: + // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm + // section 9.4 + // + if (linesCount > 1 && + !isUndefined(node.layout[dim[crossAxis]])) { + var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] - + getPaddingAndBorderAxis(node, crossAxis); + var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim; + + var/*float*/ crossDimLead = 0; + var/*float*/ currentLead = getLeadingPaddingAndBorder(node, crossAxis); + + var/*css_align_t*/ alignContent = getAlignContent(node); + if (alignContent === CSS_ALIGN_FLEX_END) { + currentLead += remainingAlignContentDim; + } else if (alignContent === CSS_ALIGN_CENTER) { + currentLead += remainingAlignContentDim / 2; + } else if (alignContent === CSS_ALIGN_STRETCH) { + if (nodeCrossAxisInnerSize > linesCrossDim) { + crossDimLead = (remainingAlignContentDim / linesCount); + } + } + + var/*int*/ endIndex = 0; + for (i = 0; i < linesCount; ++i) { + var/*int*/ startIndex = endIndex; + + // compute the line's height and find the endIndex + var/*float*/ lineHeight = 0; + for (ii = startIndex; ii < node.children.length; ++ii) { + child = node.children[ii]; + if (getPositionType(child) !== CSS_POSITION_RELATIVE) { + continue; + } + if (child.lineIndex !== i) { + break; + } + if (!isUndefined(child.layout[dim[crossAxis]])) { + lineHeight = fmaxf( + lineHeight, + child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis) + ); + } + } + endIndex = ii; + lineHeight += crossDimLead; + + for (ii = startIndex; ii < endIndex; ++ii) { + child = node.children[ii]; + if (getPositionType(child) !== CSS_POSITION_RELATIVE) { + continue; + } + + var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child); + if (alignContentAlignItem === CSS_ALIGN_FLEX_START) { + child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis); + } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) { + child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[dim[crossAxis]]; + } else if (alignContentAlignItem === CSS_ALIGN_CENTER) { + var/*float*/ childHeight = child.layout[dim[crossAxis]]; + child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2; + } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) { + child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis); + // TODO(prenaux): Correctly set the height of items with undefined + // (auto) crossAxis dimension. + } + } + + currentLead += lineHeight; + } + } + + var/*bool*/ needsMainTrailingPos = false; + var/*bool*/ needsCrossTrailingPos = false; + + // If the user didn't specify a width or height, and it has not been set + // by the container, then we set it via the children. + if (isUndefined(node.layout[dim[mainAxis]])) { + node.layout[dim[mainAxis]] = fmaxf( + // We're missing the last padding at this point to get the final + // dimension + boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)), + // We can never assign a width smaller than the padding and borders + getPaddingAndBorderAxis(node, mainAxis) + ); + + needsMainTrailingPos = true; + } + + if (isUndefined(node.layout[dim[crossAxis]])) { + node.layout[dim[crossAxis]] = fmaxf( + // For the cross dim, we add both sides at the end because the value + // is aggregate via a max function. Intermediate negative values + // can mess this computation otherwise + boundAxis(node, crossAxis, linesCrossDim + getPaddingAndBorderAxis(node, crossAxis)), + getPaddingAndBorderAxis(node, crossAxis) + ); + + needsCrossTrailingPos = true; + } + + // Set trailing position if necessary + if (needsMainTrailingPos || needsCrossTrailingPos) { + for (i = 0; i < node.children.length; ++i) { + child = node.children[i]; + + if (needsMainTrailingPos) { + setTrailingPosition(node, child, mainAxis); + } + + if (needsCrossTrailingPos) { + setTrailingPosition(node, child, crossAxis); + } + } + } + + // Calculate dimensions for absolutely positioned elements + for (i = 0; i < node.children.length; ++i) { + child = node.children[i]; + if (getPositionType(child) === CSS_POSITION_ABSOLUTE) { + // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both + // left and right or top and bottom). + for (ii = 0; ii < 2; ii++) { + axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (!isUndefined(node.layout[dim[axis]]) && + !isDimDefined(child, axis) && + isPosDefined(child, leading[axis]) && + isPosDefined(child, trailing[axis])) { + child.layout[dim[axis]] = fmaxf( + boundAxis(child, axis, node.layout[dim[axis]] - + getBorderAxis(node, axis) - + getMarginAxis(child, axis) - + getPosition(child, leading[axis]) - + getPosition(child, trailing[axis]) + ), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, axis) + ); + } + } + for (ii = 0; ii < 2; ii++) { + axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (isPosDefined(child, trailing[axis]) && + !isPosDefined(child, leading[axis])) { + child.layout[leading[axis]] = + node.layout[dim[axis]] - + child.layout[dim[axis]] - + getPosition(child, trailing[axis]); + } + } + } + } + } + + return { + computeLayout: layoutNode, + fillNodes: fillNodes, + extractNodes: extractNodes + }; +})(); + +if (typeof exports === 'object') { + module.exports = computeLayout; +} + + return function(node) { + node = computeLayout.fillNodes(node); + computeLayout.computeLayout(node); + node = computeLayout.extractNodes(node); + return node; + }; +})); diff --git a/dist/css-layout.min.js b/dist/css-layout.min.js new file mode 100644 index 00000000..efe7fd66 --- /dev/null +++ b/dist/css-layout.min.js @@ -0,0 +1,2 @@ +!function(a,b){"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.computeLayout=b()}(this,function(){var a=function(){function a(a){return a.charAt(0).toUpperCase()+a.slice(1)}function b(b,c,d,e){for(var f=0;f0?b.children=a.children.map(d):delete a.children,delete b.right,delete b.bottom,delete b.direction,b}function e(b,c,d,e){for(var f=0;f=0)return b.style[h];if(h=c+d,h in b.style&&b.style[h]>=0)return b.style[h]}return 0}function f(a){return void 0===a}function g(a){return a===Y||a===Z}function h(a){return a===$||a===_}function i(a){var b=[ka[a]];return g(a)&&b.unshift("start"),b}function j(a){var b=[la[a]];return g(a)&&b.unshift("end"),b}function k(a,c){return b(a,"margin","",c)}function l(a,b){return k(a,i(b))}function m(a,b){return k(a,j(b))}function n(a,b){return e(a,"padding","",b)}function o(a,b){return n(a,i(b))}function p(a,b){return n(a,j(b))}function q(a,b){return e(a,"border","Width",b)}function r(a,b){return q(a,i(b))}function s(a,b){return q(a,j(b))}function t(a,b){return o(a,b)+r(a,b)}function u(a,b){return p(a,b)+s(a,b)}function v(a,b){return r(a,b)+s(a,b)}function w(a,b){return l(a,b)+m(a,b)}function x(a,b){return t(a,b)+u(a,b)}function y(a){return"justifyContent"in a.style?a.style.justifyContent:"flex-start"}function z(a){return"alignContent"in a.style?a.style.alignContent:"flex-start"}function A(a,b){return"alignSelf"in b.style?b.style.alignSelf:"alignItems"in a.style?a.style.alignItems:"stretch"}function B(a,b){if(b===X){if(a===Y)return Z;if(a===Z)return Y}return a}function C(a,b){var c;return c="direction"in a.style?a.style.direction:V,c===V&&(c=void 0===b?W:b),c}function D(a){return"flexDirection"in a.style?a.style.flexDirection:$}function E(a,b){return h(a)?B(Y,b):$}function F(a){return"position"in a.style?a.style.position:"relative"}function G(a){return a.style.flex}function H(a){return F(a)===ia&&G(a)>0}function I(a){return"wrap"===a.style.flexWrap}function J(a,b){return a.layout[na[b]]+w(a,b)}function K(a,b){return!f(a.style[na[b]])&&a.style[na[b]]>=0}function L(a,b){return!f(a.style[b])}function M(a){return"measure"in a.style}function N(a,b){return b in a.style?a.style[b]:0}function O(a,b,c){var d={row:a.style.minWidth,"row-reverse":a.style.minWidth,column:a.style.minHeight,"column-reverse":a.style.minHeight}[b],e={row:a.style.maxWidth,"row-reverse":a.style.maxWidth,column:a.style.maxHeight,"column-reverse":a.style.maxHeight}[b],g=c;return!f(e)&&e>=0&&g>e&&(g=e),!f(d)&&d>=0&&d>g&&(g=d),g}function P(a,b){return a>b?a:b}function Q(a,b){f(a.layout[na[b]])&&K(a,b)&&(a.layout[na[b]]=P(O(a,b,a.style[na[b]]),x(a,b)))}function R(a,b,c){b.layout[la[c]]=a.layout[na[c]]-b.layout[na[c]]-b.layout[ma[c]]}function S(a,b){return ka[b]in a.style?N(a,ka[b]):-N(a,la[b])}function T(a,b,c){var d=C(a,c),e=B(D(a),d),h=E(e,d),i=B(Y,d);if(Q(a,e),Q(a,h),a.layout.direction=d,a.layout[ka[e]]+=l(a,e)+S(a,e),a.layout[la[e]]+=m(a,e)+S(a,e),a.layout[ka[h]]+=l(a,h)+S(a,h),a.layout[la[h]]+=m(a,h)+S(a,h),M(a)){var j=U;j=K(a,i)?a.style.width:f(a.layout[na[i]])?b-w(a,i):a.layout[na[i]],j-=x(a,i);var k=!K(a,i)&&f(a.layout[na[i]]),n=!K(a,$)&&f(a.layout[na[$]]);if(k||n){var o=a.style.measure(j);k&&(a.layout.width=o.width+x(a,i)),n&&(a.layout.height=o.height+x(a,$))}if(0===a.children.length)return}var p,q,s,V;for(p=0;pq;q++)V=0!==q?Y:$,!f(a.layout[na[V]])&&!K(s,V)&&L(s,ka[V])&&L(s,la[V])&&(s.layout[na[V]]=P(O(s,V,a.layout[na[V]]-x(a,V)-w(s,V)-N(s,ka[V])-N(s,la[V])),x(s,V)))}else s.layout[na[h]]=P(O(s,h,a.layout[na[h]]-x(a,h)-w(s,h)),x(s,h));var W=U;f(a.layout[na[e]])||(W=a.layout[na[e]]-x(a,e));for(var X=0,Z=0,_=0,oa=0,pa=0,qa=0;ZW&&p!==X){va--,_=1;break}_=0,sa+=wa,Z=p+1}var xa=0,ya=0,za=0;if(za=f(a.layout[na[e]])?P(sa,0)-sa:W-sa,0!==ta){var Aa,Ba,Ca=za/ua;for(p=X;Z>p;++p)s=a.children[p],H(s)&&(Aa=Ca*G(s)+x(s,e),Ba=O(s,e,Aa),Aa!==Ba&&(za-=Ba,ua-=G(s)));for(Ca=za/ua,0>Ca&&(Ca=0),p=X;Z>p;++p)s=a.children[p],H(s)&&(s.layout[na[e]]=O(s,e,Ca*G(s)+x(s,e)),ra=U,K(a,i)?ra=a.layout[na[i]]-x(a,i):g(e)||(ra=b-w(a,i)-x(a,i)),T(s,ra,d))}else{var Da=y(a);Da===aa?xa=za/2:Da===ba?xa=za:Da===ca?(za=P(za,0),ya=ta+va-1!==0?za/(ta+va-1):0):Da===da&&(ya=za/(ta+va),xa=ya/2)}var Ea=0,Fa=xa+t(a,e);for(p=X;Z>p;++p)s=a.children[p],s.lineIndex=qa,F(s)===ja&&L(s,ka[e])?s.layout[ma[e]]=N(s,ka[e])+r(a,e)+l(s,e):(s.layout[ma[e]]+=Fa,f(a.layout[na[e]])||R(a,s,e)),F(s)===ia&&(Fa+=ya+J(s,e),Ea=P(Ea,O(s,h,J(s,h))));var Ga=a.layout[na[h]];for(f(a.layout[na[h]])&&(Ga=P(O(a,h,Ea+x(a,h)),x(a,h))),p=X;Z>p;++p)if(s=a.children[p],F(s)===ja&&L(s,ka[h]))s.layout[ma[h]]=N(s,ka[h])+r(a,h)+l(s,h);else{var Ha=t(a,h);if(F(s)===ia){var Ia=A(a,s);if(Ia===ha)K(s,h)||(s.layout[na[h]]=P(O(s,h,Ga-x(a,h)-w(s,h)),x(s,h)));else if(Ia!==ea){var Ja=Ga-x(a,h)-J(s,h);Ha+=Ia===fa?Ja/2:Ja}}s.layout[ma[h]]+=oa+Ha,f(a.layout[na[h]])||R(a,s,h)}oa+=Ea,pa=P(pa,Fa),qa+=1,X=Z}if(qa>1&&!f(a.layout[na[h]])){var Ka=a.layout[na[h]]-x(a,h),La=Ka-oa,Ma=0,Na=t(a,h),Oa=z(a);Oa===ga?Na+=La:Oa===fa?Na+=La/2:Oa===ha&&Ka>oa&&(Ma=La/qa);var Pa=0;for(p=0;qa>p;++p){var Qa=Pa,Ra=0;for(q=Qa;qq;++q)if(s=a.children[q],F(s)===ia){var Sa=A(a,s);if(Sa===ea)s.layout[ma[h]]=Na+l(s,h);else if(Sa===ga)s.layout[ma[h]]=Na+Ra-m(s,h)-s.layout[na[h]];else if(Sa===fa){var Ta=s.layout[na[h]];s.layout[ma[h]]=Na+(Ra-Ta)/2}else Sa===ha&&(s.layout[ma[h]]=Na+l(s,h))}Na+=Ra}}var Ua=!1,Va=!1;if(f(a.layout[na[e]])&&(a.layout[na[e]]=P(O(a,e,pa+u(a,e)),x(a,e)),Ua=!0),f(a.layout[na[h]])&&(a.layout[na[h]]=P(O(a,h,oa+x(a,h)),x(a,h)),Va=!0),Ua||Va)for(p=0;pq;q++)V=0!==q?Y:$,!f(a.layout[na[V]])&&!K(s,V)&&L(s,ka[V])&&L(s,la[V])&&(s.layout[na[V]]=P(O(s,V,a.layout[na[V]]-v(a,V)-w(s,V)-N(s,ka[V])-N(s,la[V])),x(s,V)));for(q=0;2>q;q++)V=0!==q?Y:$,L(s,la[V])&&!L(s,ka[V])&&(s.layout[ka[V]]=a.layout[na[V]]-s.layout[na[V]]-N(s,la[V]))}}var U,V="inherit",W="ltr",X="rtl",Y="row",Z="row-reverse",$="column",_="column-reverse",aa="center",ba="flex-end",ca="space-between",da="space-around",ea="flex-start",fa="center",ga="flex-end",ha="stretch",ia="relative",ja="absolute",ka={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},la={row:"right","row-reverse":"left",column:"bottom","column-reverse":"top"},ma={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},na={row:"width","row-reverse":"width",column:"height","column-reverse":"height"};return{computeLayout:T,fillNodes:c,extractNodes:d}}();return"object"==typeof exports&&(module.exports=a),function(b){return b=a.fillNodes(b),a.computeLayout(b),b=a.extractNodes(b)}}); +//# sourceMappingURL=css-layout.min.js.map \ No newline at end of file diff --git a/dist/css-layout.min.js.map b/dist/css-layout.min.js.map new file mode 100644 index 00000000..b4cdec24 --- /dev/null +++ b/dist/css-layout.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"css-layout.min.js","sources":["css-layout.js"],"names":["root","factory","define","amd","exports","module","computeLayout","this","capitalizeFirst","str","charAt","toUpperCase","slice","getSpacing","node","type","suffix","locations","i","length","location","key","style","fillNodes","layout","width","undefined","height","top","left","right","bottom","children","measure","forEach","extractNodes","map","direction","getPositiveSpacing","isUndefined","value","isRowDirection","flexDirection","CSS_FLEX_DIRECTION_ROW","CSS_FLEX_DIRECTION_ROW_REVERSE","isColumnDirection","CSS_FLEX_DIRECTION_COLUMN","CSS_FLEX_DIRECTION_COLUMN_REVERSE","getLeadingLocations","axis","leading","unshift","getTrailingLocations","trailing","getMargin","getLeadingMargin","getTrailingMargin","getPadding","getLeadingPadding","getTrailingPadding","getBorder","getLeadingBorder","getTrailingBorder","getLeadingPaddingAndBorder","getTrailingPaddingAndBorder","getBorderAxis","getMarginAxis","getPaddingAndBorderAxis","getJustifyContent","justifyContent","getAlignContent","alignContent","getAlignItem","child","alignSelf","alignItems","resolveAxis","CSS_DIRECTION_RTL","resolveDirection","parentDirection","CSS_DIRECTION_INHERIT","CSS_DIRECTION_LTR","getFlexDirection","getCrossFlexDirection","getPositionType","position","getFlex","flex","isFlex","CSS_POSITION_RELATIVE","isFlexWrap","flexWrap","getDimWithMargin","dim","isDimDefined","isPosDefined","pos","isMeasureDefined","getPosition","boundAxis","min","row","minWidth","row-reverse","column","minHeight","column-reverse","max","maxWidth","maxHeight","boundValue","fmaxf","a","b","setDimensionFromStyle","setTrailingPosition","getRelativePosition","layoutNode","parentMaxWidth","mainAxis","crossAxis","resolvedRowAxis","CSS_UNDEFINED","isRowUndefined","isColumnUndefined","measureDim","ii","CSS_ALIGN_STRETCH","CSS_POSITION_ABSOLUTE","definedMainDim","startLine","endLine","alreadyComputedNextLayout","linesCrossDim","linesMainDim","linesCount","mainContentDim","flexibleChildrenCount","totalFlexible","nonFlexibleChildrenCount","nextContentDim","leadingMainDim","betweenMainDim","remainingMainDim","baseMainDim","boundMainDim","flexibleMainDim","CSS_JUSTIFY_CENTER","CSS_JUSTIFY_FLEX_END","CSS_JUSTIFY_SPACE_BETWEEN","CSS_JUSTIFY_SPACE_AROUND","crossDim","mainDim","lineIndex","containerCrossAxis","leadingCrossDim","alignItem","CSS_ALIGN_FLEX_START","remainingCrossDim","CSS_ALIGN_CENTER","nodeCrossAxisInnerSize","remainingAlignContentDim","crossDimLead","currentLead","CSS_ALIGN_FLEX_END","endIndex","startIndex","lineHeight","alignContentAlignItem","childHeight","needsMainTrailingPos","needsCrossTrailingPos"],"mappings":"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","sourcesContent":["// UMD (Universal Module Definition)\n// See https://github.com/umdjs/umd for reference\n//\n// This file uses the following specific UMD implementation:\n// https://github.com/umdjs/umd/blob/master/returnExports.js\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define([], factory);\n } else if (typeof exports === 'object') {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory();\n } else {\n // Browser globals (root is window)\n root.computeLayout = factory();\n }\n}(this, function () {\n /**\n * Copyright (c) 2014, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nvar computeLayout = (function() {\n\n var CSS_UNDEFINED;\n\n var CSS_DIRECTION_INHERIT = 'inherit';\n var CSS_DIRECTION_LTR = 'ltr';\n var CSS_DIRECTION_RTL = 'rtl';\n\n var CSS_FLEX_DIRECTION_ROW = 'row';\n var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';\n var CSS_FLEX_DIRECTION_COLUMN = 'column';\n var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';\n\n // var CSS_JUSTIFY_FLEX_START = 'flex-start';\n var CSS_JUSTIFY_CENTER = 'center';\n var CSS_JUSTIFY_FLEX_END = 'flex-end';\n var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between';\n var CSS_JUSTIFY_SPACE_AROUND = 'space-around';\n\n var CSS_ALIGN_FLEX_START = 'flex-start';\n var CSS_ALIGN_CENTER = 'center';\n var CSS_ALIGN_FLEX_END = 'flex-end';\n var CSS_ALIGN_STRETCH = 'stretch';\n\n var CSS_POSITION_RELATIVE = 'relative';\n var CSS_POSITION_ABSOLUTE = 'absolute';\n\n var leading = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var trailing = {\n 'row': 'right',\n 'row-reverse': 'left',\n 'column': 'bottom',\n 'column-reverse': 'top'\n };\n var pos = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var dim = {\n 'row': 'width',\n 'row-reverse': 'width',\n 'column': 'height',\n 'column-reverse': 'height'\n };\n\n function capitalizeFirst(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n }\n\n function getSpacing(node, type, suffix, locations) {\n for (var i = 0; i < locations.length; ++i) {\n var location = locations[i];\n\n var key = type + capitalizeFirst(location) + suffix;\n if (key in node.style) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style) {\n return node.style[key];\n }\n }\n\n return 0;\n }\n function fillNodes(node) {\n node.layout = {\n width: undefined,\n height: undefined,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n };\n if (!node.style) {\n node.style = {};\n }\n\n if (!node.children || node.style.measure) {\n node.children = [];\n }\n node.children.forEach(fillNodes);\n return node;\n }\n\n function extractNodes(node) {\n var layout = node.layout;\n delete node.layout;\n if (node.children && node.children.length > 0) {\n layout.children = node.children.map(extractNodes);\n } else {\n delete node.children;\n }\n\n delete layout.right;\n delete layout.bottom;\n delete layout.direction;\n\n return layout;\n }\n\n function getPositiveSpacing(node, type, suffix, locations) {\n for (var i = 0; i < locations.length; ++i) {\n var location = locations[i];\n\n var key = type + capitalizeFirst(location) + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n }\n\n return 0;\n }\n\n function isUndefined(value) {\n return value === undefined;\n }\n\n function isRowDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_ROW ||\n flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;\n }\n\n function isColumnDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||\n flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;\n }\n\n function getLeadingLocations(axis) {\n var locations = [leading[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('start');\n }\n\n return locations;\n }\n\n function getTrailingLocations(axis) {\n var locations = [trailing[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('end');\n }\n\n return locations;\n }\n\n function getMargin(node, locations) {\n return getSpacing(node, 'margin', '', locations);\n }\n\n function getLeadingMargin(node, axis) {\n return getMargin(node, getLeadingLocations(axis));\n }\n\n function getTrailingMargin(node, axis) {\n return getMargin(node, getTrailingLocations(axis));\n }\n\n function getPadding(node, locations) {\n return getPositiveSpacing(node, 'padding', '', locations);\n }\n\n function getLeadingPadding(node, axis) {\n return getPadding(node, getLeadingLocations(axis));\n }\n\n function getTrailingPadding(node, axis) {\n return getPadding(node, getTrailingLocations(axis));\n }\n\n function getBorder(node, locations) {\n return getPositiveSpacing(node, 'border', 'Width', locations);\n }\n\n function getLeadingBorder(node, axis) {\n return getBorder(node, getLeadingLocations(axis));\n }\n\n function getTrailingBorder(node, axis) {\n return getBorder(node, getTrailingLocations(axis));\n }\n\n function getLeadingPaddingAndBorder(node, axis) {\n return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);\n }\n\n function getTrailingPaddingAndBorder(node, axis) {\n return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);\n }\n\n function getBorderAxis(node, axis) {\n return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);\n }\n\n function getMarginAxis(node, axis) {\n return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);\n }\n\n function getPaddingAndBorderAxis(node, axis) {\n return getLeadingPaddingAndBorder(node, axis) +\n getTrailingPaddingAndBorder(node, axis);\n }\n\n function getJustifyContent(node) {\n if ('justifyContent' in node.style) {\n return node.style.justifyContent;\n }\n return 'flex-start';\n }\n\n function getAlignContent(node) {\n if ('alignContent' in node.style) {\n return node.style.alignContent;\n }\n return 'flex-start';\n }\n\n function getAlignItem(node, child) {\n if ('alignSelf' in child.style) {\n return child.style.alignSelf;\n }\n if ('alignItems' in node.style) {\n return node.style.alignItems;\n }\n return 'stretch';\n }\n\n function resolveAxis(axis, direction) {\n if (direction === CSS_DIRECTION_RTL) {\n if (axis === CSS_FLEX_DIRECTION_ROW) {\n return CSS_FLEX_DIRECTION_ROW_REVERSE;\n } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {\n return CSS_FLEX_DIRECTION_ROW;\n }\n }\n\n return axis;\n }\n\n function resolveDirection(node, parentDirection) {\n var direction;\n if ('direction' in node.style) {\n direction = node.style.direction;\n } else {\n direction = CSS_DIRECTION_INHERIT;\n }\n\n if (direction === CSS_DIRECTION_INHERIT) {\n direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection);\n }\n\n return direction;\n }\n\n function getFlexDirection(node) {\n if ('flexDirection' in node.style) {\n return node.style.flexDirection;\n }\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n\n function getCrossFlexDirection(flexDirection, direction) {\n if (isColumnDirection(flexDirection)) {\n return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n } else {\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n }\n\n function getPositionType(node) {\n if ('position' in node.style) {\n return node.style.position;\n }\n return 'relative';\n }\n\n function getFlex(node) {\n return node.style.flex;\n }\n\n function isFlex(node) {\n return (\n getPositionType(node) === CSS_POSITION_RELATIVE &&\n getFlex(node) > 0\n );\n }\n\n function isFlexWrap(node) {\n return node.style.flexWrap === 'wrap';\n }\n\n function getDimWithMargin(node, axis) {\n return node.layout[dim[axis]] + getMarginAxis(node, axis);\n }\n\n function isDimDefined(node, axis) {\n return !isUndefined(node.style[dim[axis]]) && node.style[dim[axis]] >= 0;\n }\n\n function isPosDefined(node, pos) {\n return !isUndefined(node.style[pos]);\n }\n\n function isMeasureDefined(node) {\n return 'measure' in node.style;\n }\n\n function getPosition(node, pos) {\n if (pos in node.style) {\n return node.style[pos];\n }\n return 0;\n }\n\n function boundAxis(node, axis, value) {\n var min = {\n 'row': node.style.minWidth,\n 'row-reverse': node.style.minWidth,\n 'column': node.style.minHeight,\n 'column-reverse': node.style.minHeight\n }[axis];\n\n var max = {\n 'row': node.style.maxWidth,\n 'row-reverse': node.style.maxWidth,\n 'column': node.style.maxHeight,\n 'column-reverse': node.style.maxHeight\n }[axis];\n\n var boundValue = value;\n if (!isUndefined(max) && max >= 0 && boundValue > max) {\n boundValue = max;\n }\n if (!isUndefined(min) && min >= 0 && boundValue < min) {\n boundValue = min;\n }\n return boundValue;\n }\n\n function fmaxf(a, b) {\n if (a > b) {\n return a;\n }\n return b;\n }\n\n // When the user specifically sets a value for width or height\n function setDimensionFromStyle(node, axis) {\n // The parent already computed us a width or height. We just skip it\n if (!isUndefined(node.layout[dim[axis]])) {\n return;\n }\n // We only run if there's a width or height defined\n if (!isDimDefined(node, axis)) {\n return;\n }\n\n // The dimensions can never be smaller than the padding and border\n node.layout[dim[axis]] = fmaxf(\n boundAxis(node, axis, node.style[dim[axis]]),\n getPaddingAndBorderAxis(node, axis)\n );\n }\n\n function setTrailingPosition(node, child, axis) {\n child.layout[trailing[axis]] = node.layout[dim[axis]] -\n child.layout[dim[axis]] - child.layout[pos[axis]];\n }\n\n // If both left and right are defined, then use left. Otherwise return\n // +left or -right depending on which is defined.\n function getRelativePosition(node, axis) {\n if (leading[axis] in node.style) {\n return getPosition(node, leading[axis]);\n }\n return -getPosition(node, trailing[axis]);\n }\n\n function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) {\n var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);\n var/*css_flex_direction_t*/ mainAxis = resolveAxis(getFlexDirection(node), direction);\n var/*css_flex_direction_t*/ crossAxis = getCrossFlexDirection(mainAxis, direction);\n var/*css_flex_direction_t*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n\n // Handle width and height style attributes\n setDimensionFromStyle(node, mainAxis);\n setDimensionFromStyle(node, crossAxis);\n\n // Set the resolved resolution in the node's layout\n node.layout.direction = direction;\n\n // The position is set by the parent, but we need to complete it with a\n // delta composed of the margin and left/top/right/bottom\n node.layout[leading[mainAxis]] += getLeadingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[leading[crossAxis]] += getLeadingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n node.layout[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n\n if (isMeasureDefined(node)) {\n var/*float*/ width = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n width = node.style.width;\n } else if (!isUndefined(node.layout[dim[resolvedRowAxis]])) {\n width = node.layout[dim[resolvedRowAxis]];\n } else {\n width = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis);\n }\n width -= getPaddingAndBorderAxis(node, resolvedRowAxis);\n\n // We only need to give a dimension for the text if we haven't got any\n // for it computed yet. It can either be from the style attribute or because\n // the element is flexible.\n var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&\n isUndefined(node.layout[dim[resolvedRowAxis]]);\n var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&\n isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);\n\n // Let's not measure the text if we already know both dimensions\n if (isRowUndefined || isColumnUndefined) {\n var/*css_dim_t*/ measureDim = node.style.measure(\n /*(c)!node->context,*/\n /*(java)!layoutContext.measureOutput,*/\n width\n );\n if (isRowUndefined) {\n node.layout.width = measureDim.width +\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n }\n if (isColumnUndefined) {\n node.layout.height = measureDim.height +\n getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n }\n }\n if (node.children.length === 0) {\n return;\n }\n }\n\n var/*int*/ i;\n var/*int*/ ii;\n var/*css_node_t**/ child;\n var/*css_flex_direction_t*/ axis;\n\n // Pre-fill some dimensions straight from the parent\n for (i = 0; i < node.children.length; ++i) {\n child = node.children[i];\n // Pre-fill cross axis dimensions when the child is using stretch before\n // we call the recursive layout pass\n if (getAlignItem(node, child) === CSS_ALIGN_STRETCH &&\n getPositionType(child) === CSS_POSITION_RELATIVE &&\n !isUndefined(node.layout[dim[crossAxis]]) &&\n !isDimDefined(child, crossAxis)) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, node.layout[dim[crossAxis]] -\n getPaddingAndBorderAxis(node, crossAxis) -\n getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both\n // left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(child, axis) &&\n isPosDefined(child, leading[axis]) &&\n isPosDefined(child, trailing[axis])) {\n child.layout[dim[axis]] = fmaxf(\n boundAxis(child, axis, node.layout[dim[axis]] -\n getPaddingAndBorderAxis(node, axis) -\n getMarginAxis(child, axis) -\n getPosition(child, leading[axis]) -\n getPosition(child, trailing[axis])),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, axis)\n );\n }\n }\n }\n }\n\n var/*float*/ definedMainDim = CSS_UNDEFINED;\n if (!isUndefined(node.layout[dim[mainAxis]])) {\n definedMainDim = node.layout[dim[mainAxis]] -\n getPaddingAndBorderAxis(node, mainAxis);\n }\n\n // We want to execute the next two loops one per line with flex-wrap\n var/*int*/ startLine = 0;\n var/*int*/ endLine = 0;\n // var/*int*/ nextOffset = 0;\n var/*int*/ alreadyComputedNextLayout = 0;\n // We aggregate the total dimensions of the container in those two variables\n var/*float*/ linesCrossDim = 0;\n var/*float*/ linesMainDim = 0;\n var/*int*/ linesCount = 0;\n while (endLine < node.children.length) {\n // Layout non flexible children and count children by type\n\n // mainContentDim is accumulation of the dimensions and margin of all the\n // non flexible children. This will be used in order to either set the\n // dimensions of the node if none already exist, or to compute the\n // remaining space left for the flexible children.\n var/*float*/ mainContentDim = 0;\n\n // There are three kind of children, non flexible, flexible and absolute.\n // We need to know how many there are in order to distribute the space.\n var/*int*/ flexibleChildrenCount = 0;\n var/*float*/ totalFlexible = 0;\n var/*int*/ nonFlexibleChildrenCount = 0;\n\n var/*float*/ maxWidth;\n for (i = startLine; i < node.children.length; ++i) {\n child = node.children[i];\n var/*float*/ nextContentDim = 0;\n\n // It only makes sense to consider a child flexible if we have a computed\n // dimension for the node.\n if (!isUndefined(node.layout[dim[mainAxis]]) && isFlex(child)) {\n flexibleChildrenCount++;\n totalFlexible += getFlex(child);\n\n // Even if we don't know its exact size yet, we already know the padding,\n // border and margin. We'll use this partial information, which represents\n // the smallest possible size for the child, to compute the remaining\n // available space.\n nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +\n getMarginAxis(child, mainAxis);\n\n } else {\n maxWidth = CSS_UNDEFINED;\n if (!isRowDirection(mainAxis)) {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n }\n }\n\n // This is the main recursive call. We layout non flexible children.\n if (alreadyComputedNextLayout === 0) {\n layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);\n }\n\n // Absolute positioned elements do not take part of the layout, so we\n // don't use them to compute mainContentDim\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n nonFlexibleChildrenCount++;\n // At this point we know the final size and margin of the element.\n nextContentDim = getDimWithMargin(child, mainAxis);\n }\n }\n\n // The element we are about to add would make us go to the next line\n if (isFlexWrap(node) &&\n !isUndefined(node.layout[dim[mainAxis]]) &&\n mainContentDim + nextContentDim > definedMainDim &&\n // If there's only one element, then it's bigger than the content\n // and needs its own line\n i !== startLine) {\n nonFlexibleChildrenCount--;\n alreadyComputedNextLayout = 1;\n break;\n }\n alreadyComputedNextLayout = 0;\n mainContentDim += nextContentDim;\n endLine = i + 1;\n }\n\n // Layout flexible children and allocate empty space\n\n // In order to position the elements in the main axis, we have two\n // controls. The space between the beginning and the first element\n // and the space between each two elements.\n var/*float*/ leadingMainDim = 0;\n var/*float*/ betweenMainDim = 0;\n\n // The remaining available space that needs to be allocated\n var/*float*/ remainingMainDim = 0;\n if (!isUndefined(node.layout[dim[mainAxis]])) {\n remainingMainDim = definedMainDim - mainContentDim;\n } else {\n remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;\n }\n\n // If there are flexible children in the mix, they are going to fill the\n // remaining space\n if (flexibleChildrenCount !== 0) {\n var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible;\n var/*float*/ baseMainDim;\n var/*float*/ boundMainDim;\n\n // Iterate over every child in the axis. If the flex share of remaining\n // space doesn't meet min/max bounds, remove this child from flex\n // calculations.\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n if (isFlex(child)) {\n baseMainDim = flexibleMainDim * getFlex(child) +\n getPaddingAndBorderAxis(child, mainAxis);\n boundMainDim = boundAxis(child, mainAxis, baseMainDim);\n\n if (baseMainDim !== boundMainDim) {\n remainingMainDim -= boundMainDim;\n totalFlexible -= getFlex(child);\n }\n }\n }\n flexibleMainDim = remainingMainDim / totalFlexible;\n\n // The non flexible children can overflow the container, in this case\n // we should just assume that there is no space available.\n if (flexibleMainDim < 0) {\n flexibleMainDim = 0;\n }\n // We iterate over the full array and only apply the action on flexible\n // children. This is faster than actually allocating a new array that\n // contains only flexible children.\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n if (isFlex(child)) {\n // At this point we know the final size of the element in the main\n // dimension\n child.layout[dim[mainAxis]] = boundAxis(child, mainAxis,\n flexibleMainDim * getFlex(child) + getPaddingAndBorderAxis(child, mainAxis)\n );\n\n maxWidth = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n } else if (!isRowDirection(mainAxis)) {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n }\n\n // And we recursively call the layout algorithm for this child\n layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);\n }\n }\n\n // We use justifyContent to figure out how to allocate the remaining\n // space available\n } else {\n var/*css_justify_t*/ justifyContent = getJustifyContent(node);\n if (justifyContent === CSS_JUSTIFY_CENTER) {\n leadingMainDim = remainingMainDim / 2;\n } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {\n leadingMainDim = remainingMainDim;\n } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {\n remainingMainDim = fmaxf(remainingMainDim, 0);\n if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) {\n betweenMainDim = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount - 1);\n } else {\n betweenMainDim = 0;\n }\n } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) {\n // Space on the edges is half of the space between elements\n betweenMainDim = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount);\n leadingMainDim = betweenMainDim / 2;\n }\n }\n\n // Position elements in the main axis and compute dimensions\n\n // At this point, all the children have their dimensions set. We need to\n // find their position. In order to do that, we accumulate data in\n // variables that are also useful to compute the total dimensions of the\n // container!\n var/*float*/ crossDim = 0;\n var/*float*/ mainDim = leadingMainDim +\n getLeadingPaddingAndBorder(node, mainAxis);\n\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n child.lineIndex = linesCount;\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[mainAxis])) {\n // In case the child is position absolute and has left/top being\n // defined, we override the position to whatever the user said\n // (and margin/border).\n child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +\n getLeadingBorder(node, mainAxis) +\n getLeadingMargin(child, mainAxis);\n } else {\n // If the child is position absolute (without top/left) or relative,\n // we put it at the current accumulated offset.\n child.layout[pos[mainAxis]] += mainDim;\n\n // Define the trailing position accordingly.\n if (!isUndefined(node.layout[dim[mainAxis]])) {\n setTrailingPosition(node, child, mainAxis);\n }\n }\n\n // Now that we placed the element, we need to update the variables\n // We only need to do that for relative elements. Absolute elements\n // do not take part in that phase.\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n // The main dimension is the sum of all the elements dimension plus\n // the spacing.\n mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);\n // The cross dimension is the max of the elements dimension since there\n // can only be one element in that cross dimension.\n crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));\n }\n }\n\n var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]];\n if (isUndefined(node.layout[dim[crossAxis]])) {\n containerCrossAxis = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, crossDim + getPaddingAndBorderAxis(node, crossAxis)),\n getPaddingAndBorderAxis(node, crossAxis)\n );\n }\n\n // Position elements in the cross axis\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[crossAxis])) {\n // In case the child is absolutely positionned and has a\n // top/left/bottom/right being set, we override all the previously\n // computed positions to set it correctly.\n child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +\n getLeadingBorder(node, crossAxis) +\n getLeadingMargin(child, crossAxis);\n\n } else {\n var/*float*/ leadingCrossDim = getLeadingPaddingAndBorder(node, crossAxis);\n\n // For a relative children, we're either using alignItems (parent) or\n // alignSelf (child) in order to determine the position in the cross axis\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n if (alignItem === CSS_ALIGN_STRETCH) {\n // You can only stretch if the dimension has not already been set\n // previously.\n if (!isDimDefined(child, crossAxis)) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, containerCrossAxis -\n getPaddingAndBorderAxis(node, crossAxis) -\n getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n }\n } else if (alignItem !== CSS_ALIGN_FLEX_START) {\n // The remaining space between the parent dimensions+padding and child\n // dimensions+margin.\n var/*float*/ remainingCrossDim = containerCrossAxis -\n getPaddingAndBorderAxis(node, crossAxis) -\n getDimWithMargin(child, crossAxis);\n\n if (alignItem === CSS_ALIGN_CENTER) {\n leadingCrossDim += remainingCrossDim / 2;\n } else { // CSS_ALIGN_FLEX_END\n leadingCrossDim += remainingCrossDim;\n }\n }\n }\n\n // And we apply the position\n child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim;\n\n // Define the trailing position accordingly.\n if (!isUndefined(node.layout[dim[crossAxis]])) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n\n linesCrossDim += crossDim;\n linesMainDim = fmaxf(linesMainDim, mainDim);\n linesCount += 1;\n startLine = endLine;\n }\n\n // \n //\n // Note(prenaux): More than one line, we need to layout the crossAxis\n // according to alignContent.\n //\n // Note that we could probably remove and handle the one line case\n // here too, but for the moment this is safer since it won't interfere with\n // previously working code.\n //\n // See specs:\n // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm\n // section 9.4\n //\n if (linesCount > 1 &&\n !isUndefined(node.layout[dim[crossAxis]])) {\n var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] -\n getPaddingAndBorderAxis(node, crossAxis);\n var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;\n\n var/*float*/ crossDimLead = 0;\n var/*float*/ currentLead = getLeadingPaddingAndBorder(node, crossAxis);\n\n var/*css_align_t*/ alignContent = getAlignContent(node);\n if (alignContent === CSS_ALIGN_FLEX_END) {\n currentLead += remainingAlignContentDim;\n } else if (alignContent === CSS_ALIGN_CENTER) {\n currentLead += remainingAlignContentDim / 2;\n } else if (alignContent === CSS_ALIGN_STRETCH) {\n if (nodeCrossAxisInnerSize > linesCrossDim) {\n crossDimLead = (remainingAlignContentDim / linesCount);\n }\n }\n\n var/*int*/ endIndex = 0;\n for (i = 0; i < linesCount; ++i) {\n var/*int*/ startIndex = endIndex;\n\n // compute the line's height and find the endIndex\n var/*float*/ lineHeight = 0;\n for (ii = startIndex; ii < node.children.length; ++ii) {\n child = node.children[ii];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n if (child.lineIndex !== i) {\n break;\n }\n if (!isUndefined(child.layout[dim[crossAxis]])) {\n lineHeight = fmaxf(\n lineHeight,\n child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis)\n );\n }\n }\n endIndex = ii;\n lineHeight += crossDimLead;\n\n for (ii = startIndex; ii < endIndex; ++ii) {\n child = node.children[ii];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n\n var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child);\n if (alignContentAlignItem === CSS_ALIGN_FLEX_START) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) {\n child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[dim[crossAxis]];\n } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {\n var/*float*/ childHeight = child.layout[dim[crossAxis]];\n child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;\n } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n // TODO(prenaux): Correctly set the height of items with undefined\n // (auto) crossAxis dimension.\n }\n }\n\n currentLead += lineHeight;\n }\n }\n\n var/*bool*/ needsMainTrailingPos = false;\n var/*bool*/ needsCrossTrailingPos = false;\n\n // If the user didn't specify a width or height, and it has not been set\n // by the container, then we set it via the children.\n if (isUndefined(node.layout[dim[mainAxis]])) {\n node.layout[dim[mainAxis]] = fmaxf(\n // We're missing the last padding at this point to get the final\n // dimension\n boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),\n // We can never assign a width smaller than the padding and borders\n getPaddingAndBorderAxis(node, mainAxis)\n );\n\n needsMainTrailingPos = true;\n }\n\n if (isUndefined(node.layout[dim[crossAxis]])) {\n node.layout[dim[crossAxis]] = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, linesCrossDim + getPaddingAndBorderAxis(node, crossAxis)),\n getPaddingAndBorderAxis(node, crossAxis)\n );\n\n needsCrossTrailingPos = true;\n }\n\n // Set trailing position if necessary\n if (needsMainTrailingPos || needsCrossTrailingPos) {\n for (i = 0; i < node.children.length; ++i) {\n child = node.children[i];\n\n if (needsMainTrailingPos) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n if (needsCrossTrailingPos) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n\n // Calculate dimensions for absolutely positioned elements\n for (i = 0; i < node.children.length; ++i) {\n child = node.children[i];\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both\n // left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(child, axis) &&\n isPosDefined(child, leading[axis]) &&\n isPosDefined(child, trailing[axis])) {\n child.layout[dim[axis]] = fmaxf(\n boundAxis(child, axis, node.layout[dim[axis]] -\n getBorderAxis(node, axis) -\n getMarginAxis(child, axis) -\n getPosition(child, leading[axis]) -\n getPosition(child, trailing[axis])\n ),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, axis)\n );\n }\n }\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (isPosDefined(child, trailing[axis]) &&\n !isPosDefined(child, leading[axis])) {\n child.layout[leading[axis]] =\n node.layout[dim[axis]] -\n child.layout[dim[axis]] -\n getPosition(child, trailing[axis]);\n }\n }\n }\n }\n }\n\n return {\n computeLayout: layoutNode,\n fillNodes: fillNodes,\n extractNodes: extractNodes\n };\n})();\n\nif (typeof exports === 'object') {\n module.exports = computeLayout;\n}\n\n return function(node) {\n node = computeLayout.fillNodes(node);\n computeLayout.computeLayout(node);\n node = computeLayout.extractNodes(node);\n return node;\n };\n}));\n"]} \ No newline at end of file diff --git a/src/Layout.js b/src/Layout.js index 4c1ca6f6..f5ee1953 100755 --- a/src/Layout.js +++ b/src/Layout.js @@ -985,3 +985,7 @@ var computeLayout = (function() { extractNodes: extractNodes }; })(); + +if (typeof exports === 'object') { + module.exports = computeLayout; +} \ No newline at end of file