From ae37366f1b03740b795fb5ed68447bb60840f540 Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Fri, 1 Jan 2016 12:31:41 -0500 Subject: [PATCH] stylus helpers: add wfpl_columns() --- stylus_helpers.styl | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) diff --git a/stylus_helpers.styl b/stylus_helpers.styl index bc73f95..e6df86e 100644 --- a/stylus_helpers.styl +++ b/stylus_helpers.styl @@ -239,3 +239,204 @@ noselect() -moz-user-select: none -ms-user-select: none user-select: none + +// Do all the crazy math to get columns to fit properly +// and (optionally) scale for responsive designs. +// +// example: +// +// columns = wfpl_columns({ +// type: 'node', +// name: 'centerer', +// margin: 15px, +// width: 940px, +// child: { +// type: 'node', +// name: 'middler', +// border-width: 1px, +// border-style: solid, +// border-color: black, +// padding-left: 30px, +// padding-right: 18px, +// child: { +// type: 'alternatives', +// full: { +// type: 'series', +// nav: { +// type: 'node' +// width: 219px +// float: left +// }, +// main: { +// type: 'node' +// margin-left: 48px, +// width: 623px +// float: left +// } +// }, +// with_sidebar: { +// type: 'series', +// nav: { +// type: 'node', +// width: 219px +// float: left +// }, +// main: { +// type: 'node', +// margin-left: 48px, +// width: 343px +// float: left +// }, +// sidebar: { +// type: 'alternatives', +// plain: { +// type: 'node' +// margin-left: 30px, +// width: 250px +// float: left +// }, +// bordered: { +// type: 'node' +// margin-left: 30px, +// border-width: 1px, +// border-style: solid +// border-color: red +// padding: 15px, +// width: 218px +// float: left +// } +// } +// } +// } +// } +// }) +// output css from column calculations +// for selector, css in columns.css +// body > {selector} +// {css} +// @media screen and (max-width: (columns.width)) +// // output responsive css from column calculations +// for selector, css in columns.responsive_css +// body > {selector} +// {css} +// +// // as big as it can be +// body > .centerer +// width: auto +// +// // make sure that borders (which won't scale) and rounding errors don't +// // break the layout +// body > .centerer.full > .main, +// body > .centerer.with_sidebar > .sidebar.plain, +// body > .centerer.with_sidebar > .sidebar.bordered +// margin-right: -10px +// +// // switch to 1-column layout +// @media screen and (max-width: (single_column_max)) +// for selector, css in columns.css +// body > {selector} +// if selector == '.centerer' +// margin-top: 0 +// else if selector in hide_in_one_column_mode +// display: none +// else +// border: none +// float: none +// width: auto +// margin: 0 +// padding: 0 +// margin-top: columns['responsive_css']['.centerer']['margin'] +wfpl_columns_helper(top, node, selector, parent_width, expected_width) + css_rules = {} + responsive_css_rules = {} + if node.type == 'node' + left_width = 0px + right_width = 0px + width = null // inner + outer_width = null + if node.name + if selector == '' + selector = '.' + node.name + else + selector += ' > .' + node.name + // callculate width and outer_width + for k, v in node + if match('^(margin|padding|border-width)$', k) + left_width += v + right_width += v + if match('^((margin|padding)-left)|(border-left-width)$', k) + left_width += v + if match('^((margin|padding)-right)|(border-right-width)$', k) + right_width += v + if k != 'type' && k != 'child' && k != 'name' && k != 'outer-width' && k != 'outer_width' + css_rules[k] = v + for k, v in node + if k == 'width' + width = v + outer_width = left_width + v + right_width + if k == 'outer-width' && k == 'outer_width' + outer_width = k + width = v - left_width - right_width + if (!width) && (!outer_width) + if parent_width + outer_width = parent_width + else + error("Couldn't figure out width of " + selector); + if outer_width && !width + width = outer_width - left_width - right_width + if width && !outer_width + outer_width = width + left_width + right_width + unless parent_width // should only happen at top level + parent_width = outer_width + top['css'][selector] = css_rules + for k, v in node + if k != 'outer-width' && k != 'outer_width' && k != 'border-width' && k != 'border-left-width' && k != 'border-right-width' + if typeof(v) == 'unit' && unit(v) == 'px' + responsive_css_rules[k] = floor(unit((v / parent_width) * 100, '%'), 4) + top['responsive_css'][selector] = responsive_css_rules + if 'child' in node + child_width = wfpl_columns_helper(top, node.child, selector, width, width) + _columns_recurser(rargs) + if child_width != width + error(selector + " is the is wrong width. Expected: " + width + ", got: " + rargs.ret.w) + top['widths'][selector] = width + return outer_width + if node.type == 'alternatives' + for name, child in node + if name != 'type' + child_selector = selector + '.' + name + child_width = wfpl_columns_helper(top, child, child_selector, parent_width, expected_width) + if expected_width + if child_width != expected_width + error(child_selector + " is wrong width. Expected: " + expected_width + ", got: " + child_width) + else + expected_width = child_width + unless parent_width + parent_width = child_width + return expected_width + if node.type == 'series' + series_width = 0px + for name, child in node + if name != 'type' + if selector == '' + child_selector = '.' + name + else + child_selector = selector + ' > .' + name + child_width = wfpl_columns_helper(top, child, child_selector, parent_width, null) + series_width += child_width + if expected_width + if series_width != expected_width + error(selector + " series total wrong. expected: " + expected_width + ", got: " + series_width); + return series_width + return // never reached with valid data + +wfpl_columns(hash) + top = { // contains settings, and is returned from porcelain + responsive: responsive + width: null + css: {} + responsive_css: {} + widths: {} + } + top.width = wfpl_columns_helper(top, hash, '', null, null) + return top -- 1.7.10.4