@@ -1029,7 +1029,7 @@ function h2cRenderContext(width, height) {
10291029 }
10301030 } ;
10311031}
1032- _html2canvas . Parse = function ( images , options ) {
1032+ _html2canvas . Parse = function ( images , options , cb ) {
10331033 window . scroll ( 0 , 0 ) ;
10341034
10351035 var element = ( ( options . elements === undefined ) ? document . body : options . elements [ 0 ] ) , // select body by default
@@ -1050,6 +1050,28 @@ _html2canvas.Parse = function (images, options) {
10501050
10511051 images = images || { } ;
10521052
1053+ function init ( ) {
1054+ var background = getCSS ( document . documentElement , "backgroundColor" ) ,
1055+ transparentBackground = ( Util . isTransparent ( background ) && element === document . body ) ,
1056+ stack = renderElement ( element , null , false , transparentBackground ) ;
1057+
1058+ parseChildren ( element , stack , null , function ( ) {
1059+ if ( transparentBackground ) {
1060+ background = stack . backgroundColor ;
1061+ }
1062+
1063+ Util . log ( 'Done parsing, moving to Render.' ) ;
1064+
1065+ body . removeChild ( hidePseudoElements ) ;
1066+ cb ( {
1067+ backgroundColor : background ,
1068+ stack : stack
1069+ } ) ;
1070+ } ) ;
1071+ }
1072+
1073+ init ( ) ;
1074+
10531075 function documentWidth ( ) {
10541076 return Math . max (
10551077 Math . max ( doc . body . scrollWidth , doc . documentElement . scrollWidth ) ,
@@ -1367,6 +1389,13 @@ _html2canvas.Parse = function (images, options) {
13671389 }
13681390 }
13691391
1392+ function h2czContext ( zindex ) {
1393+ return {
1394+ zindex : zindex ,
1395+ children : [ ]
1396+ } ;
1397+ }
1398+
13701399 function renderImage ( ctx , element , image , bounds , borders ) {
13711400
13721401 var paddingLeft = getCSSInt ( element , 'paddingLeft' ) ,
@@ -1403,69 +1432,67 @@ _html2canvas.Parse = function (images, options) {
14031432 } ) ;
14041433 }
14051434
1406- var getCurvePoints = ( function ( kappa ) {
1407-
1408- return function ( x , y , r1 , r2 ) {
1409- var ox = ( r1 ) * kappa , // control point offset horizontal
1410- oy = ( r2 ) * kappa , // control point offset vertical
1411- xm = x + r1 , // x-middle
1412- ym = y + r2 ; // y-middle
1413- return {
1414- topLeft : bezierCurve ( {
1415- x :x ,
1416- y :ym
1417- } , {
1418- x :x ,
1419- y :ym - oy
1420- } , {
1421- x :xm - ox ,
1422- y :y
1423- } , {
1424- x :xm ,
1425- y :y
1426- } ) ,
1427- topRight : bezierCurve ( {
1428- x :x ,
1429- y :y
1430- } , {
1431- x :x + ox ,
1432- y :y
1433- } , {
1434- x :xm ,
1435- y :ym - oy
1436- } , {
1437- x :xm ,
1438- y :ym
1439- } ) ,
1440- bottomRight : bezierCurve ( {
1441- x :xm ,
1442- y :y
1443- } , {
1444- x :xm ,
1445- y :y + oy
1446- } , {
1447- x :x + ox ,
1448- y :ym
1449- } , {
1450- x :x ,
1451- y :ym
1452- } ) ,
1453- bottomLeft : bezierCurve ( {
1454- x :xm ,
1455- y :ym
1456- } , {
1457- x :xm - ox ,
1458- y :ym
1459- } , {
1460- x :x ,
1461- y :y + oy
1462- } , {
1463- x :x ,
1464- y :y
1465- } )
1466- } ;
1435+ function getCurvePoints ( x , y , r1 , r2 ) {
1436+ var kappa = 4 * ( ( Math . sqrt ( 2 ) - 1 ) / 3 ) ;
1437+ var ox = ( r1 ) * kappa , // control point offset horizontal
1438+ oy = ( r2 ) * kappa , // control point offset vertical
1439+ xm = x + r1 , // x-middle
1440+ ym = y + r2 ; // y-middle
1441+ return {
1442+ topLeft : bezierCurve ( {
1443+ x :x ,
1444+ y :ym
1445+ } , {
1446+ x :x ,
1447+ y :ym - oy
1448+ } , {
1449+ x :xm - ox ,
1450+ y :y
1451+ } , {
1452+ x :xm ,
1453+ y :y
1454+ } ) ,
1455+ topRight : bezierCurve ( {
1456+ x :x ,
1457+ y :y
1458+ } , {
1459+ x :x + ox ,
1460+ y :y
1461+ } , {
1462+ x :xm ,
1463+ y :ym - oy
1464+ } , {
1465+ x :xm ,
1466+ y :ym
1467+ } ) ,
1468+ bottomRight : bezierCurve ( {
1469+ x :xm ,
1470+ y :y
1471+ } , {
1472+ x :xm ,
1473+ y :y + oy
1474+ } , {
1475+ x :x + ox ,
1476+ y :ym
1477+ } , {
1478+ x :x ,
1479+ y :ym
1480+ } ) ,
1481+ bottomLeft : bezierCurve ( {
1482+ x :xm ,
1483+ y :ym
1484+ } , {
1485+ x :xm - ox ,
1486+ y :ym
1487+ } , {
1488+ x :x ,
1489+ y :y + oy
1490+ } , {
1491+ x :x ,
1492+ y :y
1493+ } )
14671494 } ;
1468- } ) ( 4 * ( ( Math . sqrt ( 2 ) - 1 ) / 3 ) ) ;
1495+ }
14691496
14701497 function bezierCurve ( start , startControl , endControl , end ) {
14711498
@@ -1984,9 +2011,8 @@ _html2canvas.Parse = function (images, options) {
19842011 return str . replace ( "px" , "" ) ;
19852012 }
19862013
1987- var transformRegExp = / ( m a t r i x ) \( ( .+ ) \) / ;
1988-
19892014 function getTransform ( element , parentStack ) {
2015+ var transformRegExp = / ( m a t r i x ) \( ( .+ ) \) / ;
19902016 var transform = getCSS ( element , "transform" ) || getCSS ( element , "-webkit-transform" ) || getCSS ( element , "-moz-transform" ) || getCSS ( element , "-ms-transform" ) || getCSS ( element , "-o-transform" ) ;
19912017 var transformOrigin = getCSS ( element , "transform-origin" ) || getCSS ( element , "-webkit-transform-origin" ) || getCSS ( element , "-moz-transform-origin" ) || getCSS ( element , "-ms-transform-origin" ) || getCSS ( element , "-o-transform-origin" ) || "0px 0px" ;
19922018
@@ -2127,52 +2153,54 @@ _html2canvas.Parse = function (images, options) {
21272153 return ( getCSS ( element , 'display' ) !== "none" && getCSS ( element , 'visibility' ) !== "hidden" && ! element . hasAttribute ( "data-html2canvas-ignore" ) ) ;
21282154 }
21292155
2130- function parseElement ( element , stack , pseudoElement ) {
2156+ function parseElement ( element , stack , pseudoElement , cb ) {
2157+ if ( ! cb ) {
2158+ cb = function ( ) { } ;
2159+ }
21312160 if ( isElementVisible ( element ) ) {
21322161 stack = renderElement ( element , stack , pseudoElement , false ) || stack ;
21332162 if ( ! ignoreElementsRegExp . test ( element . nodeName ) ) {
2134- parseChildren ( element , stack , pseudoElement ) ;
2163+ return parseChildren ( element , stack , pseudoElement , cb ) ;
21352164 }
21362165 }
2166+ cb ( ) ;
21372167 }
21382168
2139- function parseChildren ( element , stack , pseudoElement ) {
2140- Util . Children ( element ) . forEach ( function ( node ) {
2169+ function parseChildren ( element , stack , pseudoElement , cb ) {
2170+ var children = Util . Children ( element ) ;
2171+ // After all nodes have processed, finished() will call the cb.
2172+ // We add one and kick it off so this will still work when children.length === 0.
2173+ // Note that unless async is true, this will happen synchronously, just will callbacks.
2174+ var jobs = children . length + 1 ;
2175+ finished ( ) ;
2176+
2177+ if ( options . async ) {
2178+ children . forEach ( function ( node ) {
2179+ // Don't block the page from rendering
2180+ setTimeout ( function ( ) { parseNode ( node ) ; } , 0 ) ;
2181+ } ) ;
2182+ } else {
2183+ children . forEach ( parseNode ) ;
2184+ }
2185+
2186+ function parseNode ( node ) {
21412187 if ( node . nodeType === node . ELEMENT_NODE ) {
2142- parseElement ( node , stack , pseudoElement ) ;
2188+ parseElement ( node , stack , pseudoElement , finished ) ;
21432189 } else if ( node . nodeType === node . TEXT_NODE ) {
21442190 renderText ( element , node , stack ) ;
2191+ finished ( ) ;
2192+ } else {
2193+ finished ( ) ;
2194+ }
2195+ }
2196+ function finished ( el ) {
2197+ if ( -- jobs <= 0 ) {
2198+ Util . log ( "finished rendering " + children . length + " children." ) ;
2199+ cb ( ) ;
21452200 }
2146- } ) ;
2147- }
2148-
2149- function init ( ) {
2150- var background = getCSS ( document . documentElement , "backgroundColor" ) ,
2151- transparentBackground = ( Util . isTransparent ( background ) && element === document . body ) ,
2152- stack = renderElement ( element , null , false , transparentBackground ) ;
2153- parseChildren ( element , stack ) ;
2154-
2155- if ( transparentBackground ) {
2156- background = stack . backgroundColor ;
21572201 }
2158-
2159- body . removeChild ( hidePseudoElements ) ;
2160- return {
2161- backgroundColor : background ,
2162- stack : stack
2163- } ;
21642202 }
2165-
2166- return init ( ) ;
21672203} ;
2168-
2169- function h2czContext ( zindex ) {
2170- return {
2171- zindex : zindex ,
2172- children : [ ]
2173- } ;
2174- }
2175-
21762204_html2canvas . Preload = function ( options ) {
21772205
21782206 var images = {
@@ -2697,21 +2725,19 @@ window.html2canvas = function(elements, opts) {
26972725 return ;
26982726 }
26992727 }
2700- queue = _html2canvas . Parse ( images , options ) ;
2701-
2702- if ( typeof options . onparsed === "function" ) {
2703- if ( options . onparsed ( queue ) === false ) {
2704- return ;
2728+ _html2canvas . Parse ( images , options , function ( queue ) {
2729+ if ( typeof options . onparsed === "function" ) {
2730+ if ( options . onparsed ( queue ) === false ) {
2731+ return ;
2732+ }
27052733 }
2706- }
2707-
2708- canvas = _html2canvas . Renderer ( queue , options ) ;
2709-
2710- if ( typeof options . onrendered === "function" ) {
2711- options . onrendered ( canvas ) ;
2712- }
27132734
2735+ canvas = _html2canvas . Renderer ( queue , options ) ;
27142736
2737+ if ( typeof options . onrendered === "function" ) {
2738+ options . onrendered ( canvas ) ;
2739+ }
2740+ } ) ;
27152741 } ;
27162742
27172743 // for pages without images, we still want this to be async, i.e. return methods before executing
0 commit comments