From a5cf03e8c557ee95769e351835910ad0114f5503 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Wed, 28 Sep 2016 16:53:40 -0400 Subject: [PATCH 1/2] Add vmax support --- README.md | 7 +-- test.css | 4 +- vminpoly.coffee | 28 ++++++++-- vminpoly.js | 137 ++++++++++++++++++++++++++---------------------- 4 files changed, 105 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index f674b40..3bf7162 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ vminpoly ======== -A polyfill for CSS units vw, vh & vmin. +A polyfill for CSS units vw, vh, vmin, & vmax. -Simple online [demo](http://saabi.github.com/vminpoly) right here. A more sophisticated [responsive demo](http://saabi.github.com/vminpoly/demo2.html) demonstrating vw/vh/vmin units along with *media queries*, working right down to IE5.5 on the desktop and Opera Mini on mobiles!! (In Opera Mini the browser must be refreshed after changing phone orientations as it appears it doesn't trigger the window resize event) +Simple online [demo](http://saabi.github.com/vminpoly) right here. A more sophisticated [responsive demo](http://saabi.github.com/vminpoly/demo2.html) demonstrating vw/vh/vmin/vmax units along with *media queries*, working right down to IE5.5 on the desktop and Opera Mini on mobiles!! (In Opera Mini the browser must be refreshed after changing phone orientations as it appears it doesn't trigger the window resize event) This is a working proof of concept right now. There's a lot of cleanup to do on the code. -Since most browsers ignore rules they don't understand, the code must load and parse the original CSS sourcecode. It does this using a javascript [CSS parser](https://github.com/tabatkins/css-parser). Once this is done, it filters the generated tree leaving only rules that use 'vh', 'vw' & 'vmin' units. +Since most browsers ignore rules they don't understand, the code must load and parse the original CSS sourcecode. It does this using a javascript [CSS parser](https://github.com/tabatkins/css-parser). Once this is done, it filters the generated tree leaving only rules that use 'vh', 'vw', 'vmin' & 'vmax' units. At window resize time, it generates CSS code for the 'px' equivalents and appends it in a 'style' element at the end of the 'head' element. The generated code respects media queries. As it is, it's fast enough for a lot of cases, but the code can still be optimized greatly, both in parsing and in resizing. @@ -33,6 +33,7 @@ In short, the only browser with apparently full native support right now is Fire Latest Changes: --------------- +* Added vmax unit support! * After some bug fixes it finally works down to **IE5.5 on the desktop** and **Opera Mini on mobile**!! * Also, I removed the dependency on jQuery. * Now resizes correctly right after page load. diff --git a/test.css b/test.css index 454c0f9..548e558 100644 --- a/test.css +++ b/test.css @@ -6,6 +6,6 @@ left:4vw; width:50vmin; height:50vmin; - font-size:3vmin; + font-size:3vmax; border:1vw solid black; -} \ No newline at end of file +} diff --git a/vminpoly.coffee b/vminpoly.coffee index 2ca9b97..5b50af6 100644 --- a/vminpoly.coffee +++ b/vminpoly.coffee @@ -67,7 +67,7 @@ browserSupportsUnitsNatively = -> head = document.getElementsByTagName('head')[0] head.appendChild style_block - test_results = testVWSupport(test_element, style_block) and testVWSupport(test_element, style_block) and testVMinSupport(test_element, style_block) + test_results = testVWSupport(test_element, style_block) and testVWSupport(test_element, style_block) and testVMinSupport(test_element, style_block) and testVMaxSupport(test_element, style_block) body.removeChild test_element head.removeChild style_block @@ -147,13 +147,34 @@ testVMinSupport = (element, style_block) -> # return result actual_vmin is comp_width +testVMaxSupport = (element, style_block) -> + # Set width of the element + applyStyleTest(style_block, 'width: 50vmax') + + # docElement has to be defined, can you believe it + docElement = document.documentElement + + # find maximum calculation sizes + one_vw = docElement.clientWidth / 100 + one_vh = docElement.clientHeight / 100 + actual_vmax = parseInt(Math.max(one_vw, one_vh)*50,10) + + # Computed width + comp_width = parseInt(testElementStyle(element).width, 10) + + # Remove current test style + clearStyleTests style_block + + # return result + actual_vmax is comp_width + initLayoutEngine = () -> analyzeStyleRule = (rule) -> declarations = [] for declaration in rule.value hasDimension = false for token in declaration.value - if token.tokenType is 'DIMENSION' and (token.unit is 'vmin' or token.unit is 'vh' or token.unit is 'vw') + if token.tokenType is 'DIMENSION' and (token.unit is 'vmin' or token.unit is 'vh' or token.unit is 'vw' or token.unit is 'vmax') hasDimension = true if hasDimension declarations.push declaration @@ -181,6 +202,7 @@ initLayoutEngine = () -> vh: vpDims.height / 100 vw: vpDims.width / 100 dims.vmin = Math.min dims.vh, dims.vw + dims.vmax = Math.max dims.vh, dims.vw vpAspectRatio = vpDims.width / vpDims.height @@ -202,7 +224,7 @@ initLayoutEngine = () -> ruleCss += declaration.name ruleCss += ":" for token in declaration.value - if token.tokenType is 'DIMENSION' and (token.unit is 'vmin' or token.unit is 'vh' or token.unit is 'vw') + if token.tokenType is 'DIMENSION' and (token.unit is 'vmin' or token.unit is 'vh' or token.unit is 'vw' or token.unit is 'vmax') ruleCss += "#{Math.floor(token.num*dims[token.unit])}px" else ruleCss += token.toSourceString() diff --git a/vminpoly.js b/vminpoly.js index 91d5a2a..3923d8e 100644 --- a/vminpoly.js +++ b/vminpoly.js @@ -1,6 +1,6 @@ -// Generated by CoffeeScript 1.7.1 +// Generated by CoffeeScript 1.11.0 (function() { - var XMLHttpFactories, ajax, applyStyleTest, browserSupportsUnitsNatively, clearStyleTests, createXMLHTTPObject, getViewportSize, initLayoutEngine, testElementStyle, testVHSupport, testVMinSupport, testVWSupport; + var XMLHttpFactories, ajax, applyStyleTest, browserSupportsUnitsNatively, clearStyleTests, createXMLHTTPObject, getViewportSize, initLayoutEngine, testElementStyle, testVHSupport, testVMaxSupport, testVMinSupport, testVWSupport; XMLHttpFactories = [ function() { @@ -21,8 +21,8 @@ while (i < XMLHttpFactories.length) { try { xmlhttp = XMLHttpFactories[i++](); - } catch (_error) { - e = _error; + } catch (error) { + e = error; continue; } break; @@ -46,8 +46,8 @@ try { xmlhttp.open("GET", url, true); xmlhttp.send(); - } catch (_error) { - e = _error; + } catch (error) { + e = error; console.log("ERROR: " + e.message + " (" + e.type + ") when accessing " + url); } }; @@ -81,7 +81,7 @@ style_block = document.createElement('style'); head = document.getElementsByTagName('head')[0]; head.appendChild(style_block); - test_results = testVWSupport(test_element, style_block) && testVWSupport(test_element, style_block) && testVMinSupport(test_element, style_block); + test_results = testVWSupport(test_element, style_block) && testVWSupport(test_element, style_block) && testVMinSupport(test_element, style_block) && testVMaxSupport(test_element, style_block); body.removeChild(test_element); head.removeChild(style_block); return test_results; @@ -144,19 +144,31 @@ return actual_vmin === comp_width; }; + testVMaxSupport = function(element, style_block) { + var actual_vmax, comp_width, docElement, one_vh, one_vw; + applyStyleTest(style_block, 'width: 50vmax'); + docElement = document.documentElement; + one_vw = docElement.clientWidth / 100; + one_vh = docElement.clientHeight / 100; + actual_vmax = parseInt(Math.max(one_vw, one_vh) * 50, 10); + comp_width = parseInt(testElementStyle(element).width, 10); + clearStyleTests(style_block); + return actual_vmax === comp_width; + }; + initLayoutEngine = function() { - var analyzeStyleRule, analyzeStylesheet, head, innerSheetCount, links, onresize, outerSheetCount, sheets, styleElement, _i, _len; + var analyzeStyleRule, analyzeStylesheet, head, i, innerSheetCount, j, len, links, onresize, outerSheetCount, sheets, styleElement; analyzeStyleRule = function(rule) { - var declaration, declarations, hasDimension, token, _i, _j, _len, _len1, _ref, _ref1; + var declaration, declarations, hasDimension, j, k, len, len1, ref, ref1, token; declarations = []; - _ref = rule.value; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - declaration = _ref[_i]; + ref = rule.value; + for (j = 0, len = ref.length; j < len; j++) { + declaration = ref[j]; hasDimension = false; - _ref1 = declaration.value; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - token = _ref1[_j]; - if (token.tokenType === 'DIMENSION' && (token.unit === 'vmin' || token.unit === 'vh' || token.unit === 'vw')) { + ref1 = declaration.value; + for (k = 0, len1 = ref1.length; k < len1; k++) { + token = ref1[k]; + if (token.tokenType === 'DIMENSION' && (token.unit === 'vmin' || token.unit === 'vh' || token.unit === 'vw' || token.unit === 'vmax')) { hasDimension = true; } } @@ -168,11 +180,11 @@ return declarations; }; analyzeStylesheet = function(sheet) { - var atRules, decs, rule, rules, _i, _len, _ref; + var atRules, decs, j, len, ref, rule, rules; rules = []; - _ref = sheet.value; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - rule = _ref[_i]; + ref = sheet.value; + for (j = 0, len = ref.length; j < len; j++) { + rule = ref[j]; switch (rule.type) { case 'STYLE-RULE': decs = analyzeStyleRule(rule); @@ -198,22 +210,23 @@ vw: vpDims.width / 100 }; dims.vmin = Math.min(dims.vh, dims.vw); + dims.vmax = Math.max(dims.vh, dims.vw); vpAspectRatio = vpDims.width / vpDims.height; map = function(a, f) { - var a1, e, _i, _len; + var a1, e, j, len; if (a.map != null) { return a.map(f); } else { a1 = []; - for (_i = 0, _len = a.length; _i < _len; _i++) { - e = a[_i]; + for (j = 0, len = a.length; j < len; j++) { + e = a[j]; a1.push(f(e)); } return a1; } }; generateRuleCode = function(rule) { - var declaration, declarations, ruleCss, token, _i, _j, _len, _len1, _ref, _ref1; + var declaration, declarations, j, k, len, len1, ref, ref1, ruleCss, token; declarations = []; ruleCss = (map(rule.selector, function(o) { if (o.toSourceString != null) { @@ -223,16 +236,16 @@ } })).join(''); ruleCss += "{"; - _ref = rule.value; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - declaration = _ref[_i]; + ref = rule.value; + for (j = 0, len = ref.length; j < len; j++) { + declaration = ref[j]; ruleCss += declaration.name; ruleCss += ":"; - _ref1 = declaration.value; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - token = _ref1[_j]; - if (token.tokenType === 'DIMENSION' && (token.unit === 'vmin' || token.unit === 'vh' || token.unit === 'vw')) { - ruleCss += "" + (Math.floor(token.num * dims[token.unit])) + "px"; + ref1 = declaration.value; + for (k = 0, len1 = ref1.length; k < len1; k++) { + token = ref1[k]; + if (token.tokenType === 'DIMENSION' && (token.unit === 'vmin' || token.unit === 'vh' || token.unit === 'vw' || token.unit === 'vmax')) { + ruleCss += (Math.floor(token.num * dims[token.unit])) + "px"; } else { ruleCss += token.toSourceString(); } @@ -243,11 +256,11 @@ return ruleCss; }; generateSheetCode = function(sheet) { - var mar, nums, prelude, rule, sheetCss, source, t, t1, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3; + var j, k, l, len, len1, len2, len3, m, mar, nums, prelude, ref, ref1, ref2, ref3, rule, sheetCss, source, t, t1; sheetCss = ''; - _ref = sheet.value; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - rule = _ref[_i]; + ref = sheet.value; + for (j = 0, len = ref.length; j < len; j++) { + rule = ref[j]; switch (rule.type) { case 'STYLE-RULE': sheetCss += generateRuleCode(rule); @@ -257,14 +270,14 @@ prelude = ''; mar = false; nums = []; - _ref1 = rule.prelude; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - t = _ref1[_j]; + ref1 = rule.prelude; + for (k = 0, len1 = ref1.length; k < len1; k++) { + t = ref1[k]; if (t.name === '(') { prelude += '('; - _ref2 = t.value; - for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { - t1 = _ref2[_k]; + ref2 = t.value; + for (l = 0, len2 = ref2.length; l < len2; l++) { + t1 = ref2[l]; source = t1.toSourceString != null ? t1.toSourceString() : ''; if (t1.tokenType === 'IDENT' && source === 'max-aspect-ratio') { mar = true; @@ -284,9 +297,9 @@ } } else { prelude = ''; - _ref3 = rule.prelude; - for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { - t = _ref3[_l]; + ref3 = rule.prelude; + for (m = 0, len3 = ref3.length; m < len3; m++) { + t = ref3[m]; if (t.name === '(') { prelude += '('; prelude += (map(t.value, function(o) { @@ -327,25 +340,23 @@ links = document.getElementsByTagName('link'); innerSheetCount = 0; outerSheetCount = 0; - for (_i = 0, _len = links.length; _i < _len; _i++) { - (function () { - var i = links[_i]; - if (i.rel !== 'stylesheet') { - return; + for (j = 0, len = links.length; j < len; j++) { + i = links[j]; + if (i.rel !== 'stylesheet') { + continue; + } + innerSheetCount++; + ajax(i.href, function(cssText) { + var sheet, tokenlist; + tokenlist = tokenize(cssText); + sheet = parse(tokenlist); + analyzeStylesheet(sheet); + sheets[i.href] = sheet; + outerSheetCount++; + if (outerSheetCount === innerSheetCount) { + window.onresize(); } - innerSheetCount++; - ajax(i.href, function (cssText) { - var sheet, tokenlist; - tokenlist = tokenize(cssText); - sheet = parse(tokenlist); - analyzeStylesheet(sheet); - sheets[i.href] = sheet; - outerSheetCount++; - if (outerSheetCount === innerSheetCount) { - window.onresize(); - } - }); - }()); + }); } window.onresize = onresize; }; From 2009382aa179a4be4c04647aa2e3b3324b125f95 Mon Sep 17 00:00:00 2001 From: Face Kapow Date: Wed, 28 Sep 2016 16:56:04 -0400 Subject: [PATCH 2/2] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3bf7162..4edc7ad 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ vminpoly A polyfill for CSS units vw, vh, vmin, & vmax. -Simple online [demo](http://saabi.github.com/vminpoly) right here. A more sophisticated [responsive demo](http://saabi.github.com/vminpoly/demo2.html) demonstrating vw/vh/vmin/vmax units along with *media queries*, working right down to IE5.5 on the desktop and Opera Mini on mobiles!! (In Opera Mini the browser must be refreshed after changing phone orientations as it appears it doesn't trigger the window resize event) +Simple online [demo](http://saabi.github.com/vminpoly) right here. A more sophisticated [responsive demo](http://saabi.github.com/vminpoly/demo2.html) demonstrating vw/vh/vmin units along with *media queries*, working right down to IE5.5 on the desktop and Opera Mini on mobiles!! (In Opera Mini the browser must be refreshed after changing phone orientations as it appears it doesn't trigger the window resize event) This is a working proof of concept right now. There's a lot of cleanup to do on the code.