From d8ded53bc5cf8ac2dc2fa5ccfeee921f38e6cc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Saunier?= Date: Fri, 3 Apr 2015 17:04:04 +0200 Subject: [PATCH 1/4] bump version to 0.0.1 --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 6c1723d..c4b441a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "shapes-polyfill", - "version": "0.0.0", + "version": "0.0.1", "description": "A Polyfill for CSS Shapes", "main": "index.js", "scripts": { @@ -14,6 +14,10 @@ "Bear Travis", "Hans Muller" ], + "contributors": [{ + "name": "Cédric Saunier", + "email": "cedric.sa@gmail.com" + }], "license": "BSD", "readmeFilename": "README.md", "devDependencies": { From a195f16e27390c321b1a686e896d11e27fb745f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Saunier?= Date: Fri, 3 Apr 2015 17:04:42 +0200 Subject: [PATCH 2/4] add .idea folder to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c234900..63279c1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .DS_Store node_modules/ tags +.idea \ No newline at end of file From 1fe5a1fc2ded26f1b5e15d381fb5f5040c24b9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Saunier?= Date: Fri, 3 Apr 2015 17:40:59 +0200 Subject: [PATCH 3/4] add demo file for mediaQueries --- demos/mediaQueries-demo.html | 60 ++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 demos/mediaQueries-demo.html diff --git a/demos/mediaQueries-demo.html b/demos/mediaQueries-demo.html new file mode 100644 index 0000000..0b0ce9b --- /dev/null +++ b/demos/mediaQueries-demo.html @@ -0,0 +1,60 @@ + + + + + + + + +
+
+

Pelicans are a genus of large water birds comprising the family Pelecanidae. They are characterised by a long beak and large throat pouch used for catching prey and draining water from the scooped up contents before swallowing. They have predominantly pale plumage, the exceptions being the Brown and Peruvian Pelicans. The bills, pouches and bare facial skin of all species become brightly coloured before the breeding season. The eight living pelican species have a patchy global distribution, ranging latitudinally from the tropics to the temperate zone, though they are absent from interior South America as well as from polar regions and the open ocean. Fossil evidence of pelicans dates back at least 30 million years, to the remains of a beak very similar to that of modern species recovered from Oligocene strata in France.

+ +

Long thought to be related to frigatebirds, cormorants, tropicbirds, gannets and boobies, pelicans are now known instead to be most closely related to the Shoebill and Hamerkop, and are placed in the order Pelecaniformes. Ibises, spoonbills and herons are more distant relatives, and have been classified in the same order. Pelicans frequent inland and coastal waters where they feed principally on fish, catching them at or near the water surface. Gregarious birds, they often hunt cooperatively and breed colonially. Four white-plumaged species tend to nest on the ground, and four brown or grey-plumaged species nest mainly in trees.

+
+ + + + + + From ba65fd61e1874c23b87125bc5a77831830a4c9ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Saunier?= Date: Tue, 7 Apr 2015 15:05:56 +0200 Subject: [PATCH 4/4] add mediaqueries support --- Gruntfile.js | 4 +- shapes-polyfill.js | 178 +++++++++++++++++++++++++++++++++++--- shapes-polyfill.min.js | 5 +- src/shape-info.js | 28 +++++- src/shape-polyfill.js | 42 ++++++++- src/style-polyfill.js | 108 +++++++++++++++++++++-- tests/shape-info-tests.js | 10 ++- 7 files changed, 341 insertions(+), 34 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 5e0fde1..02140a3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,7 +1,7 @@ module.exports = function(grunt) { var project = { files: ['src/*.js'] - } + }; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), @@ -49,7 +49,7 @@ limitations under the License.\n\ watch: { options: { - atBegin: true, + atBegin: true }, js: { files: project.files, diff --git a/shapes-polyfill.js b/shapes-polyfill.js index b56b204..64116e9 100644 --- a/shapes-polyfill.js +++ b/shapes-polyfill.js @@ -1127,12 +1127,16 @@ function createShapeGeometry(shapeValue, whenReady) { function ShapeInfo(element) { this.metrics = new Metrics(element); + + var queryStep = this.getQueryStep(element.getAttribute('data-shape-size-mediaqueries').split('|')); + var parserSettings = { metrics: this.metrics, - shapeOutside: element.getAttribute('data-shape-outside'), - shapeMargin: element.getAttribute('data-shape-margin'), - shapeImageThreshold: element.getAttribute('data-shape-image-threshold') + shapeOutside: element.getAttribute('data-shape-outside').split('|')[queryStep], + shapeMargin: element.getAttribute('data-shape-margin').split('|')[queryStep], + shapeImageThreshold: element.getAttribute('data-shape-image-threshold').split('|')[queryStep] }; + this.shapeValue = new ShapeValue(parserSettings); var self = this; @@ -1150,6 +1154,24 @@ ShapeInfo.prototype.onReady = function(callback) { this.callback = callback; }; +ShapeInfo.prototype.getQueryStep = function(steps) { + var i = 0, + step = 0, + documentWidth = document.documentElement.clientWidth, + minWidth, + maxWidth; + for(i; i < steps.length; i++) { + minWidth = steps[i].split(',')[0].split('(')[1]; + minWidth = minWidth === "null" ? 0 : Number(minWidth); + maxWidth = steps[i].split(',')[1].split(')')[0]; + maxWidth = maxWidth === "null" ? documentWidth : Number(maxWidth); + if(documentWidth >= minWidth && documentWidth <= maxWidth) { + step = i; + } + } + return step; +}; + ShapeInfo.prototype.leftExclusionEdge = function(line) { // { top, bottom, left, right } return this.geometry ? this.geometry.leftExclusionEdge(line.top, line.bottom) : line.left; }; @@ -1375,10 +1397,43 @@ Polyfill.prototype.run = function(settings) { this.stylesLoaded = true; new StylePolyfill(function(rules) { + + var _this = this, + els, + queriesTab, + queryRule, + queryIndex; + rules.forEach(function(rule) { - var els = document.querySelectorAll(rule.selector); - for (var i = 0; i < els.length; i++) - els[i].setAttribute('data-' + rule.property, rule.value); + els = document.querySelectorAll(rule.selector); + + for (var i = 0; i < els.length; i++){ + // if this is new element, we init all the value to null + if(!els[i].hasAttribute('data-shape-outside')) { + els[i].setAttribute('data-shape-outside', 'null'); + els[i].setAttribute('data-shape-margin', 'null'); + els[i].setAttribute('data-shape-image-threshold', 'null'); + els[i].setAttribute('data-shape-size-mediaqueries', '(null,null)'); + } + + queriesTab = els[i].getAttribute('data-shape-size-mediaqueries').split('|'); + queryRule = '('+rule.minWidth+','+rule.maxWidth+')'; + queryIndex = queriesTab.indexOf(queryRule); + + if(queryIndex === -1) { + // mediaquery doesn't exist, we create a new entry + els[i].setAttribute('data-shape-outside', els[i].getAttribute('data-shape-outside') + '|null'); + els[i].setAttribute('data-shape-margin', els[i].getAttribute('data-shape-margin') + '|null'); + els[i].setAttribute('data-shape-image-threshold', els[i].getAttribute('data-shape-image-threshold') + '|null'); + els[i].setAttribute('data-shape-size-mediaqueries', els[i].getAttribute('data-shape-size-mediaqueries') + '|' + queryRule); + // we update specific entry + _this.setPropertyForQuery(els[i], rule, queriesTab.length); + } else { + // mediaquery exist, we update specific entry + _this.setPropertyForQuery(els[i], rule, queryIndex); + } + + } }); self.run(settings); @@ -1394,8 +1449,9 @@ Polyfill.prototype.run = function(settings) { } var els = document.querySelectorAll('[data-shape-outside]'); - for (var i = 0; i < els.length; i++) + for (var i = 0; i < els.length; i++){ this.polyfill(els[i], settings); + } }; Polyfill.prototype.teardown = function() { @@ -1899,21 +1955,113 @@ StyleLoader.prototype.onComplete = function() { function StylePolyfill(callback) { this.callback = callback || function() {}; + this.eminpx = this.getEmValue(); var self = this; new StyleLoader(function(stylesheets) { self.onStylesLoaded(stylesheets); }); } +StylePolyfill.prototype.setPropertyForQuery = function(elem, rule, index) { + var propertyQueriesTab = elem.getAttribute('data-' + rule.property).split('|'); + propertyQueriesTab[index] = rule.value; + elem.setAttribute('data-' + rule.property, propertyQueriesTab.join('|')); +}; + +// thanks to Scott Jehl getEmValue() function he wrote for Respond.js (https://github.com/scottjehl/Respond) +StylePolyfill.prototype.getEmValue = function() { + var ret, + div = window.document.createElement('div'), + body = window.document.body, + docElem = window.document.documentElement, + originalHTMLFontSize = docElem.style.fontSize, + originalBodyFontSize = body && body.style.fontSize, + fakeUsed = false; + div.style.cssText = "position:absolute;font-size:1em;width:1em"; + if( !body ){ + body = fakeUsed = doc.createElement( "body" ); + body.style.background = "none"; + } + // 1em in a media query is the value of the default font size of the browser + // reset docElem and body to ensure the correct value is returned + docElem.style.fontSize = "100%"; + body.style.fontSize = "100%"; + body.appendChild( div ); + if( fakeUsed ){ + docElem.insertBefore( body, docElem.firstChild ); + } + ret = div.offsetWidth; + if( fakeUsed ){ + docElem.removeChild( body ); + } + else { + body.removeChild( div ); + } + // restore the original values + docElem.style.fontSize = originalHTMLFontSize; + if( originalBodyFontSize ) { + body.style.fontSize = originalBodyFontSize; + } + + return ret; +}; + StylePolyfill.prototype.onStylesLoaded = function(stylesheets) { + var parsedStylesheets = this.parseForMediaQueries(stylesheets); + this.parseForShapes(parsedStylesheets); +}; + +StylePolyfill.prototype.parseForMediaQueries = function(stylesheets) { + + var cleanCss, + queries, + styleBlock = [], + styleBlockMQ = [], + queryMinWidth, + queryMaxWidth, + self = this; + stylesheets.forEach(function(stylesheet) { + + // thanks to Scott Jehl regexp he wrote for Respond.js (https://github.com/scottjehl/Respond) + cleanCss = stylesheet.cssText.replace( /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi , '' ); // comments + queries = cleanCss.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ); // queries + + if(queries) { + queries.forEach(function(query) { + cleanCss = cleanCss.split(query).join(""); + queryMinWidth = query.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ); + queryMaxWidth = query.match( /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ); + styleBlockMQ.push({ + cssText : query.match( /@media *([^\{]+)\{([\S\s]+?)$/ )[2], + minWidth : queryMinWidth ? queryMinWidth[2] === "em" ? queryMinWidth[1]*self.eminpx : queryMinWidth[1] : null, + maxWidth : queryMaxWidth ? queryMaxWidth[2] === "em" ? queryMaxWidth[1]*self.eminpx : queryMaxWidth[1] : null + }); + }); + } + + styleBlock.push({ + cssText: cleanCss, + minWidth: null, + maxWidth : null + }); + + }); + + return styleBlock.concat(styleBlockMQ); + +}; + +StylePolyfill.prototype.parseForShapes = function(stylesheets) { // use : and ; as delimiters, except between () // this will be sufficient for most, but not all cases, eg: rectangle(calc(100%)) - var selector = "\\s*([^{}]*[^\\s])\\s*{[^\\}]*"; - var value = "\\s*:\\s*((?:[^;\\(]|\\([^\\)]*\\))*)\\s*;"; - - var re, match; + var selector = "\\s*([^{}]*[^\\s])\\s*{[^\\}]*", + value = "\\s*:\\s*((?:[^;\\(]|\\([^\\)]*\\))*)\\s*;", + re, + match, + rules = [], + properties = ["shape-outside", "shape-margin", "shape-image-threshold"], + _this = this; - var rules = [], properties = ["shape-outside", "shape-margin", "shape-image-threshold"]; properties.forEach(function(property) { re = new RegExp(selector + "(" + property + ")" + value, "ig"); stylesheets.forEach(function(stylesheet) { @@ -1921,13 +2069,17 @@ StylePolyfill.prototype.onStylesLoaded = function(stylesheets) { rules.push({ selector: match[1], property: match[2], - value: match[3] + value: match[3], + minWidth: stylesheet.minWidth, + maxWidth: stylesheet.maxWidth }); + } }); }); this.callback(rules); + }; scope.ShapesPolyfill = new Polyfill(scope); diff --git a/shapes-polyfill.min.js b/shapes-polyfill.min.js index f1d3a58..523125c 100644 --- a/shapes-polyfill.min.js +++ b/shapes-polyfill.min.js @@ -12,5 +12,6 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -!function(a){"use strict";function b(a){var b=getComputedStyle(a);this.units={px:1},this.element=a;var c=function(a){return a&&a.length?parseInt(a):0};this.margins=[b.marginTop,b.marginRight,b.marginBottom,b.marginLeft],this.margins=this.margins.map(c),this.borders=[b.borderTopWidth,b.borderRightWidth,b.borderBottomWidth,b.borderLeftWidth],this.borders=this.borders.map(c),this.paddings=[b.paddingTop,b.paddingRight,b.paddingBottom,b.paddingLeft],this.paddings=this.paddings.map(c),this.borderBox={x:0,y:0,width:a.offsetWidth,height:a.offsetHeight},this.marginBox={x:-this.margins[3],y:-this.margins[0],width:a.offsetWidth+this.margins[1]+this.margins[3],height:a.offsetHeight+this.margins[0]+this.margins[2]};var d=this,e=["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"];this.borderBox.radii=e.map(function(a){return a=b[a].split(/\s+/),[d.toPixels(a[0],d.borderBox.width),d.toPixels(a.length>1?a[1]:a[0],d.borderBox.height)]}),this.cssFloat=b.cssFloat}function c(a,b,c){return(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y)}function d(a,b,d){return Math.abs(c(a,b,d))<350}function e(a,b){return a.x==b.x&&a.y==b.y}function f(a,b,c){return c.x>=Math.min(a.x,b.x)&&c.x<=Math.max(a.x,b.x)&&d(a,b,c)}function g(){}function h(a,b,c,d){if(a.y>=c&&a.y<=d)return{x1:a.x-b,x2:a.x+b};var e,f;return d0?a[0].x:void 0,g=a.length>0?a[0].y:void 0,h=f,l=g,m=k(a),n=0;do{var o=this.nextEdgeVertexIndex(n,m);e.push(new i(this,a[n],a[o]));var p=a[n].x,q=a[n].y;f=Math.min(p,f),g=Math.min(q,g),h=Math.max(p,h),l=Math.max(q,l),n=o}while(0!==n);for(var r,s=0;s3;)r=(s+1)%e.length,d(e[s].vertex1,e[s].vertex2,e[r].vertex2)?(e[s].vertex2=e[r].vertex2,e.splice(r,1)):s++;if(0===c)this.shapeMarginEdges=e;else{for(var t=[],u=0;uc;c++)this.intervals[c]=r.none;this.minY=-a,this.maxY=b-a}function s(a){this.shapeMargin=a,this.xIntercepts=[];for(var b=0;a>=b;b++)this.xIntercepts[b]=Math.sqrt(a*a-b*b)}function t(a,b){console.log("Unable to load image ",a,". It's probably missing or you've run into a CORS issue."),b&&console.log("The exact problem was ",b)}function u(a,b,c){var d=document.createElement("canvas");this.width=d.width=b,this.height=d.height=c;var e=d.getContext("2d");e.drawImage(a,0,0,b,c);try{this.imageData=e.getImageData(0,0,b,c)}catch(f){t(a.src,f)}}function v(a,b,c,d,e,f){this.url=a,this.box=b,this.shapeImageThreshold=256*c,this.shapeMargin=d,this.clip=e,this.init(f)}function w(a,b){this.width=a,this.height=b}function x(a,b,c,d){this.x=a,this.y=b,this.width=c,this.height=d,this.maxX=a+c,this.maxY=b+d}function y(a,b,c,d,e){this.rect=a,this.radii={topLeft:b,topRight:c,bottomLeft:d,bottomRight:e}}function z(a,b,c){return b*Math.sqrt(1-a*a/(c*c))}function A(a,b,c){return 0===b?1:Math.round(0===a||c>a*b/2?b:Math.sqrt(2*c*(b/a)))}function B(a,b){return a.maxX-b}function C(a,b){return a.x+b}function D(a){return a.x}function E(a){return a.maxX}function F(a,b,c,d){return function(e,f,g){if(!this.rect.overlapsYRange(e,f))return[{x:void 0,height:f-e}];var h=[];el;l+=i)m=o.maxY-Math.min(l+i,k),n=z(m,o.width,o.height),h.push({height:Math.min(i,k-l),x:d(o,n)});if(j=Math.max(q.y,e),k=Math.min(q.maxY,f),q.overlapsYRange(e,f)&&h.push({x:c(q),height:k-j}),p.overlapsYRange(e,f))for(i=A(p.width,p.height,g),j=Math.max(e,p.y),k=Math.min(p.maxY,f),l=j;k>l;l+=i)m=l-p.y,n=z(m,p.width,p.height),h.push({height:Math.min(i,k-l),x:d(p,n)});return f>this.rect.maxY&&h.push({x:void 0,height:f-this.rect.maxY}),h}}function G(a,b){var c=a.r+b,d=new w(c,c);return new y(new x(a.cx-c,a.cy-c,2*c,2*c),d,d,d,d)}function H(a,b){var c=new w(a.rx+b,a.ry+b);return new y(new x(a.cx-c.width,a.cy-c.height,2*c.width,2*c.height),c,c,c,c)}function I(a,b){function c(a){return new w(a[0]+b,a[1]+b)}var d=c(a.radii[0]),e=c(a.radii[1]),f=c(a.radii[2]),g=c(a.radii[3]),h=new x(a.x-b,a.y-b,a.width+2*b,a.height+2*b);return new y(h,d,e,g,f)}function J(a,b){function c(a){return new w(a[0]+b,a[1]+b)}var d=c(a.radii[0]),e=c(a.radii[1]),f=c(a.radii[2]),g=c(a.radii[3]),h=new x(-b,-b,a.width+2*b,a.height+2*b);return new y(h,d,e,g,f)}function K(a,b,c,d,e,f){var g=new x(e.x,e.y,e.width,e.height);return new v(a,b,c,d,g,f)}function L(a,b){return new l(a.points,a.fillRule,b)}function M(a,b){var c,d=void 0===a.shapeMargin?0:a.shapeMargin;if(a.shape){switch(a.shape.type){case"circle":c=G(a.shape,d);break;case"ellipse":c=H(a.shape,d);break;case"inset":c=I(a.shape,d),c.isRenderable()||c.adjustRadii();break;case"polygon":c=L(a.shape,d)}return b(),c}return a.url?K(a.url,a.box,a.shapeImageThreshold,d,a.clip,b):a.box?(c=J(a.box,d),b(),c):void console.error("Unrecognized shape")}function N(a){this.metrics=new b(a);var c={metrics:this.metrics,shapeOutside:a.getAttribute("data-shape-outside"),shapeMargin:a.getAttribute("data-shape-margin"),shapeImageThreshold:a.getAttribute("data-shape-image-threshold")};this.shapeValue=new R(c);var d=this;this.geometry=M(this.shapeValue,function(){d.ready=!0,d.callback&&d.callback()})}function O(a){this.scope=a;var b=document.currentScript;b||(b=document.getElementsByTagName("script"),b=b[b.length-1]);var c=this,d="false"!==b.getAttribute("data-auto-run");d&&a.addEventListener&&a.addEventListener("load",function(){c.run()})}function P(a,b){var c,d=document.createElement("div");b.forEach(function(a){var b=a.bottom-a.top,e=document.createElement("div");e.className="sandbag",c={cssFloat:a.cssFloat,width:a.offset+"px",height:b+"px",clear:a.cssFloat};for(var f in c)e.style[f]=c[f];d.appendChild(e)}),c={position:"relative",width:"auto",height:"0",clear:"both",pointerEvents:"none"};for(var e in c)d.style[e]=c[e];var f,g=a.parentNode,h=getComputedStyle(g),i=parseFloat(h.borderTop)+parseFloat(h.borderBottom);c={position:"absolute",top:"0",width:"100%",height:g.clientHeight-i,left:"0"},f=document.createElement("div");for(e in c)f.style[e]=c[e];d.appendChild(f),a.parentNode&&a.parentNode.insertBefore(d,a),f.appendChild(a),d.setAttribute("data-shape-outside-container","true")}function Q(a,b){var c;return function(){var d=this,e=arguments;clearTimeout(c),c=setTimeout(function(){c=null,a.apply(d,e)},b)}}function R(a){return a&&a.metrics&&a.shapeOutside?(this.url=this.parseUrl(a.shapeOutside),this.box=this.parseBox(this.url?"content-box":a.shapeOutside,a.metrics),this.shape=this.parseBasicShape(a.shapeOutside,this.box,a.metrics),this.clip=this.computeClip(this.box,a.metrics),this.shapeMargin=this.parseShapeMargin(a.shapeMargin,this.box,a.metrics),void(this.shapeImageThreshold=this.parseShapeImageThreshold(a.shapeImageThreshold))):void console.error("ShapeValue requires at least a metrics object and shape-outside string")}function S(a,b,c){var d=c.reduce(function(a,b){return a+b[0]},0),e=c.reduce(function(a,b){return a+b[1]},0),f=c.reduce(function(a,b){return a+b[2]},0),g=c.reduce(function(a,b){return a+b[3]},0);a.x-=b*g,a.y-=b*d,a.width+=b*(g+e),a.height+=b*(d+f)}function T(a,b,c){if(0>b)return Math.max(a+b*c,0);var d=Math.abs(a/c);return 1>d?Math.max(a+c*(1+Math.pow(d-1,3)),0):a+c}function U(a,b,c){var d=c.reduce(function(a,b){return a+b[0]},0),e=c.reduce(function(a,b){return a+b[1]},0),f=c.reduce(function(a,b){return a+b[2]},0),g=c.reduce(function(a,b){return a+b[3]},0);a[0][0]=T(a[0][0],b,g),a[0][1]=T(a[0][1],b,d),a[1][0]=T(a[1][0],b,e),a[1][1]=T(a[1][1],b,d),a[2][0]=T(a[2][0],b,e),a[2][1]=T(a[2][1],b,f),a[3][0]=T(a[3][0],b,g),a[3][1]=T(a[3][1],b,f)}function V(a,b){return a.map(function(a){return a[b]})}function W(a,b,c){a=a.split(/\s+/);var d="TopLeft",e=0;switch(a[0]){case"top":case"left":break;case"bottom":case"right":d="BottomRight";break;case"center":e=b/2;break;default:e=c.toPixels(a[0],b)}return a.length>1&&(e=c.toPixels(a[1],b)),"TopLeft"===d?e:b-e}function X(a,b,c,d){return"closest-side"===a?Math.min.apply(null,b):"farthest-side"===a?Math.max.apply(null,b):d.toPixels(a,c)}function Y(){var a,b,c=document,d=[];if("function"==typeof c.querySelectorAll)d=c.querySelectorAll('link[rel="stylesheet"], style'),d=Array.prototype.slice.call(d,0);else{var e=c.getElementsByTagName("link");if(e.length)for(a=0,b=e.length;b>a;a++)"stylesheet"===e[a].getAttribute("rel")&&d.push(e[a]);for(e=c.getElementsByTagName("style"),a=0,b=e.length;b>a;a++)d.push(e[a])}return d}function Z(a){this.source=a,this.url=a.href||null,this.cssText=""}function $(a){return this instanceof $?(this.stylesheets=[],this.queueCount=0,this.callback=a||function(){},void this.init()):new $(a)}function _(a){this.callback=a||function(){};var b=this;new $(function(a){b.onStylesLoaded(a)})}b.prototype.unitToPx=function(a){if(this.units[a])return this.units[a];var b=this.element.style.getPropertyValue("line-height");return this.element.style.setProperty("line-height",1+a),this.units[a]=parseFloat(getComputedStyle(this.element).getPropertyValue("line-height")),this.element.style.setProperty("line-height",b),this.units[a]},b.prototype.getUnitsMap=function(a){var b=["em","ex","ch","rem","vw","vh","vmin","vmax","cm","mm","in","px","pt","pc"],c=document.createElement("div");c.style.width="0px",c.style.height="0px",a.appendChild(c);var d=getComputedStyle(c),e={};return b.forEach(function(a){c.style.lineHeight="1"+a,e[a]=parseFloat(d.lineHeight)}),c.parentNode.removeChild(c),e},b.prototype.toPixels=function(a,b){var c=/([\-0-9\.]*)([a-z%]*)/.exec(a);return c[1]=parseFloat(c[1]),c[2]?"%"===c[2]?c[1]*b/100:c[1]*this.unitToPx(c[2]):c[1]},g.prototype.init=function(a,b,c){this.polygon=a,this.vertex1=b,this.vertex2=c,this.minX=Math.min(this.vertex1.x,this.vertex2.x),this.maxX=Math.max(this.vertex1.x,this.vertex2.x)},g.prototype.containsPoint=function(a){return f(this.vertex1,this.vertex2,a)},g.prototype.overlapsYRange=function(a,b){var c=this.vertex1.y,d=this.vertex2.y;return b>=Math.min(c,d)&&a<=Math.max(c,d)},g.prototype.isWithinYRange=function(a,b){var c=this.vertex1.y,d=this.vertex2.y;return a<=Math.min(c,d)&&b>=Math.max(c,d)},g.prototype.inwardNormal=function(){var a=this.vertex2.x-this.vertex1.x,b=this.vertex2.y-this.vertex1.y,c=Math.sqrt(a*a+b*b);return{x:-b/c,y:a/c}},g.prototype.outwardNormal=function(){var a=this.inwardNormal();return{x:-a.x,y:-a.y}},g.prototype.xIntercept=function(a){var b=this.vertex1.y,c=this.vertex2.y;return b==c?Math.min(this.vertex1.x,this.vertex2.x):a==Math.min(b,c)?c>b?this.vertex1.x:this.vertex2.x:a==Math.max(b,c)?b>c?this.vertex1.x:this.vertex2.x:this.vertex1.x+(a-b)*(this.vertex2.x-this.vertex1.x)/(c-b)},g.prototype.clippedEdgeXRange=function(a,b){if(this.isWithinYRange(a,b)){var c=this.vertex1.x,d=this.vertex2.x;return{x1:Math.min(c,d),x2:Math.max(c,d)}}var e,f;this.vertex1.yb?this.xIntercept(b):f.x;return{x1:Math.min(g,h),x2:Math.max(g,h)}},i.prototype=new g,j.prototype=new g,l.prototype.vertexAt=function(a){return this.m_vertices[a]},l.prototype.edgeAt=function(a){return this.m_edges[a]},l.prototype.isEmpty=function(){return this.m_edges.length<3||this.bounds.isEmpty()},l.prototype.vertices=function(){return this.m_vertices.slice(0)},l.prototype.edges=function(){return this.m_edges.slice(0)},l.prototype.overlapsYRange=function(a,b){return a=this.bounds.y},l.prototype.nextVertexIndex=function(a,b){var c=this.m_vertices.length;return(b?a+1:a-1+c)%c},l.prototype.nextEdgeVertexIndex=function(a,b){for(var c=(this.m_vertices.length,this.nextVertexIndex(a,b));c&&e(this.vertexAt(a),this.vertexAt(c));)c=this.nextVertexIndex(c,b);for(;c;){var f=this.nextVertexIndex(c,b);if(!d(this.vertexAt(a),this.vertexAt(c),this.vertexAt(f)))break;c=f}return c},l.prototype.containsPointEvenOdd=function(a){for(var b=0,c=0;ca.y||e.y>a.y&&f.y<=a.y){var g=(a.y-e.y)/(f.y-e.y);a.xa.y&&c(f,g,a)>0&&++b:g.y>a.y&&f.y<=a.y&&c(f,g,a)<0&&--b}return 0!==b},l.prototype.containsPoint=function(a){return this.bounds.containsPoint(a)?"nonzero"==this.fillRule?this.containsPointNonZero(a):this.containsPointEvenOdd(a):!1},l.prototype.edgeVerticesThatOverlapYRange=function(a,b){for(var c=[],d=0;d=a&&e.yc);d++)e=f[d].clippedEdgeXRange(a,b),c=void 0===c?e.x1:Math.min(c,e.x1);var g=this.shapeMargin;if(g>0){var i=this.edgeVerticesThatOverlapYRange(a-g,b+g);for(i.sort(n),d=0;d0){var i=this.edgeVerticesThatOverlapYRange(a-g,b+g);for(i.sort(p),d=0;d=b.endX},s.prototype.generateIntervalAt=function(a,b){var c=Math.abs(a-b.y),d=c>this.shapeMargin?0:this.xIntercepts[c];return new q(a,b.startX-d,b.endX+d)},r.prototype.computeMarginIntervals=function(a){for(var b=new s(a),c=new r(this.yOffset,this.size),d=this.minY;d=g&&!(f>0&&this.intervalAtContains(f,e));--f)c.uniteIntervalAt(f,b.generateIntervalAt(f,e));for(c.uniteIntervalAt(d,b.generateIntervalAt(d,e)),f=d+1;h>=f&&!(f0&&(c.intervals=c.intervals.computeMarginIntervals(c.shapeMargin,c.clip)),b&&URL.revokeObjectURL(b),a()},d.onerror=function(){t(c.url),a()},!d.hasOwnProperty("crossOrigin")&&window.URL&&window.URL.createObjectURL){var f=new XMLHttpRequest;f.onreadystatechange=function(){4===f.readyState&&(200===f.status?(b=URL.createObjectURL(f.response),d.src=b):(t(c.url),a()))},f.open("GET",c.url,!0),f.responseType="blob",f.send()}else d.crossOrigin="anonymous",d.src=c.url},v.prototype.computeIntervals=function(a){var b=this.clip,c=this.shapeImageThreshold,d=this.box.width,e=this.box.height,f=new u(a,d,e);if(!f.hasData())return void 0;for(var g=new r(-b.y,b.height),h=Math.min(b.height,this.box.height),i=0;h>i;i++)for(var j=-1,k=0;kc?(j=k,g.intervalAt(i)===r.none&&g.setIntervalAt(i,new q(i,j,d))):-1!=j&&c>=l&&(g.intervalAt(i).endX=k,j=-1)}return g},v.prototype.rightExclusionEdge=function(a,b){var c=this.intervals;if(!c)return this.clip.width;for(var d,e=Math.max(a,this.clip.y);b>=e&&ed)&&(d=f)}return d},v.prototype.leftExclusionEdge=function(a,b){var c=this.intervals;if(!c)return 0;for(var d,e=Math.max(a,this.clip.y);b>=e&&ef)&&(d=f)}return d},w.zeroSize={width:0,height:0},w.prototype.isEmpty=function(){return this.width<=0||this.height<=0},w.prototype.scale=function(a){this.width*=a,this.height*=a},x.prototype.isEmpty=function(){return this.width<=0||this.height<=0},x.prototype.containsX=function(a){return a>=this.x&&a=this.y&&a=this.y&&a=this.x&&a0&&a.height>0}return a(this.radii.topLeft)||a(this.radii.topRight)||a(this.radii.bottomLeft)||a(this.radii.bottomRight)},y.prototype.cornersInsetRect=function(){var a=this.topLeftCorner(),b=this.topRightCorner(),c=this.bottomLeftCorner(),d=this.bottomRightCorner(),e=Math.max(a.maxX,c.maxX),f=Math.max(a.maxY,b.maxY);return new x(e,f,Math.min(b.x,d.x)-e,Math.min(c.y,d.y)-f)},y.prototype.scaleRadii=function(a){if(1!=a){var b=this.radii;b.topLeft.scale(a),b.topLeft.isEmpty()&&(b.topLeft=w.zeroSize),b.topRight.scale(a),b.topRight.isEmpty()&&(b.topRight=w.zeroSize),b.bottomLeft.scale(a),b.bottomLeft.isEmpty()&&(b.bottomLeft=w.zeroSize),b.bottomRight.scale(a),b.bottomRight.isEmpty()&&(b.bottomRight=w.zeroSize)}},y.prototype.isRenderable=function(){var a=this.radii,b=this.rect;return a.topLeft.width+a.topRight.width<=b.width&&a.bottomLeft.width+a.bottomRight.width<=b.width&&a.topLeft.height+a.bottomLeft.height<=b.height&&a.topRight.height+a.bottomRight.height<=b.height},y.prototype.adjustRadii=function(){var a=this.radii,b=Math.max(a.topLeft.width+a.topRight.width,a.bottomLeft.width+a.bottomRight.width),c=Math.max(a.topLeft.height+a.bottomLeft.height,a.topRight.height+a.bottomRight.height);if(0>=b||0>=c)return void(this.radii={topLeft:w.zeroSize,topRight:w.zeroSize,bottomRight:w.zeroSize,bottomLeft:w.zeroSize});var d=this.rect,e=d.width/b,f=d.height/c;this.scaleRadii(f>e?e:f)},y.prototype.minXInterceptAt=function(a,b){if(!this.rect.containsY(a))return b;var c,d=this.topLeftCorner();if(d.containsY(a))return c=d.maxY-a,d.maxX-z(c,d.width,d.height);var e=this.bottomLeftCorner();return e.containsY(a)?(c=a-e.y,e.maxX-z(c,e.width,e.height)):this.rect.x},y.prototype.maxXInterceptAt=function(a,b){if(!this.rect.containsY(a))return b;var c,d=this.topRightCorner();if(d.containsY(a))return c=d.maxY-a,d.x+z(c,d.width,d.height);var e=this.bottomRightCorner();return e.containsY(a)?(c=a-e.y,e.x+z(c,e.width,e.height)):this.rect.maxX},y.prototype.rightExclusionEdge=function(a,b){return this.rect.isEmpty()||!this.rect.overlapsYRange(a,b)?void 0:!this.isRounded()||this.cornersInsetRect().overlapsYRange(a,b)?this.rect.maxX:Math.max(this.maxXInterceptAt(a,this.rect.x),this.maxXInterceptAt(b,this.rect.x))},y.prototype.leftExclusionEdge=function(a,b){return this.rect.isEmpty()||!this.rect.overlapsYRange(a,b)?void 0:!this.isRounded()||this.cornersInsetRect().overlapsYRange(a,b)?this.rect.x:Math.min(this.minXInterceptAt(a,this.rect.maxX),this.minXInterceptAt(b,this.rect.maxX))},y.prototype.rightExclusionOffsets=F(y.prototype.topRightCorner,y.prototype.bottomRightCorner,E,C),y.prototype.leftExclusionOffsets=F(y.prototype.topLeftCorner,y.prototype.bottomLeftCorner,D,B),N.prototype.onReady=function(a){this.ready?a():this.callback=a},N.prototype.leftExclusionEdge=function(a){return this.geometry?this.geometry.leftExclusionEdge(a.top,a.bottom):a.left},N.prototype.rightExclusionEdge=function(a){return this.geometry?this.geometry.rightExclusionEdge(a.top,a.bottom):a.right},N.prototype.computeStepOffsets=function(a){for(var b,c=[],d=0;d1?f[1]:e.insets[0],e.insets[2]=f.length>2?f[2]:e.insets[0],e.insets[3]=f.length>3?f[3]:e.insets[1],e.insets[0]=c.toPixels(e.insets[0],b.height),e.insets[1]=c.toPixels(e.insets[1],b.width),e.insets[2]=c.toPixels(e.insets[2],b.height),e.insets[3]=c.toPixels(e.insets[3],b.width)}var g;return a&&a[2]&&(g=a[2].trim(),g=g.split(/\s+/),g.length<2&&g.push(g[0]),g.length<3&&g.push(g[0]),g.length<4&&g.push(g[1]),e.radii=g.map(function(a){return a=c.toPixels(a,b.width),[a,a]})),a&&a[3]&&(g=a[3].trim(),g=g.split(/\s+/),g.length<2&&g.push(g[0]),g.length<3&&g.push(g[0]),g.length<4&&g.push(g[1]),g.forEach(function(a,d){e.radii[d][1]=c.toPixels(a,b.height)})),e.x=e.insets[3],e.y=e.insets[0],e.width=b.width-(e.insets[1]+e.insets[3]),e.height=b.height-(e.insets[0]+e.insets[2]),e},R.prototype.parseEllipsoid=function(a){var b=/((?:[^a]|a(?!t))*)?\s*(?:at\s+(.*))?/;a=b.exec(a);var c={};if(a&&a[1]){var d=a[1].trim();d=d.split(/\s+/),c.rx=d[0],c.ry=d.length>1?d[1]:d[0]}else c.rx=c.ry="closest-side";var e=[];if(a&&a[2]){var f=a[2].trim();f=f.split(/\s+/);var g=!1;f.forEach(function(a){/\d+/.test(a)&&g?e[e.length-1]+=" "+a:e.push(a),g=/top|bottom|left|right/.test(a)&&f.length>2})}for(;e.length<2;)e.push("center");if(/top|bottom/.test(e[0])||/left|right/.test(e[1])){var h=e[0];e[0]=e[1],e[1]=h}return c.cx=e[0],c.cy=e[1],c},R.prototype.parseCircle=function(a,b,c){var d=this.parseEllipsoid(a);return d.type="circle",d.cx=W(d.cx,b.width,c),d.cy=W(d.cy,b.height,c),d.r=X(d.rx,[Math.abs(d.cx),Math.abs(b.width-d.cx),Math.abs(d.cy),Math.abs(b.height-d.cy)],Math.sqrt((b.width*b.width+b.height*b.height)/2),c),delete d.rx,delete d.ry,d},R.prototype.parseEllipse=function(a,b,c){var d=this.parseEllipsoid(a);return d.type="ellipse",d.cx=W(d.cx,b.width,c),d.cy=W(d.cy,b.height,c),d.rx=X(d.rx,[Math.abs(d.cx),Math.abs(b.width-d.cx)],b.width,c),d.ry=X(d.ry,[Math.abs(d.cy),Math.abs(b.height-d.cy)],b.height,c),d},R.prototype.parsePolygon=function(a,b,c){a=a.split(/\s*,\s*/);var d="nonzero";a.length>0&&/nonzero|evenodd/.test(a[0])&&(d=a[0].trim(),a=a.slice(1));var e=a.map(function(a){var d=a.split(/\s+/);return{x:c.toPixels(d[0],b.width),y:c.toPixels(d[1],b.height)}});return{type:"polygon",fillRule:d,points:e}},R.prototype.computeClip=function(a,b){var c=b.margins[3],d=b.margins[0],e=b.margins[3]+b.margins[1],f=b.margins[0]+b.margins[2];return{x:-a.x-c,y:-a.y-d,width:b.borderBox.width+e,height:b.borderBox.height+f}},R.prototype.parseShapeMargin=function(a,b,c){return parseInt(a)?Math.max(0,c.toPixels(a,b.width)):0},R.prototype.parseShapeImageThreshold=function(a){var b=parseFloat(a);return b?Math.min(Math.max(0,b),1):0},Z.prototype.load=function(a,b,c){var d=this;if(this.url){var e=new XMLHttpRequest;e.onreadystatechange=function(){4===e.readyState&&(200===e.status?(d.cssText=e.responseText,a.call(c,d)):b.call(c,d))},e.open("GET",this.url);try{e.send(null)}catch(f){console.log("An error occurred loading a stylesheet, probably because we can't access the local file system"),b.call(c,d)}}else this.cssText=this.source.textContent,a.call(c,d)},$.prototype.init=function(){var a,b,c=Y(),d=c.length;for(this.queueCount=d,b=0;d>b;b++)a=new Z(c[b]),this.stylesheets.push(a),a.load(this.onStyleSheetLoad,this.onStyleSheetError,this)},$.prototype.onStyleSheetLoad=function(){this.queueCount--,this.onComplete.call(this)},$.prototype.onStyleSheetError=function(a){var b,c=this.stylesheets.length;for(b=0;c>b;b++)if(a.source===this.stylesheets[b].source)return this.stylesheets.splice(b,1),this.queueCount--,void this.onComplete.call(this)},$.prototype.onComplete=function(){0===this.queueCount&&this.callback.call(this,this.stylesheets)},_.prototype.onStylesLoaded=function(a){var b,c,d="\\s*([^{}]*[^\\s])\\s*{[^\\}]*",e="\\s*:\\s*((?:[^;\\(]|\\([^\\)]*\\))*)\\s*;",f=[],g=["shape-outside","shape-margin","shape-image-threshold"]; -g.forEach(function(g){b=new RegExp(d+"("+g+")"+e,"ig"),a.forEach(function(a){for(;null!==(c=b.exec(a.cssText));)f.push({selector:c[1],property:c[2],value:c[3]})})}),this.callback(f)},a.ShapesPolyfill=new O(a)}(window); \ No newline at end of file +!function(a){"use strict";function b(a){var b=getComputedStyle(a);this.units={px:1},this.element=a;var c=function(a){return a&&a.length?parseInt(a):0};this.margins=[b.marginTop,b.marginRight,b.marginBottom,b.marginLeft],this.margins=this.margins.map(c),this.borders=[b.borderTopWidth,b.borderRightWidth,b.borderBottomWidth,b.borderLeftWidth],this.borders=this.borders.map(c),this.paddings=[b.paddingTop,b.paddingRight,b.paddingBottom,b.paddingLeft],this.paddings=this.paddings.map(c),this.borderBox={x:0,y:0,width:a.offsetWidth,height:a.offsetHeight},this.marginBox={x:-this.margins[3],y:-this.margins[0],width:a.offsetWidth+this.margins[1]+this.margins[3],height:a.offsetHeight+this.margins[0]+this.margins[2]};var d=this,e=["borderTopLeftRadius","borderTopRightRadius","borderBottomRightRadius","borderBottomLeftRadius"];this.borderBox.radii=e.map(function(a,c){return a=b[a].split(/\s+/),[d.toPixels(a[0],d.borderBox.width),d.toPixels(a.length>1?a[1]:a[0],d.borderBox.height)]}),this.cssFloat=b.cssFloat}function c(a,b,c){return(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y)}function d(a,b,d){return Math.abs(c(a,b,d))<350}function e(a,b){return a.x==b.x&&a.y==b.y}function f(a,b,c){return c.x>=Math.min(a.x,b.x)&&c.x<=Math.max(a.x,b.x)&&d(a,b,c)}function g(){}function h(a,b,c,d){if(a.y>=c&&a.y<=d)return{x1:a.x-b,x2:a.x+b};var e,f;return d0?a[0].x:void 0,g=a.length>0?a[0].y:void 0,h=f,l=g,m=k(a),n=0;do{var o=this.nextEdgeVertexIndex(n,m);e.push(new i(this,a[n],a[o]));var p=a[n].x,q=a[n].y;f=Math.min(p,f),g=Math.min(q,g),h=Math.max(p,h),l=Math.max(q,l),n=o}while(0!==n);for(var r,s=0;s3;)r=(s+1)%e.length,d(e[s].vertex1,e[s].vertex2,e[r].vertex2)?(e[s].vertex2=e[r].vertex2,e.splice(r,1)):s++;if(0===c)this.shapeMarginEdges=e;else{for(var t=[],u=0;uc;c++)this.intervals[c]=r.none;this.minY=-a,this.maxY=b-a}function s(a){this.shapeMargin=a,this.xIntercepts=[];for(var b=0;a>=b;b++)this.xIntercepts[b]=Math.sqrt(a*a-b*b)}function t(a,b){console.log("Unable to load image ",a,". It's probably missing or you've run into a CORS issue."),b&&console.log("The exact problem was ",b)}function u(a,b,c){var d=document.createElement("canvas");this.width=d.width=b,this.height=d.height=c;var e=d.getContext("2d");e.drawImage(a,0,0,b,c);try{this.imageData=e.getImageData(0,0,b,c)}catch(f){t(a.src,f)}}function v(a,b,c,d,e,f){this.url=a,this.box=b,this.shapeImageThreshold=256*c,this.shapeMargin=d,this.clip=e,this.init(f)}function w(a,b){this.width=a,this.height=b}function x(a,b,c,d){this.x=a,this.y=b,this.width=c,this.height=d,this.maxX=a+c,this.maxY=b+d}function y(a,b,c,d,e){this.rect=a,this.radii={topLeft:b,topRight:c,bottomLeft:d,bottomRight:e}}function z(a,b,c){return b*Math.sqrt(1-a*a/(c*c))}function A(a,b,c){return 0===b?1:Math.round(0===a||c>a*b/2?b:Math.sqrt(2*c*(b/a)))}function B(a,b){return a.maxX-b}function C(a,b){return a.x+b}function D(a){return a.x}function E(a){return a.maxX}function F(a,b,c,d){return function(e,f,g){if(!this.rect.overlapsYRange(e,f))return[{x:void 0,height:f-e}];var h=[];el;l+=i)m=o.maxY-Math.min(l+i,k),n=z(m,o.width,o.height),h.push({height:Math.min(i,k-l),x:d(o,n)});if(j=Math.max(q.y,e),k=Math.min(q.maxY,f),q.overlapsYRange(e,f)&&h.push({x:c(q),height:k-j}),p.overlapsYRange(e,f))for(i=A(p.width,p.height,g),j=Math.max(e,p.y),k=Math.min(p.maxY,f),l=j;k>l;l+=i)m=l-p.y,n=z(m,p.width,p.height),h.push({height:Math.min(i,k-l),x:d(p,n)});return f>this.rect.maxY&&h.push({x:void 0,height:f-this.rect.maxY}),h}}function G(a,b){var c=a.r+b,d=new w(c,c);return new y(new x(a.cx-c,a.cy-c,2*c,2*c),d,d,d,d)}function H(a,b){var c=new w(a.rx+b,a.ry+b);return new y(new x(a.cx-c.width,a.cy-c.height,2*c.width,2*c.height),c,c,c,c)}function I(a,b){function c(a){return new w(a[0]+b,a[1]+b)}var d=c(a.radii[0]),e=c(a.radii[1]),f=c(a.radii[2]),g=c(a.radii[3]),h=new x(a.x-b,a.y-b,a.width+2*b,a.height+2*b);return new y(h,d,e,g,f)}function J(a,b){function c(a){return new w(a[0]+b,a[1]+b)}var d=c(a.radii[0]),e=c(a.radii[1]),f=c(a.radii[2]),g=c(a.radii[3]),h=new x(-b,-b,a.width+2*b,a.height+2*b);return new y(h,d,e,g,f)}function K(a,b,c,d,e,f){var g=new x(e.x,e.y,e.width,e.height);return new v(a,b,c,d,g,f)}function L(a,b){return new l(a.points,a.fillRule,b)}function M(a,b){var c,d=void 0===a.shapeMargin?0:a.shapeMargin;if(a.shape){switch(a.shape.type){case"circle":c=G(a.shape,d);break;case"ellipse":c=H(a.shape,d);break;case"inset":c=I(a.shape,d),c.isRenderable()||c.adjustRadii();break;case"polygon":c=L(a.shape,d)}return b(),c}return a.url?K(a.url,a.box,a.shapeImageThreshold,d,a.clip,b):a.box?(c=J(a.box,d),b(),c):void console.error("Unrecognized shape")}function N(a){this.metrics=new b(a);var c=this.getQueryStep(a.getAttribute("data-shape-size-mediaqueries").split("|")),d={metrics:this.metrics,shapeOutside:a.getAttribute("data-shape-outside").split("|")[c],shapeMargin:a.getAttribute("data-shape-margin").split("|")[c],shapeImageThreshold:a.getAttribute("data-shape-image-threshold").split("|")[c]};this.shapeValue=new R(d);var e=this;this.geometry=M(this.shapeValue,function(){e.ready=!0,e.callback&&e.callback()})}function O(a){this.scope=a;var b=document.currentScript;b||(b=document.getElementsByTagName("script"),b=b[b.length-1]);var c=this,d="false"!==b.getAttribute("data-auto-run");d&&a.addEventListener&&a.addEventListener("load",function(){c.run()})}function P(a,b){var c,d=document.createElement("div");b.forEach(function(a,b){var e=a.bottom-a.top,f=document.createElement("div");f.className="sandbag",c={cssFloat:a.cssFloat,width:a.offset+"px",height:e+"px",clear:a.cssFloat};for(var g in c)f.style[g]=c[g];d.appendChild(f)}),c={position:"relative",width:"auto",height:"0",clear:"both",pointerEvents:"none"};for(var e in c)d.style[e]=c[e];var f,g=a.parentNode,h=getComputedStyle(g),i=parseFloat(h.borderTop)+parseFloat(h.borderBottom);c={position:"absolute",top:"0",width:"100%",height:g.clientHeight-i,left:"0"},f=document.createElement("div");for(e in c)f.style[e]=c[e];d.appendChild(f),a.parentNode&&a.parentNode.insertBefore(d,a),f.appendChild(a),d.setAttribute("data-shape-outside-container","true")}function Q(a,b){var c;return function(){var d=this,e=arguments;clearTimeout(c),c=setTimeout(function(){c=null,a.apply(d,e)},b)}}function R(a){return a&&a.metrics&&a.shapeOutside?(this.url=this.parseUrl(a.shapeOutside),this.box=this.parseBox(this.url?"content-box":a.shapeOutside,a.metrics),this.shape=this.parseBasicShape(a.shapeOutside,this.box,a.metrics),this.clip=this.computeClip(this.box,a.metrics),this.shapeMargin=this.parseShapeMargin(a.shapeMargin,this.box,a.metrics),void(this.shapeImageThreshold=this.parseShapeImageThreshold(a.shapeImageThreshold))):void console.error("ShapeValue requires at least a metrics object and shape-outside string")}function S(a,b,c){var d=c.reduce(function(a,b){return a+b[0]},0),e=c.reduce(function(a,b){return a+b[1]},0),f=c.reduce(function(a,b){return a+b[2]},0),g=c.reduce(function(a,b){return a+b[3]},0);a.x-=b*g,a.y-=b*d,a.width+=b*(g+e),a.height+=b*(d+f)}function T(a,b,c){if(0>b)return Math.max(a+b*c,0);var d=Math.abs(a/c);return 1>d?Math.max(a+c*(1+Math.pow(d-1,3)),0):a+c}function U(a,b,c){var d=c.reduce(function(a,b){return a+b[0]},0),e=c.reduce(function(a,b){return a+b[1]},0),f=c.reduce(function(a,b){return a+b[2]},0),g=c.reduce(function(a,b){return a+b[3]},0);a[0][0]=T(a[0][0],b,g),a[0][1]=T(a[0][1],b,d),a[1][0]=T(a[1][0],b,e),a[1][1]=T(a[1][1],b,d),a[2][0]=T(a[2][0],b,e),a[2][1]=T(a[2][1],b,f),a[3][0]=T(a[3][0],b,g),a[3][1]=T(a[3][1],b,f)}function V(a,b){return a.map(function(a){return a[b]})}function W(a,b,c){a=a.split(/\s+/);var d="TopLeft",e=0;switch(a[0]){case"top":case"left":break;case"bottom":case"right":d="BottomRight";break;case"center":e=b/2;break;default:e=c.toPixels(a[0],b)}return a.length>1&&(e=c.toPixels(a[1],b)),"TopLeft"===d?e:b-e}function X(a,b,c,d){return"closest-side"===a?Math.min.apply(null,b):"farthest-side"===a?Math.max.apply(null,b):d.toPixels(a,c)}function Y(){var a,b,c=document,d=[];if("function"==typeof c.querySelectorAll)d=c.querySelectorAll('link[rel="stylesheet"], style'),d=Array.prototype.slice.call(d,0);else{var e=c.getElementsByTagName("link");if(e.length)for(a=0,b=e.length;b>a;a++)"stylesheet"===e[a].getAttribute("rel")&&d.push(e[a]);for(e=c.getElementsByTagName("style"),a=0,b=e.length;b>a;a++)d.push(e[a])}return d}function Z(a){this.source=a,this.url=a.href||null,this.cssText=""}function $(a){return this instanceof $?(this.stylesheets=[],this.queueCount=0,this.callback=a||function(){},void this.init()):new $(a)}function _(a){this.callback=a||function(){},this.eminpx=this.getEmValue();var b=this;new $(function(a){b.onStylesLoaded(a)})}b.prototype.unitToPx=function(a){if(this.units[a])return this.units[a];var b=this.element.style.getPropertyValue("line-height");return this.element.style.setProperty("line-height",1+a),this.units[a]=parseFloat(getComputedStyle(this.element).getPropertyValue("line-height")),this.element.style.setProperty("line-height",b),this.units[a]},b.prototype.getUnitsMap=function(a){var b=["em","ex","ch","rem","vw","vh","vmin","vmax","cm","mm","in","px","pt","pc"],c=document.createElement("div");c.style.width="0px",c.style.height="0px",a.appendChild(c);var d=getComputedStyle(c),e={};return b.forEach(function(a){c.style.lineHeight="1"+a,e[a]=parseFloat(d.lineHeight)}),c.parentNode.removeChild(c),e},b.prototype.toPixels=function(a,b){var c=/([\-0-9\.]*)([a-z%]*)/.exec(a);return c[1]=parseFloat(c[1]),c[2]?"%"===c[2]?c[1]*b/100:c[1]*this.unitToPx(c[2]):c[1]},g.prototype.init=function(a,b,c){this.polygon=a,this.vertex1=b,this.vertex2=c,this.minX=Math.min(this.vertex1.x,this.vertex2.x),this.maxX=Math.max(this.vertex1.x,this.vertex2.x)},g.prototype.containsPoint=function(a){return f(this.vertex1,this.vertex2,a)},g.prototype.overlapsYRange=function(a,b){var c=this.vertex1.y,d=this.vertex2.y;return b>=Math.min(c,d)&&a<=Math.max(c,d)},g.prototype.isWithinYRange=function(a,b){var c=this.vertex1.y,d=this.vertex2.y;return a<=Math.min(c,d)&&b>=Math.max(c,d)},g.prototype.inwardNormal=function(){var a=this.vertex2.x-this.vertex1.x,b=this.vertex2.y-this.vertex1.y,c=Math.sqrt(a*a+b*b);return{x:-b/c,y:a/c}},g.prototype.outwardNormal=function(){var a=this.inwardNormal();return{x:-a.x,y:-a.y}},g.prototype.xIntercept=function(a){var b=this.vertex1.y,c=this.vertex2.y;return b==c?Math.min(this.vertex1.x,this.vertex2.x):a==Math.min(b,c)?c>b?this.vertex1.x:this.vertex2.x:a==Math.max(b,c)?b>c?this.vertex1.x:this.vertex2.x:this.vertex1.x+(a-b)*(this.vertex2.x-this.vertex1.x)/(c-b)},g.prototype.clippedEdgeXRange=function(a,b){if(this.isWithinYRange(a,b)){var c=this.vertex1.x,d=this.vertex2.x;return{x1:Math.min(c,d),x2:Math.max(c,d)}}var e,f;this.vertex1.yb?this.xIntercept(b):f.x;return{x1:Math.min(g,h),x2:Math.max(g,h)}},i.prototype=new g,j.prototype=new g,l.prototype.vertexAt=function(a){return this.m_vertices[a]},l.prototype.edgeAt=function(a){return this.m_edges[a]},l.prototype.isEmpty=function(){return this.m_edges.length<3||this.bounds.isEmpty()},l.prototype.vertices=function(){return this.m_vertices.slice(0)},l.prototype.edges=function(){return this.m_edges.slice(0)},l.prototype.overlapsYRange=function(a,b){return a=this.bounds.y},l.prototype.nextVertexIndex=function(a,b){var c=this.m_vertices.length;return(b?a+1:a-1+c)%c},l.prototype.nextEdgeVertexIndex=function(a,b){for(var c=(this.m_vertices.length,this.nextVertexIndex(a,b));c&&e(this.vertexAt(a),this.vertexAt(c));)c=this.nextVertexIndex(c,b);for(;c;){var f=this.nextVertexIndex(c,b);if(!d(this.vertexAt(a),this.vertexAt(c),this.vertexAt(f)))break;c=f}return c},l.prototype.containsPointEvenOdd=function(a){for(var b=0,c=0;ca.y||e.y>a.y&&f.y<=a.y){var g=(a.y-e.y)/(f.y-e.y);a.xa.y&&c(f,g,a)>0&&++b:g.y>a.y&&f.y<=a.y&&c(f,g,a)<0&&--b}return 0!==b},l.prototype.containsPoint=function(a){return this.bounds.containsPoint(a)?"nonzero"==this.fillRule?this.containsPointNonZero(a):this.containsPointEvenOdd(a):!1},l.prototype.edgeVerticesThatOverlapYRange=function(a,b){for(var c=[],d=0;d=a&&e.yc);d++)e=f[d].clippedEdgeXRange(a,b),c=void 0===c?e.x1:Math.min(c,e.x1);var g=this.shapeMargin;if(g>0){var i=this.edgeVerticesThatOverlapYRange(a-g,b+g);for(i.sort(n),d=0;d0){var i=this.edgeVerticesThatOverlapYRange(a-g,b+g);for(i.sort(p),d=0;d=b.endX},s.prototype.generateIntervalAt=function(a,b){var c=Math.abs(a-b.y),d=c>this.shapeMargin?0:this.xIntercepts[c];return new q(a,b.startX-d,b.endX+d)},r.prototype.computeMarginIntervals=function(a,b){for(var c=new s(a),d=new r(this.yOffset,this.size),e=this.minY;e=h&&!(g>0&&this.intervalAtContains(g,f));--g)d.uniteIntervalAt(g,c.generateIntervalAt(g,f));for(d.uniteIntervalAt(e,c.generateIntervalAt(e,f)),g=e+1;i>=g&&!(g0&&(c.intervals=c.intervals.computeMarginIntervals(c.shapeMargin,c.clip)),b&&URL.revokeObjectURL(b),a()},d.onerror=function(){t(c.url),a()},!d.hasOwnProperty("crossOrigin")&&window.URL&&window.URL.createObjectURL){var f=new XMLHttpRequest;f.onreadystatechange=function(){4===f.readyState&&(200===f.status?(b=URL.createObjectURL(f.response),d.src=b):(t(c.url),a()))},f.open("GET",c.url,!0),f.responseType="blob",f.send()}else d.crossOrigin="anonymous",d.src=c.url},v.prototype.computeIntervals=function(a){var b=this.clip,c=this.shapeImageThreshold,d=this.box.width,e=this.box.height,f=new u(a,d,e);if(!f.hasData())return void 0;for(var g=new r(-b.y,b.height),h=Math.min(b.height,this.box.height),i=0;h>i;i++)for(var j=-1,k=0;kc?(j=k,g.intervalAt(i)===r.none&&g.setIntervalAt(i,new q(i,j,d))):-1!=j&&c>=l&&(g.intervalAt(i).endX=k,j=-1)}return g},v.prototype.rightExclusionEdge=function(a,b){var c=this.intervals;if(!c)return this.clip.width;for(var d,e=Math.max(a,this.clip.y);b>=e&&ed)&&(d=f)}return d},v.prototype.leftExclusionEdge=function(a,b){var c=this.intervals;if(!c)return 0;for(var d,e=Math.max(a,this.clip.y);b>=e&&ef)&&(d=f)}return d},w.zeroSize={width:0,height:0},w.prototype.isEmpty=function(){return this.width<=0||this.height<=0},w.prototype.scale=function(a){this.width*=a,this.height*=a},x.prototype.isEmpty=function(){return this.width<=0||this.height<=0},x.prototype.containsX=function(a){return a>=this.x&&a=this.y&&a=this.y&&a=this.x&&a0&&a.height>0}return a(this.radii.topLeft)||a(this.radii.topRight)||a(this.radii.bottomLeft)||a(this.radii.bottomRight)},y.prototype.cornersInsetRect=function(){var a=this.topLeftCorner(),b=this.topRightCorner(),c=this.bottomLeftCorner(),d=this.bottomRightCorner(),e=Math.max(a.maxX,c.maxX),f=Math.max(a.maxY,b.maxY);return new x(e,f,Math.min(b.x,d.x)-e,Math.min(c.y,d.y)-f)},y.prototype.scaleRadii=function(a){if(1!=a){var b=this.radii;b.topLeft.scale(a),b.topLeft.isEmpty()&&(b.topLeft=w.zeroSize),b.topRight.scale(a),b.topRight.isEmpty()&&(b.topRight=w.zeroSize),b.bottomLeft.scale(a),b.bottomLeft.isEmpty()&&(b.bottomLeft=w.zeroSize),b.bottomRight.scale(a),b.bottomRight.isEmpty()&&(b.bottomRight=w.zeroSize)}},y.prototype.isRenderable=function(){var a=this.radii,b=this.rect;return a.topLeft.width+a.topRight.width<=b.width&&a.bottomLeft.width+a.bottomRight.width<=b.width&&a.topLeft.height+a.bottomLeft.height<=b.height&&a.topRight.height+a.bottomRight.height<=b.height},y.prototype.adjustRadii=function(){var a=this.radii,b=Math.max(a.topLeft.width+a.topRight.width,a.bottomLeft.width+a.bottomRight.width),c=Math.max(a.topLeft.height+a.bottomLeft.height,a.topRight.height+a.bottomRight.height);if(0>=b||0>=c)return void(this.radii={topLeft:w.zeroSize,topRight:w.zeroSize,bottomRight:w.zeroSize,bottomLeft:w.zeroSize});var d=this.rect,e=d.width/b,f=d.height/c;this.scaleRadii(f>e?e:f)},y.prototype.minXInterceptAt=function(a,b){if(!this.rect.containsY(a))return b;var c,d=this.topLeftCorner();if(d.containsY(a))return c=d.maxY-a,d.maxX-z(c,d.width,d.height);var e=this.bottomLeftCorner();return e.containsY(a)?(c=a-e.y,e.maxX-z(c,e.width,e.height)):this.rect.x},y.prototype.maxXInterceptAt=function(a,b){if(!this.rect.containsY(a))return b;var c,d=this.topRightCorner();if(d.containsY(a))return c=d.maxY-a,d.x+z(c,d.width,d.height);var e=this.bottomRightCorner();return e.containsY(a)?(c=a-e.y,e.x+z(c,e.width,e.height)):this.rect.maxX},y.prototype.rightExclusionEdge=function(a,b){return this.rect.isEmpty()||!this.rect.overlapsYRange(a,b)?void 0:!this.isRounded()||this.cornersInsetRect().overlapsYRange(a,b)?this.rect.maxX:Math.max(this.maxXInterceptAt(a,this.rect.x),this.maxXInterceptAt(b,this.rect.x))},y.prototype.leftExclusionEdge=function(a,b){return this.rect.isEmpty()||!this.rect.overlapsYRange(a,b)?void 0:!this.isRounded()||this.cornersInsetRect().overlapsYRange(a,b)?this.rect.x:Math.min(this.minXInterceptAt(a,this.rect.maxX),this.minXInterceptAt(b,this.rect.maxX))},y.prototype.rightExclusionOffsets=F(y.prototype.topRightCorner,y.prototype.bottomRightCorner,E,C),y.prototype.leftExclusionOffsets=F(y.prototype.topLeftCorner,y.prototype.bottomLeftCorner,D,B),N.prototype.onReady=function(a){this.ready?a():this.callback=a},N.prototype.getQueryStep=function(a){var b,c,d=0,e=0,f=document.documentElement.clientWidth;for(d;d=b&&c>=f&&(e=d);return e},N.prototype.leftExclusionEdge=function(a){return this.geometry?this.geometry.leftExclusionEdge(a.top,a.bottom):a.left},N.prototype.rightExclusionEdge=function(a){return this.geometry?this.geometry.rightExclusionEdge(a.top,a.bottom):a.right},N.prototype.computeStepOffsets=function(a){for(var b,c=[],d=0;d1?f[1]:e.insets[0],e.insets[2]=f.length>2?f[2]:e.insets[0],e.insets[3]=f.length>3?f[3]:e.insets[1],e.insets[0]=c.toPixels(e.insets[0],b.height),e.insets[1]=c.toPixels(e.insets[1],b.width),e.insets[2]=c.toPixels(e.insets[2],b.height),e.insets[3]=c.toPixels(e.insets[3],b.width)}var g;return a&&a[2]&&(g=a[2].trim(),g=g.split(/\s+/),g.length<2&&g.push(g[0]),g.length<3&&g.push(g[0]),g.length<4&&g.push(g[1]),e.radii=g.map(function(a){return a=c.toPixels(a,b.width),[a,a]})),a&&a[3]&&(g=a[3].trim(),g=g.split(/\s+/),g.length<2&&g.push(g[0]),g.length<3&&g.push(g[0]),g.length<4&&g.push(g[1]),g.forEach(function(a,d){e.radii[d][1]=c.toPixels(a,b.height)})),e.x=e.insets[3],e.y=e.insets[0],e.width=b.width-(e.insets[1]+e.insets[3]),e.height=b.height-(e.insets[0]+e.insets[2]),e},R.prototype.parseEllipsoid=function(a){var b=/((?:[^a]|a(?!t))*)?\s*(?:at\s+(.*))?/;a=b.exec(a);var c={};if(a&&a[1]){var d=a[1].trim();d=d.split(/\s+/),c.rx=d[0],c.ry=d.length>1?d[1]:d[0]}else c.rx=c.ry="closest-side";var e=[];if(a&&a[2]){var f=a[2].trim();f=f.split(/\s+/);var g=!1;f.forEach(function(a){/\d+/.test(a)&&g?e[e.length-1]+=" "+a:e.push(a),g=/top|bottom|left|right/.test(a)&&f.length>2})}for(;e.length<2;)e.push("center");if(/top|bottom/.test(e[0])||/left|right/.test(e[1])){var h=e[0];e[0]=e[1],e[1]=h}return c.cx=e[0],c.cy=e[1],c},R.prototype.parseCircle=function(a,b,c){var d=this.parseEllipsoid(a);return d.type="circle",d.cx=W(d.cx,b.width,c),d.cy=W(d.cy,b.height,c),d.r=X(d.rx,[Math.abs(d.cx),Math.abs(b.width-d.cx),Math.abs(d.cy),Math.abs(b.height-d.cy)],Math.sqrt((b.width*b.width+b.height*b.height)/2),c),delete d.rx,delete d.ry,d},R.prototype.parseEllipse=function(a,b,c){var d=this.parseEllipsoid(a);return d.type="ellipse",d.cx=W(d.cx,b.width,c),d.cy=W(d.cy,b.height,c),d.rx=X(d.rx,[Math.abs(d.cx),Math.abs(b.width-d.cx)],b.width,c),d.ry=X(d.ry,[Math.abs(d.cy),Math.abs(b.height-d.cy)],b.height,c),d},R.prototype.parsePolygon=function(a,b,c){a=a.split(/\s*,\s*/);var d="nonzero";a.length>0&&/nonzero|evenodd/.test(a[0])&&(d=a[0].trim(),a=a.slice(1));var e=a.map(function(a){var d=a.split(/\s+/);return{x:c.toPixels(d[0],b.width),y:c.toPixels(d[1],b.height)}});return{type:"polygon",fillRule:d,points:e}},R.prototype.computeClip=function(a,b){var c=b.margins[3],d=b.margins[0],e=b.margins[3]+b.margins[1],f=b.margins[0]+b.margins[2];return{x:-a.x-c,y:-a.y-d,width:b.borderBox.width+e,height:b.borderBox.height+f}},R.prototype.parseShapeMargin=function(a,b,c){return parseInt(a)?Math.max(0,c.toPixels(a,b.width)):0; + +},R.prototype.parseShapeImageThreshold=function(a){var b=parseFloat(a);return b?Math.min(Math.max(0,b),1):0},Z.prototype.load=function(a,b,c){var d=this;if(this.url){var e=new XMLHttpRequest;e.onreadystatechange=function(){4===e.readyState&&(200===e.status?(d.cssText=e.responseText,a.call(c,d)):b.call(c,d))},e.open("GET",this.url);try{e.send(null)}catch(f){console.log("An error occurred loading a stylesheet, probably because we can't access the local file system"),b.call(c,d)}}else this.cssText=this.source.textContent,a.call(c,d)},$.prototype.init=function(){var a,b,c=Y(),d=c.length;for(this.queueCount=d,b=0;d>b;b++)a=new Z(c[b]),this.stylesheets.push(a),a.load(this.onStyleSheetLoad,this.onStyleSheetError,this)},$.prototype.onStyleSheetLoad=function(a){this.queueCount--,this.onComplete.call(this)},$.prototype.onStyleSheetError=function(a){var b,c=this.stylesheets.length;for(b=0;c>b;b++)if(a.source===this.stylesheets[b].source)return this.stylesheets.splice(b,1),this.queueCount--,void this.onComplete.call(this)},$.prototype.onComplete=function(){0===this.queueCount&&this.callback.call(this,this.stylesheets)},_.prototype.setPropertyForQuery=function(a,b,c){var d=a.getAttribute("data-"+b.property).split("|");d[c]=b.value,a.setAttribute("data-"+b.property,d.join("|"))},_.prototype.getEmValue=function(){var a,b=window.document.createElement("div"),c=window.document.body,d=window.document.documentElement,e=d.style.fontSize,f=c&&c.style.fontSize,g=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=g=doc.createElement("body"),c.style.background="none"),d.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),g&&d.insertBefore(c,d.firstChild),a=b.offsetWidth,g?d.removeChild(c):c.removeChild(b),d.style.fontSize=e,f&&(c.style.fontSize=f),a},_.prototype.onStylesLoaded=function(a){var b=this.parseForMediaQueries(a);this.parseForShapes(b)},_.prototype.parseForMediaQueries=function(a){var b,c,d,e,f=[],g=[],h=this;return a.forEach(function(a){b=a.cssText.replace(/\/\*[^*]*\*+([^/][^*]*\*+)*\//gi,""),c=b.match(/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi),c&&c.forEach(function(a){b=b.split(a).join(""),d=a.match(/\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/),e=a.match(/\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/),g.push({cssText:a.match(/@media *([^\{]+)\{([\S\s]+?)$/)[2],minWidth:d?"em"===d[2]?d[1]*h.eminpx:d[1]:null,maxWidth:e?"em"===e[2]?e[1]*h.eminpx:e[1]:null})}),f.push({cssText:b,minWidth:null,maxWidth:null})}),f.concat(g)},_.prototype.parseForShapes=function(a){var b,c,d="\\s*([^{}]*[^\\s])\\s*{[^\\}]*",e="\\s*:\\s*((?:[^;\\(]|\\([^\\)]*\\))*)\\s*;",f=[],g=["shape-outside","shape-margin","shape-image-threshold"];g.forEach(function(g){b=new RegExp(d+"("+g+")"+e,"ig"),a.forEach(function(a){for(;null!==(c=b.exec(a.cssText));)f.push({selector:c[1],property:c[2],value:c[3],minWidth:a.minWidth,maxWidth:a.maxWidth})})}),this.callback(f)},a.ShapesPolyfill=new O(a)}(window); \ No newline at end of file diff --git a/src/shape-info.js b/src/shape-info.js index 60b8f92..c9089ba 100644 --- a/src/shape-info.js +++ b/src/shape-info.js @@ -93,12 +93,16 @@ function createShapeGeometry(shapeValue, whenReady) { function ShapeInfo(element) { this.metrics = new Metrics(element); + + var queryStep = this.getQueryStep(element.getAttribute('data-shape-size-mediaqueries').split('|')); + var parserSettings = { metrics: this.metrics, - shapeOutside: element.getAttribute('data-shape-outside'), - shapeMargin: element.getAttribute('data-shape-margin'), - shapeImageThreshold: element.getAttribute('data-shape-image-threshold') + shapeOutside: element.getAttribute('data-shape-outside').split('|')[queryStep], + shapeMargin: element.getAttribute('data-shape-margin').split('|')[queryStep], + shapeImageThreshold: element.getAttribute('data-shape-image-threshold').split('|')[queryStep] }; + this.shapeValue = new ShapeValue(parserSettings); var self = this; @@ -116,6 +120,24 @@ ShapeInfo.prototype.onReady = function(callback) { this.callback = callback; }; +ShapeInfo.prototype.getQueryStep = function(steps) { + var i = 0, + step = 0, + documentWidth = document.documentElement.clientWidth, + minWidth, + maxWidth; + for(i; i < steps.length; i++) { + minWidth = steps[i].split(',')[0].split('(')[1]; + minWidth = minWidth === "null" ? 0 : Number(minWidth); + maxWidth = steps[i].split(',')[1].split(')')[0]; + maxWidth = maxWidth === "null" ? documentWidth : Number(maxWidth); + if(documentWidth >= minWidth && documentWidth <= maxWidth) { + step = i; + } + } + return step; +}; + ShapeInfo.prototype.leftExclusionEdge = function(line) { // { top, bottom, left, right } return this.geometry ? this.geometry.leftExclusionEdge(line.top, line.bottom) : line.left; }; diff --git a/src/shape-polyfill.js b/src/shape-polyfill.js index d0c0fd8..6533b4d 100644 --- a/src/shape-polyfill.js +++ b/src/shape-polyfill.js @@ -161,10 +161,43 @@ Polyfill.prototype.run = function(settings) { this.stylesLoaded = true; new StylePolyfill(function(rules) { + + var _this = this, + els, + queriesTab, + queryRule, + queryIndex; + rules.forEach(function(rule) { - var els = document.querySelectorAll(rule.selector); - for (var i = 0; i < els.length; i++) - els[i].setAttribute('data-' + rule.property, rule.value); + els = document.querySelectorAll(rule.selector); + + for (var i = 0; i < els.length; i++){ + // if this is new element, we init all the value to null + if(!els[i].hasAttribute('data-shape-outside')) { + els[i].setAttribute('data-shape-outside', 'null'); + els[i].setAttribute('data-shape-margin', 'null'); + els[i].setAttribute('data-shape-image-threshold', 'null'); + els[i].setAttribute('data-shape-size-mediaqueries', '(null,null)'); + } + + queriesTab = els[i].getAttribute('data-shape-size-mediaqueries').split('|'); + queryRule = '('+rule.minWidth+','+rule.maxWidth+')'; + queryIndex = queriesTab.indexOf(queryRule); + + if(queryIndex === -1) { + // mediaquery doesn't exist, we create a new entry + els[i].setAttribute('data-shape-outside', els[i].getAttribute('data-shape-outside') + '|null'); + els[i].setAttribute('data-shape-margin', els[i].getAttribute('data-shape-margin') + '|null'); + els[i].setAttribute('data-shape-image-threshold', els[i].getAttribute('data-shape-image-threshold') + '|null'); + els[i].setAttribute('data-shape-size-mediaqueries', els[i].getAttribute('data-shape-size-mediaqueries') + '|' + queryRule); + // we update specific entry + _this.setPropertyForQuery(els[i], rule, queriesTab.length); + } else { + // mediaquery exist, we update specific entry + _this.setPropertyForQuery(els[i], rule, queryIndex); + } + + } }); self.run(settings); @@ -180,8 +213,9 @@ Polyfill.prototype.run = function(settings) { } var els = document.querySelectorAll('[data-shape-outside]'); - for (var i = 0; i < els.length; i++) + for (var i = 0; i < els.length; i++){ this.polyfill(els[i], settings); + } }; Polyfill.prototype.teardown = function() { diff --git a/src/style-polyfill.js b/src/style-polyfill.js index 8303ed9..aa23de5 100644 --- a/src/style-polyfill.js +++ b/src/style-polyfill.js @@ -144,21 +144,113 @@ StyleLoader.prototype.onComplete = function() { function StylePolyfill(callback) { this.callback = callback || function() {}; + this.eminpx = this.getEmValue(); var self = this; new StyleLoader(function(stylesheets) { self.onStylesLoaded(stylesheets); }); } +StylePolyfill.prototype.setPropertyForQuery = function(elem, rule, index) { + var propertyQueriesTab = elem.getAttribute('data-' + rule.property).split('|'); + propertyQueriesTab[index] = rule.value; + elem.setAttribute('data-' + rule.property, propertyQueriesTab.join('|')); +}; + +// thanks to Scott Jehl getEmValue() function he wrote for Respond.js (https://github.com/scottjehl/Respond) +StylePolyfill.prototype.getEmValue = function() { + var ret, + div = window.document.createElement('div'), + body = window.document.body, + docElem = window.document.documentElement, + originalHTMLFontSize = docElem.style.fontSize, + originalBodyFontSize = body && body.style.fontSize, + fakeUsed = false; + div.style.cssText = "position:absolute;font-size:1em;width:1em"; + if( !body ){ + body = fakeUsed = doc.createElement( "body" ); + body.style.background = "none"; + } + // 1em in a media query is the value of the default font size of the browser + // reset docElem and body to ensure the correct value is returned + docElem.style.fontSize = "100%"; + body.style.fontSize = "100%"; + body.appendChild( div ); + if( fakeUsed ){ + docElem.insertBefore( body, docElem.firstChild ); + } + ret = div.offsetWidth; + if( fakeUsed ){ + docElem.removeChild( body ); + } + else { + body.removeChild( div ); + } + // restore the original values + docElem.style.fontSize = originalHTMLFontSize; + if( originalBodyFontSize ) { + body.style.fontSize = originalBodyFontSize; + } + + return ret; +}; + StylePolyfill.prototype.onStylesLoaded = function(stylesheets) { + var parsedStylesheets = this.parseForMediaQueries(stylesheets); + this.parseForShapes(parsedStylesheets); +}; + +StylePolyfill.prototype.parseForMediaQueries = function(stylesheets) { + + var cleanCss, + queries, + styleBlock = [], + styleBlockMQ = [], + queryMinWidth, + queryMaxWidth, + self = this; + stylesheets.forEach(function(stylesheet) { + + // thanks to Scott Jehl regexp he wrote for Respond.js (https://github.com/scottjehl/Respond) + cleanCss = stylesheet.cssText.replace( /\/\*[^*]*\*+([^/][^*]*\*+)*\//gi , '' ); // comments + queries = cleanCss.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ); // queries + + if(queries) { + queries.forEach(function(query) { + cleanCss = cleanCss.split(query).join(""); + queryMinWidth = query.match( /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ); + queryMaxWidth = query.match( /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)(px|em)\s*\)/ ); + styleBlockMQ.push({ + cssText : query.match( /@media *([^\{]+)\{([\S\s]+?)$/ )[2], + minWidth : queryMinWidth ? queryMinWidth[2] === "em" ? queryMinWidth[1]*self.eminpx : queryMinWidth[1] : null, + maxWidth : queryMaxWidth ? queryMaxWidth[2] === "em" ? queryMaxWidth[1]*self.eminpx : queryMaxWidth[1] : null + }); + }); + } + + styleBlock.push({ + cssText: cleanCss, + minWidth: null, + maxWidth : null + }); + + }); + + return styleBlock.concat(styleBlockMQ); + +}; + +StylePolyfill.prototype.parseForShapes = function(stylesheets) { // use : and ; as delimiters, except between () // this will be sufficient for most, but not all cases, eg: rectangle(calc(100%)) - var selector = "\\s*([^{}]*[^\\s])\\s*{[^\\}]*"; - var value = "\\s*:\\s*((?:[^;\\(]|\\([^\\)]*\\))*)\\s*;"; + var selector = "\\s*([^{}]*[^\\s])\\s*{[^\\}]*", + value = "\\s*:\\s*((?:[^;\\(]|\\([^\\)]*\\))*)\\s*;", + re, + match, + rules = [], + properties = ["shape-outside", "shape-margin", "shape-image-threshold"], + _this = this; - var re, match; - - var rules = [], properties = ["shape-outside", "shape-margin", "shape-image-threshold"]; properties.forEach(function(property) { re = new RegExp(selector + "(" + property + ")" + value, "ig"); stylesheets.forEach(function(stylesheet) { @@ -166,11 +258,15 @@ StylePolyfill.prototype.onStylesLoaded = function(stylesheets) { rules.push({ selector: match[1], property: match[2], - value: match[3] + value: match[3], + minWidth: stylesheet.minWidth, + maxWidth: stylesheet.maxWidth }); + } }); }); this.callback(rules); + }; diff --git a/tests/shape-info-tests.js b/tests/shape-info-tests.js index 669073b..6944262 100644 --- a/tests/shape-info-tests.js +++ b/tests/shape-info-tests.js @@ -647,8 +647,9 @@ function register(mocha, expect) { for (prop in test.styles) el.style[prop] = test.styles[prop]; el.setAttribute('data-shape-outside', test.shapeOutside); - if (test.shapeMargin) - el.setAttribute('data-shape-margin', test.shapeMargin); + el.setAttribute('data-shape-size-mediaqueries', test.shapeMediaQueries ? test.shapeMediaQueries : '(null,null)'); + el.setAttribute('data-shape-margin', test.shapeMargin ? test.shapeMargin : 'null'); + el.setAttribute('data-shape-image-threshold', test.shapeImageThreshold ? test.shapeImageThreshold : 'null'); document.body.appendChild(el); var shapeInfo = new ShapeInfo(el); @@ -715,8 +716,9 @@ function register(mocha, expect) { for (prop in test.styles) el.style[prop] = test.styles[prop]; el.setAttribute('data-shape-outside', test.shapeOutside); - if (test.shapeMargin) - el.setAttribute('data-shape-margin', test.shapeMargin); + el.setAttribute('data-shape-size-mediaqueries', test.shapeMediaQueries ? test.shapeMediaQueries : '(null,null)'); + el.setAttribute('data-shape-margin', test.shapeMargin ? test.shapeMargin : 'null'); + el.setAttribute('data-shape-image-threshold', test.shapeImageThreshold ? test.shapeImageThreshold : 'null'); document.body.appendChild(el); var shapeInfo = new ShapeInfo(el);