diff --git a/build.xml b/build.xml index 609988a..bd606d0 100644 --- a/build.xml +++ b/build.xml @@ -22,6 +22,7 @@ + diff --git a/build/html2canvas.js b/build/html2canvas.js index 2f3a29a..0da113a 100644 --- a/build/html2canvas.js +++ b/build/html2canvas.js @@ -45,7 +45,8 @@ function html2canvas(el, userOptions) { }, iframeDefault: "default", flashCanvasPath: "http://html2canvas.hertzen.com/external/flashcanvas/flashcanvas.js", - renderViewport: false + renderViewport: false, + reorderZ: true }); this.element = el; @@ -60,7 +61,10 @@ function html2canvas(el, userOptions) { this.images = []; this.fontData = []; this.numDraws = 0; + this.contextStacks = []; this.ignoreElements = "IFRAME|OBJECT|PARAM"; + this.needReorder = false; + this.blockElements = new RegExp("(BR|PARAM)"); this.ignoreRe = new RegExp("("+this.ignoreElements+")"); @@ -88,43 +92,15 @@ html2canvas.prototype.init = function(){ var _ = this; - this.canvas = document.createElement('canvas'); - - // TODO remove jQuery dependency - this.canvas.width = $(document).width(); - this.canvas.height = $(document).height(); - - - - - if (!this.canvas.getContext){ - - // TODO include Flashcanvas - /* - var script = document.createElement('script'); - script.type = "text/javascript"; - script.src = this.opts.flashCanvasPath; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(script, s); - - if (typeof FlashCanvas != "undefined") { - - FlashCanvas.initElement(this.canvas); - this.ctx = this.canvas.getContext('2d'); - } */ - - }else{ - this.ctx = this.canvas.getContext('2d'); - } - + this.ctx = new this.stackingContext($(document).width(),$(document).height()); + if (!this.ctx){ // canvas not initialized, let's kill it here this.log('Canvas not available'); return; } - // set common settings for canvas - this.ctx.textBaseline = "bottom"; + this.canvas = this.ctx.canvas; this.log('Finding background images'); @@ -153,17 +129,92 @@ html2canvas.prototype.start = function(){ this.log('Started parsing'); this.bodyOverflow = document.getElementsByTagName('body')[0].style.overflow; document.getElementsByTagName('body')[0].style.overflow = "hidden"; - this.newElement(this.element); + + var ctx = this.newElement(this.element, this.ctx) || this.ctx; - this.parseElement(this.element); + this.parseElement(this.element,ctx); + } } +html2canvas.prototype.stackingContext = function(width,height){ + this.canvas = document.createElement('canvas'); + + // TODO remove jQuery dependency + this.canvas.width = $(document).width(); + this.canvas.height = $(document).height(); + + if (!this.canvas.getContext){ + + // TODO include Flashcanvas + /* + var script = document.createElement('script'); + script.type = "text/javascript"; + script.src = this.opts.flashCanvasPath; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(script, s); + + if (typeof FlashCanvas != "undefined") { + + FlashCanvas.initElement(this.canvas); + this.ctx = this.canvas.getContext('2d'); + } */ + + }else{ + this.ctx = this.canvas.getContext('2d'); + } + + // set common settings for canvas + this.ctx.textBaseline = "bottom"; + + return this.ctx; + +} + +html2canvas.prototype.storageContext = function(width,height){ + this.storage = []; + + + + // todo simplify this whole section + this.fillRect = function(x, y, w, h){ + this.storage.push( + { + type: "function", + name:"fillRect", + arguments:[x,y,w,h] + }); + + }; + + this.drawImage = function(image,sx,sy,sw,sh,dx,dy,dw,dh){ + this.storage.push( + { + type: "function", + name:"drawImage", + arguments:[image,sx,sy,sw,sh,dx,dy,dw,dh] + }); + }; + + this.fillText = function(currentText,x,y){ + + this.storage.push( + { + type: "function", + name:"fillText", + arguments:[currentText,x,y] + }); + } + + return this; + +} + /* - * Finished rendering, send callback - */ +* Finished rendering, send callback +*/ html2canvas.prototype.finish = function(){ this.log("Finished rendering"); @@ -183,7 +234,7 @@ html2canvas.prototype.finish = function(){ -html2canvas.prototype.drawBackground = function(el,bounds){ +html2canvas.prototype.drawBackground = function(el,bounds,ctx){ var background_image = this.getCSS(el,"background-image"); @@ -203,16 +254,16 @@ html2canvas.prototype.drawBackground = function(el,bounds){ switch(background_repeat){ case "repeat-x": - this.drawbackgroundRepeatX(image,bgp,bounds.left,bounds.top,bounds.width,bounds.height); + this.drawbackgroundRepeatX(ctx,image,bgp,bounds.left,bounds.top,bounds.width,bounds.height); break; case "repeat-y": - this.drawbackgroundRepeatY(image,bgp,bounds.left,bounds.top,bounds.width,bounds.height); + this.drawbackgroundRepeatY(ctx,image,bgp,bounds.left,bounds.top,bounds.width,bounds.height); break; case "no-repeat": - this.drawBackgroundRepeat(image,bgp.left+bounds.left,bgp.top+bounds.top,Math.min(bounds.width,image.width),Math.min(bounds.height,image.height),bounds.left,bounds.top); + this.drawBackgroundRepeat(ctx,image,bgp.left+bounds.left,bgp.top+bounds.top,Math.min(bounds.width,image.width),Math.min(bounds.height,image.height),bounds.left,bounds.top); // ctx.drawImage(image,(bounds.left+bgp.left),(bounds.top+bgp.top)); break; @@ -246,7 +297,7 @@ html2canvas.prototype.drawBackground = function(el,bounds){ add = 0; } - this.drawbackgroundRepeatX(image,bgp,bounds.left,bgy,bounds.width,height); + this.drawbackgroundRepeatX(ctx,image,bgp,bounds.left,bgy,bounds.width,height); if (add>0){ bgp.top += add; } @@ -329,7 +380,7 @@ html2canvas.prototype.getBackgroundPosition = function(el,bounds,image){ -html2canvas.prototype.drawbackgroundRepeatY = function(image,bgp,x,y,w,h){ +html2canvas.prototype.drawbackgroundRepeatY = function(ctx,image,bgp,x,y,w,h){ var height, width = Math.min(image.width,w),bgy; @@ -345,14 +396,14 @@ html2canvas.prototype.drawbackgroundRepeatY = function(image,bgp,x,y,w,h){ }else{ height = image.height; } - this.drawBackgroundRepeat(image,x+bgp.left,bgy,width,height,x,y); + this.drawBackgroundRepeat(ctx,image,x+bgp.left,bgy,width,height,x,y); bgy = Math.floor(bgy+image.height); } } -html2canvas.prototype.drawbackgroundRepeatX = function(image,bgp,x,y,w,h){ +html2canvas.prototype.drawbackgroundRepeatX = function(ctx,image,bgp,x,y,w,h){ var height = Math.min(image.height,h), width,bgx; @@ -369,7 +420,7 @@ html2canvas.prototype.drawbackgroundRepeatX = function(image,bgp,x,y,w,h){ width = image.width; } - this.drawBackgroundRepeat(image,bgx,(y+bgp.top),width,height,x,y); + this.drawBackgroundRepeat(ctx,image,bgx,(y+bgp.top),width,height,x,y); bgx = Math.floor(bgx+image.width); @@ -377,7 +428,7 @@ html2canvas.prototype.drawbackgroundRepeatX = function(image,bgp,x,y,w,h){ } } -html2canvas.prototype.drawBackgroundRepeat = function(image,x,y,width,height,elx,ely){ +html2canvas.prototype.drawBackgroundRepeat = function(ctx,image,x,y,width,height,elx,ely){ var sourceX = 0, sourceY=0; if (elx-x>0){ @@ -388,7 +439,8 @@ html2canvas.prototype.drawBackgroundRepeat = function(image,x,y,width,height,elx sourceY = ely-y; } - this.ctx.drawImage( + this.drawImage( + ctx, image, sourceX, // source X sourceY, // source Y @@ -399,7 +451,6 @@ html2canvas.prototype.drawBackgroundRepeat = function(image,x,y,width,height,elx width-sourceX, // destination width height-sourceY // destination height ); - this.numDraws++; } /* * Function to provide border details for an element @@ -423,7 +474,7 @@ html2canvas.prototype.getBorderData = function(el){ -html2canvas.prototype.newElement = function(el){ +html2canvas.prototype.newElement = function(el,parentStack){ var bounds = this.getBounds(el); @@ -435,14 +486,40 @@ html2canvas.prototype.newElement = function(el){ image; var bgcolor = this.getCSS(el,"background-color"); + var zindex = this.formatZ(this.getCSS(el,"z-index"),this.getCSS(el,"position"),parentStack.zIndex,el.parentNode); + + //console.log(el.nodeName+":"+zindex+":"+this.getCSS(el,"position")+":"+this.numDraws+":"+this.getCSS(el,"z-index")) + + var opacity = this.getCSS(el,"opacity"); + + //if (this.getCSS(el,"position")!="static"){ + + /* + this.contextStacks.push(ctx); + + ctx = new this.storageContext(); + */ + + + + var stack = { + ctx: new this.storageContext(), + zIndex: zindex, + opacity: opacity + }; + + var stackLength = this.contextStacks.push(stack); + + var ctx = this.contextStacks[stackLength-1].ctx; + //} /* * TODO add support for different border-style's than solid */ var borders = this.getBorderData(el); - + this.each(borders,function(borderSide,borderData){ if (borderData.width>0){ var bx = x, @@ -470,7 +547,7 @@ html2canvas.prototype.newElement = function(el){ break; } - _.newRect(bx,by,bw,bh,borderData.color); + _.newRect(ctx,bx,by,bw,bh,borderData.color); @@ -483,7 +560,7 @@ html2canvas.prototype.newElement = function(el){ if (this.ignoreRe.test(el.nodeName) && this.opts.iframeDefault != "transparent"){ if (this.opts.iframeDefault=="default"){ bgcolor = "#efefef"; - /* + /* * TODO write X over frame */ }else{ @@ -493,6 +570,7 @@ html2canvas.prototype.newElement = function(el){ // draw base element bgcolor this.newRect( + ctx, x+borders[3].width, y+borders[0].width, w-(borders[1].width+borders[3].width), @@ -505,13 +583,15 @@ html2canvas.prototype.newElement = function(el){ top: y+borders[0].width, width: w-(borders[1].width+borders[3].width), height: h-(borders[0].width+borders[2].width) - }); + } + ,ctx); if (el.nodeName=="IMG"){ image = _.loadImage(_.getAttr(el,'src')); if (image){ - this.ctx.drawImage( + this.drawImage( + ctx, image, 0, //sx 0, //sy @@ -520,15 +600,18 @@ html2canvas.prototype.newElement = function(el){ x+parseInt(_.getCSS(el,'padding-left'),10) + borders[3].width, //dx y+parseInt(_.getCSS(el,'padding-top'),10) + borders[0].width, // dy bounds.width - (borders[1].width + borders[3].width + parseInt(_.getCSS(el,'padding-left'),10) + parseInt(_.getCSS(el,'padding-right'),10)), //dw - bounds.height - (borders[0].width + borders[2].width + parseInt(_.getCSS(el,'padding-top'),10) + parseInt(_.getCSS(el,'padding-bottom'),10)) //dh - + bounds.height - (borders[0].width + borders[2].width + parseInt(_.getCSS(el,'padding-top'),10) + parseInt(_.getCSS(el,'padding-bottom'),10)) //dh ); - this.numDraws++; + }else{ this.log("Error loading :" + _.getAttr(el,'src')); } } - + + + + return this.contextStacks[stackLength-1]; + } @@ -542,23 +625,40 @@ html2canvas.prototype.newElement = function(el){ * Function to draw the text on the canvas */ -html2canvas.prototype.printText = function(currentText,x,y){ +html2canvas.prototype.printText = function(currentText,x,y,ctx){ if (this.trim(currentText).length>0){ - this.ctx.fillText(currentText,x,y); + + ctx.fillText(currentText,x,y); this.numDraws++; } } // Drawing a rectangle -html2canvas.prototype.newRect = function(x,y,w,h,bgcolor){ +html2canvas.prototype.newRect = function(ctx,x,y,w,h,bgcolor){ if (bgcolor!="transparent"){ - this.ctx.fillStyle = bgcolor; - this.ctx.fillRect (x, y, w, h); + this.setContextVariable(ctx,"fillStyle",bgcolor); + ctx.fillRect (x, y, w, h); this.numDraws++; } } + +html2canvas.prototype.drawImage = function(ctx,image,sx,sy,sw,sh,dx,dy,dw,dh){ + ctx.drawImage( + image, + sx, //sx + sy, //sy + sw, //sw + sh, //sh + dx, //dx + dy, // dy + dw, //dw + dh //dh + ); + this.numDraws++; + +} /* * Function to find all images from and background-image */ @@ -629,8 +729,127 @@ html2canvas.prototype.preloadImage = function(src){ } + + +html2canvas.prototype.canvasRenderer = function(queue){ + var _ = this; + + queue = this.sortQueue(queue); + + this.each(queue,function(i,storageContext){ + + if (storageContext.ctx.storage){ + _.each(storageContext.ctx.storage,function(a,renderItem){ + + switch(renderItem.type){ + case "variable": + _.ctx[renderItem.name] = renderItem.arguments; + break; + case "function": + if (renderItem.name=="fillRect"){ + _.ctx.fillRect(renderItem.arguments[0],renderItem.arguments[1],renderItem.arguments[2],renderItem.arguments[3]); + }else if(renderItem.name=="fillText"){ + _.ctx.fillText(renderItem.arguments[0],renderItem.arguments[1],renderItem.arguments[2]); + }else if(renderItem.name=="drawImage"){ + _.ctx.drawImage( + renderItem.arguments[0], + renderItem.arguments[1], + renderItem.arguments[2], + renderItem.arguments[3], + renderItem.arguments[4], + renderItem.arguments[5], + renderItem.arguments[6], + renderItem.arguments[7], + renderItem.arguments[8] + ); + }else{ + this.log(renderItem); + } + + + break; + default: + + } + + + }); + + } + + }); + + +}; + +/* + * Sort elements based on z-index and position attributes + */ + + +html2canvas.prototype.sortQueue = function(queue){ + if (!this.opts.reorderZ || !this.needReorder) return queue; + + var longest = 0; + this.each(queue,function(i,e){ + if (longeste.zIndex.length){ + e.zIndex += "0"; + } + e.zIndex = e.zIndex+counter; + + while((longest+more+(counter).toString().length)>e.zIndex.length){ + e.zIndex += "0"; + } + counter++; + // console.log(e.zIndex); + }); + + + + queue = queue.sort(function(a,b){ + + if (a.zIndex < b.zIndex) return -1; + if (a.zIndex > b.zIndex) return 1; + return 0; + }); + + + /* + + console.log('after'); + this.each(queue,function(i,e){ + console.log(i+":"+e.zIndex); + // console.log(e.ctx.storage); + }); */ + + return queue; +} + +html2canvas.prototype.setContextVariable = function(ctx,variable,value){ + if (!ctx.storage){ + ctx[variable] = value; + }else{ + ctx.storage.push( + { + type: "variable", + name:variable, + arguments:value + }); + } + +} -html2canvas.prototype.newText = function(el,textNode){ +html2canvas.prototype.newText = function(el,textNode,ctx){ var family = this.getCSS(el,"font-family"); var size = this.getCSS(el,"font-size"); @@ -662,9 +881,10 @@ html2canvas.prototype.newText = function(el,textNode){ } - - this.ctx.font = bold+" "+font_style+" "+size+" "+family; - this.ctx.fillStyle = color; + this.setContextVariable(ctx,"fillStyle",color); + this.setContextVariable(ctx,"font",bold+" "+font_style+" "+size+" "+family); + //ctx.font = bold+" "+font_style+" "+size+" "+family; + //ctx.fillStyle = color; var oldTextNode = textNode; for(var c=0;ce+c?e+c-c:d.height,c0&&(i.top+=f),c=Math.floor(c+d.height)-f}else this.log("Error loading background:"+c)}}; +html2canvas.prototype.drawBackground=function(a,b,c){var d=this.getCSS(a,"background-image"),e=this.getCSS(a,"background-repeat");if(typeof d!="undefined"&&/^(1|none)$/.test(d)==!1){var d=this.backgroundImageUrl(d),g=this.loadImage(d),a=this.getBackgroundPosition(a,b,g);if(g)switch(e){case "repeat-x":this.drawbackgroundRepeatX(c,g,a,b.left,b.top,b.width,b.height);break;case "repeat-y":this.drawbackgroundRepeatY(c,g,a,b.left,b.top,b.width,b.height);break;case "no-repeat":this.drawBackgroundRepeat(c, +g,a.left+b.left,a.top+b.top,Math.min(b.width,g.width),Math.min(b.height,g.height),b.left,b.top);break;default:var f;a.top-=Math.ceil(a.top/g.height)*g.height;for(d=b.top+a.top;de+d?e+d-d:g.height,d0&&(a.top+=f),d=Math.floor(d+g.height)-f}else this.log("Error loading background:"+d)}}; html2canvas.prototype.backgroundImageUrl=function(a){a.substr(0,5)=='url("'?(a=a.substr(5),a=a.substr(0,a.length-2)):(a=a.substr(4),a=a.substr(0,a.length-1));return a}; -html2canvas.prototype.getBackgroundPosition=function(a,b,c){var a=this.getCSS(a,"background-position").split(" "),e,d;a.length==1&&(e=a,a=[],a[0]=e,a[1]=e);a[0].toString().indexOf("%")!=-1?(d=parseFloat(a[0])/100,e=b.width*d-c.width*d):e=parseInt(a[0],10);a[1].toString().indexOf("%")!=-1?(d=parseFloat(a[1])/100,b=b.height*d-c.height*d):b=parseInt(a[1],10);return{top:b,left:e}}; -html2canvas.prototype.drawbackgroundRepeatY=function(a,b,c,e,d,i){var f=Math.min(a.width,d),g;b.top-=Math.ceil(b.top/a.height)*a.height;for(g=e+b.top;gi+e?i+e-g:a.height,this.drawBackgroundRepeat(a,c+b.left,g,f,d,c,e),g=Math.floor(g+a.height)}; -html2canvas.prototype.drawbackgroundRepeatX=function(a,b,c,e,d,i){var i=Math.min(a.height,i),f,g;b.left-=Math.ceil(b.left/a.width)*a.width;for(g=c+b.left;gd+c?d+c-g:a.width,this.drawBackgroundRepeat(a,g,e+b.top,f,i,c,e),g=Math.floor(g+a.width)};html2canvas.prototype.drawBackgroundRepeat=function(a,b,c,e,d,i,f){var g=0,h=0;i-b>0&&(g=i-b);f-c>0&&(h=f-c);this.ctx.drawImage(a,g,h,e-g,d-h,b+g,c+h,e-g,d-h);this.numDraws++}; -html2canvas.prototype.getBorderData=function(a){var b=[],c=this;this.each(["top","right","bottom","left"],function(e,d){b.push({width:parseInt(c.getCSS(a,"border-"+d+"-width"),10),color:c.getCSS(a,"border-"+d+"-color")})});return b}; -html2canvas.prototype.newElement=function(a){var b=this.getBounds(a),c=b.left,e=b.top,d=b.width,i=b.height,f=this,g;g=this.getCSS(a,"background-color");var h=this.getBorderData(a);this.each(h,function(a,b){if(b.width>0){var g=c,j=e,m=d,n=i-h[2].width;switch(a){case 0:n=h[0].width;break;case 1:g=c+d-h[1].width;m=h[1].width;break;case 2:j=j+i-h[2].width;n=h[2].width;break;case 3:m=h[3].width}f.newRect(g,j,m,n,b.color)}});this.ignoreRe.test(a.nodeName)&&this.opts.iframeDefault!="transparent"&&(g=this.opts.iframeDefault== -"default"?"#efefef":this.opts.iframeDefault);this.newRect(c+h[3].width,e+h[0].width,d-(h[1].width+h[3].width),i-(h[0].width+h[2].width),g);this.drawBackground(a,{left:c+h[3].width,top:e+h[0].width,width:d-(h[1].width+h[3].width),height:i-(h[0].width+h[2].width)});a.nodeName=="IMG"&&((g=f.loadImage(f.getAttr(a,"src")))?(this.ctx.drawImage(g,0,0,g.width,g.height,c+parseInt(f.getCSS(a,"padding-left"),10)+h[3].width,e+parseInt(f.getCSS(a,"padding-top"),10)+h[0].width,b.width-(h[1].width+h[3].width+parseInt(f.getCSS(a, -"padding-left"),10)+parseInt(f.getCSS(a,"padding-right"),10)),b.height-(h[0].width+h[2].width+parseInt(f.getCSS(a,"padding-top"),10)+parseInt(f.getCSS(a,"padding-bottom"),10))),this.numDraws++):this.log("Error loading :"+f.getAttr(a,"src")))};html2canvas.prototype.printText=function(a,b,c){this.trim(a).length>0&&(this.ctx.fillText(a,b,c),this.numDraws++)};html2canvas.prototype.newRect=function(a,b,c,e,d){if(d!="transparent")this.ctx.fillStyle=d,this.ctx.fillRect(a,b,c,e),this.numDraws++}; -html2canvas.prototype.getImages=function(a){var b=this;this.ignoreRe.test(a.nodeName)||this.each($(a).contents(),function(a,e){RegExp("("+this.ignoreElements+")").test(e.nodeName)||b.getImages(e)});if(a.nodeType==1||typeof a.nodeType=="undefined")(a=this.getCSS(a,"background-image"))&&a!="1"&&a!="none"&&a.substring(0,7)!="-webkit"&&a.substring(0,4)!="-moz"&&this.preloadImage(this.backgroundImageUrl(a))}; +html2canvas.prototype.getBackgroundPosition=function(a,b,c){var a=this.getCSS(a,"background-position").split(" "),d,e;a.length==1&&(d=a,a=[],a[0]=d,a[1]=d);a[0].toString().indexOf("%")!=-1?(e=parseFloat(a[0])/100,d=b.width*e-c.width*e):d=parseInt(a[0],10);a[1].toString().indexOf("%")!=-1?(e=parseFloat(a[1])/100,b=b.height*e-c.height*e):b=parseInt(a[1],10);return{top:b,left:d}}; +html2canvas.prototype.drawbackgroundRepeatY=function(a,b,c,d,e,g,f){var i=Math.min(b.width,g),h;c.top-=Math.ceil(c.top/b.height)*b.height;for(h=e+c.top;hf+e?f+e-h:b.height,this.drawBackgroundRepeat(a,b,d+c.left,h,i,g,d,e),h=Math.floor(h+b.height)}; +html2canvas.prototype.drawbackgroundRepeatX=function(a,b,c,d,e,g,f){var f=Math.min(b.height,f),i,h;c.left-=Math.ceil(c.left/b.width)*b.width;for(h=d+c.left;hg+d?g+d-h:b.width,this.drawBackgroundRepeat(a,b,h,e+c.top,i,f,d,e),h=Math.floor(h+b.width)};html2canvas.prototype.drawBackgroundRepeat=function(a,b,c,d,e,g,f,i){var h=0,k=0;f-c>0&&(h=f-c);i-d>0&&(k=i-d);this.drawImage(a,b,h,k,e-h,g-k,c+h,d+k,e-h,g-k)}; +html2canvas.prototype.getBorderData=function(a){var b=[],c=this;this.each(["top","right","bottom","left"],function(d,e){b.push({width:parseInt(c.getCSS(a,"border-"+e+"-width"),10),color:c.getCSS(a,"border-"+e+"-color")})});return b}; +html2canvas.prototype.newElement=function(a,b){var c=this.getBounds(a),d=c.left,e=c.top,g=c.width,f=c.height,i=this,h;h=this.getCSS(a,"background-color");var k=this.formatZ(this.getCSS(a,"z-index"),this.getCSS(a,"position"),b.zIndex,a.parentNode),l=this.getCSS(a,"opacity"),k=this.contextStacks.push({ctx:new this.storageContext,zIndex:k,opacity:l}),m=this.contextStacks[k-1].ctx,j=this.getBorderData(a);this.each(j,function(a,b){if(b.width>0){var c=d,h=e,k=g,l=f-j[2].width;switch(a){case 0:l=j[0].width; +break;case 1:c=d+g-j[1].width;k=j[1].width;break;case 2:h=h+f-j[2].width;l=j[2].width;break;case 3:k=j[3].width}i.newRect(m,c,h,k,l,b.color)}});this.ignoreRe.test(a.nodeName)&&this.opts.iframeDefault!="transparent"&&(h=this.opts.iframeDefault=="default"?"#efefef":this.opts.iframeDefault);this.newRect(m,d+j[3].width,e+j[0].width,g-(j[1].width+j[3].width),f-(j[0].width+j[2].width),h);this.drawBackground(a,{left:d+j[3].width,top:e+j[0].width,width:g-(j[1].width+j[3].width),height:f-(j[0].width+j[2].width)}, +m);a.nodeName=="IMG"&&((h=i.loadImage(i.getAttr(a,"src")))?this.drawImage(m,h,0,0,h.width,h.height,d+parseInt(i.getCSS(a,"padding-left"),10)+j[3].width,e+parseInt(i.getCSS(a,"padding-top"),10)+j[0].width,c.width-(j[1].width+j[3].width+parseInt(i.getCSS(a,"padding-left"),10)+parseInt(i.getCSS(a,"padding-right"),10)),c.height-(j[0].width+j[2].width+parseInt(i.getCSS(a,"padding-top"),10)+parseInt(i.getCSS(a,"padding-bottom"),10))):this.log("Error loading :"+i.getAttr(a,"src")));return this.contextStacks[k- +1]};html2canvas.prototype.printText=function(a,b,c,d){this.trim(a).length>0&&(d.fillText(a,b,c),this.numDraws++)};html2canvas.prototype.newRect=function(a,b,c,d,e,g){g!="transparent"&&(this.setContextVariable(a,"fillStyle",g),a.fillRect(b,c,d,e),this.numDraws++)};html2canvas.prototype.drawImage=function(a,b,c,d,e,g,f,i,h,k){a.drawImage(b,c,d,e,g,f,i,h,k);this.numDraws++}; +html2canvas.prototype.getImages=function(a){var b=this;this.ignoreRe.test(a.nodeName)||this.each($(a).contents(),function(a,d){RegExp("("+this.ignoreElements+")").test(d.nodeName)||b.getImages(d)});if(a.nodeType==1||typeof a.nodeType=="undefined")(a=this.getCSS(a,"background-image"))&&a!="1"&&a!="none"&&a.substring(0,7)!="-webkit"&&a.substring(0,4)!="-moz"&&this.preloadImage(this.backgroundImageUrl(a))}; html2canvas.prototype.loadImage=function(a){a=this.images.indexOf(a);return a!=-1?this.images[a+1]:!1};html2canvas.prototype.preloadImage=function(a){if(this.images.indexOf(a)==-1){this.images.push(a);var b=new Image,c=this;$(b).load(function(){c.imagesLoaded++;c.start()});b.onerror=function(){c.images.splice(c.images.indexOf(b.src),2);c.imagesLoaded++;c.start()};b.src=a;this.images.push(b)}}; -html2canvas.prototype.newText=function(a,b){var c=this.getCSS(a,"font-family"),e=this.getCSS(a,"font-size"),d=this.getCSS(a,"color"),i=this.getCSS(a,"font-weight"),f=this.getCSS(a,"font-style"),g=this.getCSS(a,"text-decoration");b.nodeValue=this.textTransform(b.nodeValue,this.getCSS(a,"text-transform"));var h=b.nodeValue;if(h.length>0){switch(i){case "401":i="bold"}if(g!="none")var k=this.fontMetrics(c,e);this.ctx.font=i+" "+f+" "+e+" "+c;this.ctx.fillStyle=d;c=b;for(e=0;e-1)return this.fontData[c+1];c=document.createElement("div");document.getElementsByTagName("body")[0].appendChild(c);$(c).css({visibility:"hidden",fontFamily:a,fontSize:b,margin:0,padding:0});var e=document.createElement("img");e.src="http://html2canvas.hertzen.com/images/8.jpg";e.width=1;e.height=1;$(e).css({margin:0,padding:0});var d=document.createElement("span");$(d).css({fontFamily:a,fontSize:b,margin:0, -padding:0});d.appendChild(document.createTextNode("Hidden Text"));c.appendChild(d);c.appendChild(e);var i=e.offsetTop-d.offsetTop+1;c.removeChild(d);c.appendChild(document.createTextNode("Hidden Text"));$(c).css("line-height","normal");$(e).css("vertical-align","super");e={baseline:i,lineWidth:1,middle:e.offsetTop-c.offsetTop+1};this.fontData.push(a+"-"+b);this.fontData.push(e);$(c).remove();return e}; -html2canvas.prototype.textTransform=function(a,b){switch(b){case "lowercase":return a.toLowerCase();case "capitalize":return a.replace(/(^|\s|:|-|\(|\))([a-z])/g,function(a,b,d){return b+d.toUpperCase()});case "uppercase":return a.toUpperCase();default:return a}};html2canvas.prototype.trim=function(a){return a.replace(/^\s*/,"").replace(/\s*$/,"")};html2canvas.prototype.parseElement=function(a){var b=this;this.each(a.children,function(a,e){b.parsing(e)});this.finish()}; -html2canvas.prototype.parsing=function(a){var b=this;this.newElement(a);if(!this.ignoreRe.test(a.nodeName)){var c=$(a).contents();c.length==1?c[0].nodeType==1?this.parsing(c[0]):c[0].nodeType==3&&this.newText(a,c[0]):this.each(c,function(c,d){d.nodeType==1?b.parsing(d):d.nodeType==3&&b.newText(a,d)})}};html2canvas.prototype.log=function(){}; -html2canvas.prototype.getBounds=function(a){window.scroll(0,0);if(a.getBoundingClientRect)return a=a.getBoundingClientRect(),a.top=a.top,a.left=a.left,a;else{var b=$(a).offset();return{left:b.left+parseInt(this.getCSS(a,"border-left-width"),10),top:b.top+parseInt(this.getCSS(a,"border-top-width"),10),width:$(a).innerWidth(),height:$(a).innerHeight()}}};html2canvas.prototype.each=function(a,b){for(var b=b||function(){},c=0;ce.zIndex.length;)e.zIndex+="0";for(e.zIndex+=c;b+g+c.toString().length>e.zIndex.length;)e.zIndex+="0";c++});return a=a.sort(function(a,b){return a.zIndexb.zIndex?1:0})}; +html2canvas.prototype.setContextVariable=function(a,b,c){a.storage?a.storage.push({type:"variable",name:b,arguments:c}):a[b]=c}; +html2canvas.prototype.newText=function(a,b,c){var d=this.getCSS(a,"font-family"),e=this.getCSS(a,"font-size"),g=this.getCSS(a,"color"),f=this.getCSS(a,"font-weight"),i=this.getCSS(a,"font-style"),h=this.getCSS(a,"text-decoration");b.nodeValue=this.textTransform(b.nodeValue,this.getCSS(a,"text-transform"));a=b.nodeValue;if(a.length>0){switch(f){case "401":f="bold"}if(h!="none")var k=this.fontMetrics(d,e);this.setContextVariable(c,"fillStyle",g);this.setContextVariable(c,"font",f+" "+i+" "+e+" "+d); +for(d=0;d-1)return this.fontData[c+1];c=document.createElement("div");document.getElementsByTagName("body")[0].appendChild(c);$(c).css({visibility:"hidden",fontFamily:a,fontSize:b,margin:0,padding:0});var d=document.createElement("img");d.src="http://html2canvas.hertzen.com/images/8.jpg";d.width=1;d.height=1;$(d).css({margin:0,padding:0});var e=document.createElement("span");$(e).css({fontFamily:a,fontSize:b,margin:0, +padding:0});e.appendChild(document.createTextNode("Hidden Text"));c.appendChild(e);c.appendChild(d);var g=d.offsetTop-e.offsetTop+1;c.removeChild(e);c.appendChild(document.createTextNode("Hidden Text"));$(c).css("line-height","normal");$(d).css("vertical-align","super");d={baseline:g,lineWidth:1,middle:d.offsetTop-c.offsetTop+1};this.fontData.push(a+"-"+b);this.fontData.push(d);$(c).remove();return d}; +html2canvas.prototype.textTransform=function(a,b){switch(b){case "lowercase":return a.toLowerCase();case "capitalize":return a.replace(/(^|\s|:|-|\(|\))([a-z])/g,function(a,b,e){return b+e.toUpperCase()});case "uppercase":return a.toUpperCase();default:return a}};html2canvas.prototype.trim=function(a){return a.replace(/^\s*/,"").replace(/\s*$/,"")}; +html2canvas.prototype.parseElement=function(a,b){var c=this;this.each(a.children,function(a,e){c.parsing(e,{ctx:b})});this.canvasRenderer(this.contextStacks);this.finish()}; +html2canvas.prototype.parsing=function(a,b){var c=this,b=this.newElement(a,b)||b,d=b.ctx;if(!this.ignoreRe.test(a.nodeName)){var e=this.contentsInZ(a);e.length==1?e[0].nodeType==1?this.parsing(e[0],b):e[0].nodeType==3&&this.newText(a,e[0],b.ctx):this.each(e,function(e,f){f.nodeType==1?c.parsing(f,b):f.nodeType==3&&c.newText(a,f,d)})}};html2canvas.prototype.log=function(){}; +html2canvas.prototype.getBounds=function(a){window.scroll(0,0);if(a.getBoundingClientRect)return a=a.getBoundingClientRect(),a.top=a.top,a.left=a.left,a;else{var b=$(a).offset();return{left:b.left+parseInt(this.getCSS(a,"border-left-width"),10),top:b.top+parseInt(this.getCSS(a,"border-top-width"),10),width:$(a).innerWidth(),height:$(a).innerHeight()}}};html2canvas.prototype.each=function(a,b){for(var b=b||function(){},c=0;c0){ bgp.top += add; } @@ -146,7 +146,7 @@ html2canvas.prototype.getBackgroundPosition = function(el,bounds,image){ -html2canvas.prototype.drawbackgroundRepeatY = function(image,bgp,x,y,w,h){ +html2canvas.prototype.drawbackgroundRepeatY = function(ctx,image,bgp,x,y,w,h){ var height, width = Math.min(image.width,w),bgy; @@ -162,14 +162,14 @@ html2canvas.prototype.drawbackgroundRepeatY = function(image,bgp,x,y,w,h){ }else{ height = image.height; } - this.drawBackgroundRepeat(image,x+bgp.left,bgy,width,height,x,y); + this.drawBackgroundRepeat(ctx,image,x+bgp.left,bgy,width,height,x,y); bgy = Math.floor(bgy+image.height); } } -html2canvas.prototype.drawbackgroundRepeatX = function(image,bgp,x,y,w,h){ +html2canvas.prototype.drawbackgroundRepeatX = function(ctx,image,bgp,x,y,w,h){ var height = Math.min(image.height,h), width,bgx; @@ -186,7 +186,7 @@ html2canvas.prototype.drawbackgroundRepeatX = function(image,bgp,x,y,w,h){ width = image.width; } - this.drawBackgroundRepeat(image,bgx,(y+bgp.top),width,height,x,y); + this.drawBackgroundRepeat(ctx,image,bgx,(y+bgp.top),width,height,x,y); bgx = Math.floor(bgx+image.width); @@ -194,7 +194,7 @@ html2canvas.prototype.drawbackgroundRepeatX = function(image,bgp,x,y,w,h){ } } -html2canvas.prototype.drawBackgroundRepeat = function(image,x,y,width,height,elx,ely){ +html2canvas.prototype.drawBackgroundRepeat = function(ctx,image,x,y,width,height,elx,ely){ var sourceX = 0, sourceY=0; if (elx-x>0){ @@ -205,7 +205,8 @@ html2canvas.prototype.drawBackgroundRepeat = function(image,x,y,width,height,elx sourceY = ely-y; } - this.ctx.drawImage( + this.drawImage( + ctx, image, sourceX, // source X sourceY, // source Y @@ -216,5 +217,4 @@ html2canvas.prototype.drawBackgroundRepeat = function(image,x,y,width,height,elx width-sourceX, // destination width height-sourceY // destination height ); - this.numDraws++; } \ No newline at end of file diff --git a/src/Core.js b/src/Core.js index 2297cc7..8259eb9 100644 --- a/src/Core.js +++ b/src/Core.js @@ -15,7 +15,8 @@ function html2canvas(el, userOptions) { }, iframeDefault: "default", flashCanvasPath: "http://html2canvas.hertzen.com/external/flashcanvas/flashcanvas.js", - renderViewport: false + renderViewport: false, + reorderZ: true }); this.element = el; @@ -30,7 +31,10 @@ function html2canvas(el, userOptions) { this.images = []; this.fontData = []; this.numDraws = 0; + this.contextStacks = []; this.ignoreElements = "IFRAME|OBJECT|PARAM"; + this.needReorder = false; + this.blockElements = new RegExp("(BR|PARAM)"); this.ignoreRe = new RegExp("("+this.ignoreElements+")"); @@ -58,43 +62,15 @@ html2canvas.prototype.init = function(){ var _ = this; - this.canvas = document.createElement('canvas'); - - // TODO remove jQuery dependency - this.canvas.width = $(document).width(); - this.canvas.height = $(document).height(); - - - - - if (!this.canvas.getContext){ - - // TODO include Flashcanvas - /* - var script = document.createElement('script'); - script.type = "text/javascript"; - script.src = this.opts.flashCanvasPath; - var s = document.getElementsByTagName('script')[0]; - s.parentNode.insertBefore(script, s); - - if (typeof FlashCanvas != "undefined") { - - FlashCanvas.initElement(this.canvas); - this.ctx = this.canvas.getContext('2d'); - } */ - - }else{ - this.ctx = this.canvas.getContext('2d'); - } - + this.ctx = new this.stackingContext($(document).width(),$(document).height()); + if (!this.ctx){ // canvas not initialized, let's kill it here this.log('Canvas not available'); return; } - // set common settings for canvas - this.ctx.textBaseline = "bottom"; + this.canvas = this.ctx.canvas; this.log('Finding background images'); @@ -123,17 +99,92 @@ html2canvas.prototype.start = function(){ this.log('Started parsing'); this.bodyOverflow = document.getElementsByTagName('body')[0].style.overflow; document.getElementsByTagName('body')[0].style.overflow = "hidden"; - this.newElement(this.element); + + var ctx = this.newElement(this.element, this.ctx) || this.ctx; - this.parseElement(this.element); + this.parseElement(this.element,ctx); + } } +html2canvas.prototype.stackingContext = function(width,height){ + this.canvas = document.createElement('canvas'); + + // TODO remove jQuery dependency + this.canvas.width = $(document).width(); + this.canvas.height = $(document).height(); + + if (!this.canvas.getContext){ + + // TODO include Flashcanvas + /* + var script = document.createElement('script'); + script.type = "text/javascript"; + script.src = this.opts.flashCanvasPath; + var s = document.getElementsByTagName('script')[0]; + s.parentNode.insertBefore(script, s); + + if (typeof FlashCanvas != "undefined") { + + FlashCanvas.initElement(this.canvas); + this.ctx = this.canvas.getContext('2d'); + } */ + + }else{ + this.ctx = this.canvas.getContext('2d'); + } + + // set common settings for canvas + this.ctx.textBaseline = "bottom"; + + return this.ctx; + +} + +html2canvas.prototype.storageContext = function(width,height){ + this.storage = []; + + + + // todo simplify this whole section + this.fillRect = function(x, y, w, h){ + this.storage.push( + { + type: "function", + name:"fillRect", + arguments:[x,y,w,h] + }); + + }; + + this.drawImage = function(image,sx,sy,sw,sh,dx,dy,dw,dh){ + this.storage.push( + { + type: "function", + name:"drawImage", + arguments:[image,sx,sy,sw,sh,dx,dy,dw,dh] + }); + }; + + this.fillText = function(currentText,x,y){ + + this.storage.push( + { + type: "function", + name:"fillText", + arguments:[currentText,x,y] + }); + } + + return this; + +} + /* - * Finished rendering, send callback - */ +* Finished rendering, send callback +*/ html2canvas.prototype.finish = function(){ this.log("Finished rendering"); diff --git a/src/Draw.js b/src/Draw.js index 6cb9ab7..4b7d23b 100644 --- a/src/Draw.js +++ b/src/Draw.js @@ -2,7 +2,7 @@ -html2canvas.prototype.newElement = function(el){ +html2canvas.prototype.newElement = function(el,parentStack){ var bounds = this.getBounds(el); @@ -14,14 +14,40 @@ html2canvas.prototype.newElement = function(el){ image; var bgcolor = this.getCSS(el,"background-color"); + var zindex = this.formatZ(this.getCSS(el,"z-index"),this.getCSS(el,"position"),parentStack.zIndex,el.parentNode); + + //console.log(el.nodeName+":"+zindex+":"+this.getCSS(el,"position")+":"+this.numDraws+":"+this.getCSS(el,"z-index")) + + var opacity = this.getCSS(el,"opacity"); + + //if (this.getCSS(el,"position")!="static"){ + + /* + this.contextStacks.push(ctx); + + ctx = new this.storageContext(); + */ + + + + var stack = { + ctx: new this.storageContext(), + zIndex: zindex, + opacity: opacity + }; + + var stackLength = this.contextStacks.push(stack); + + var ctx = this.contextStacks[stackLength-1].ctx; + //} /* * TODO add support for different border-style's than solid */ var borders = this.getBorderData(el); - + this.each(borders,function(borderSide,borderData){ if (borderData.width>0){ var bx = x, @@ -49,7 +75,7 @@ html2canvas.prototype.newElement = function(el){ break; } - _.newRect(bx,by,bw,bh,borderData.color); + _.newRect(ctx,bx,by,bw,bh,borderData.color); @@ -62,7 +88,7 @@ html2canvas.prototype.newElement = function(el){ if (this.ignoreRe.test(el.nodeName) && this.opts.iframeDefault != "transparent"){ if (this.opts.iframeDefault=="default"){ bgcolor = "#efefef"; - /* + /* * TODO write X over frame */ }else{ @@ -72,6 +98,7 @@ html2canvas.prototype.newElement = function(el){ // draw base element bgcolor this.newRect( + ctx, x+borders[3].width, y+borders[0].width, w-(borders[1].width+borders[3].width), @@ -84,13 +111,15 @@ html2canvas.prototype.newElement = function(el){ top: y+borders[0].width, width: w-(borders[1].width+borders[3].width), height: h-(borders[0].width+borders[2].width) - }); + } + ,ctx); if (el.nodeName=="IMG"){ image = _.loadImage(_.getAttr(el,'src')); if (image){ - this.ctx.drawImage( + this.drawImage( + ctx, image, 0, //sx 0, //sy @@ -99,15 +128,18 @@ html2canvas.prototype.newElement = function(el){ x+parseInt(_.getCSS(el,'padding-left'),10) + borders[3].width, //dx y+parseInt(_.getCSS(el,'padding-top'),10) + borders[0].width, // dy bounds.width - (borders[1].width + borders[3].width + parseInt(_.getCSS(el,'padding-left'),10) + parseInt(_.getCSS(el,'padding-right'),10)), //dw - bounds.height - (borders[0].width + borders[2].width + parseInt(_.getCSS(el,'padding-top'),10) + parseInt(_.getCSS(el,'padding-bottom'),10)) //dh - + bounds.height - (borders[0].width + borders[2].width + parseInt(_.getCSS(el,'padding-top'),10) + parseInt(_.getCSS(el,'padding-bottom'),10)) //dh ); - this.numDraws++; + }else{ this.log("Error loading :" + _.getAttr(el,'src')); } } - + + + + return this.contextStacks[stackLength-1]; + } @@ -121,20 +153,37 @@ html2canvas.prototype.newElement = function(el){ * Function to draw the text on the canvas */ -html2canvas.prototype.printText = function(currentText,x,y){ +html2canvas.prototype.printText = function(currentText,x,y,ctx){ if (this.trim(currentText).length>0){ - this.ctx.fillText(currentText,x,y); + + ctx.fillText(currentText,x,y); this.numDraws++; } } // Drawing a rectangle -html2canvas.prototype.newRect = function(x,y,w,h,bgcolor){ +html2canvas.prototype.newRect = function(ctx,x,y,w,h,bgcolor){ if (bgcolor!="transparent"){ - this.ctx.fillStyle = bgcolor; - this.ctx.fillRect (x, y, w, h); + this.setContextVariable(ctx,"fillStyle",bgcolor); + ctx.fillRect (x, y, w, h); this.numDraws++; } +} + +html2canvas.prototype.drawImage = function(ctx,image,sx,sy,sw,sh,dx,dy,dw,dh){ + ctx.drawImage( + image, + sx, //sx + sy, //sy + sw, //sw + sh, //sh + dx, //dx + dy, // dy + dw, //dw + dh //dh + ); + this.numDraws++; + } \ No newline at end of file diff --git a/src/Renderer.js b/src/Renderer.js new file mode 100644 index 0000000..b636b57 --- /dev/null +++ b/src/Renderer.js @@ -0,0 +1,119 @@ + + +html2canvas.prototype.canvasRenderer = function(queue){ + var _ = this; + + queue = this.sortQueue(queue); + + this.each(queue,function(i,storageContext){ + + if (storageContext.ctx.storage){ + _.each(storageContext.ctx.storage,function(a,renderItem){ + + switch(renderItem.type){ + case "variable": + _.ctx[renderItem.name] = renderItem.arguments; + break; + case "function": + if (renderItem.name=="fillRect"){ + _.ctx.fillRect(renderItem.arguments[0],renderItem.arguments[1],renderItem.arguments[2],renderItem.arguments[3]); + }else if(renderItem.name=="fillText"){ + _.ctx.fillText(renderItem.arguments[0],renderItem.arguments[1],renderItem.arguments[2]); + }else if(renderItem.name=="drawImage"){ + _.ctx.drawImage( + renderItem.arguments[0], + renderItem.arguments[1], + renderItem.arguments[2], + renderItem.arguments[3], + renderItem.arguments[4], + renderItem.arguments[5], + renderItem.arguments[6], + renderItem.arguments[7], + renderItem.arguments[8] + ); + }else{ + this.log(renderItem); + } + + + break; + default: + + } + + + }); + + } + + }); + + +}; + +/* + * Sort elements based on z-index and position attributes + */ + + +html2canvas.prototype.sortQueue = function(queue){ + if (!this.opts.reorderZ || !this.needReorder) return queue; + + var longest = 0; + this.each(queue,function(i,e){ + if (longeste.zIndex.length){ + e.zIndex += "0"; + } + e.zIndex = e.zIndex+counter; + + while((longest+more+(counter).toString().length)>e.zIndex.length){ + e.zIndex += "0"; + } + counter++; + // console.log(e.zIndex); + }); + + + + queue = queue.sort(function(a,b){ + + if (a.zIndex < b.zIndex) return -1; + if (a.zIndex > b.zIndex) return 1; + return 0; + }); + + + /* + + console.log('after'); + this.each(queue,function(i,e){ + console.log(i+":"+e.zIndex); + // console.log(e.ctx.storage); + }); */ + + return queue; +} + +html2canvas.prototype.setContextVariable = function(ctx,variable,value){ + if (!ctx.storage){ + ctx[variable] = value; + }else{ + ctx.storage.push( + { + type: "variable", + name:variable, + arguments:value + }); + } + +} \ No newline at end of file diff --git a/src/Text.js b/src/Text.js index 517a3c3..8ccd317 100644 --- a/src/Text.js +++ b/src/Text.js @@ -1,5 +1,5 @@ -html2canvas.prototype.newText = function(el,textNode){ +html2canvas.prototype.newText = function(el,textNode,ctx){ var family = this.getCSS(el,"font-family"); var size = this.getCSS(el,"font-size"); @@ -31,9 +31,10 @@ html2canvas.prototype.newText = function(el,textNode){ } - - this.ctx.font = bold+" "+font_style+" "+size+" "+family; - this.ctx.fillStyle = color; + this.setContextVariable(ctx,"fillStyle",color); + this.setContextVariable(ctx,"font",bold+" "+font_style+" "+size+" "+family); + //ctx.font = bold+" "+font_style+" "+size+" "+family; + //ctx.fillStyle = color; var oldTextNode = textNode; for(var c=0;c +* @created 15.7.2011 +* @website http://hertzen.com +--> + + + + z-index tests #1 + + + + + + + + + + + + +
+
+ + No z-indexed content +
+
DIV #1 +
position: relative; +
+
DIV #2 +
position: absolute; +
z-index: 1; +
+
+ +
+ +
+
DIV #3 +
position: relative; +
+
DIV #4 +
position: absolute; +
z-index: 2; +
+
+ Some more non-zindexed content +
+ + diff --git a/tests/z-index2.html b/tests/z-index2.html new file mode 100644 index 0000000..4bbb27e --- /dev/null +++ b/tests/z-index2.html @@ -0,0 +1,120 @@ + + + + + z-index tests #2 + + + + + + + + + + + +
+ +
+
DIV #1 +
position: relative; +
+
DIV #2 +
position: absolute; +
z-index: 2; +
+
+ +
+ +
+
DIV #3 +
position: relative; +
z-index: 1; +
+
DIV #4 +
position: absolute; +
z-index: 10; +
+
+ +

DIV #5
position:relative;
+ +

DIV #6
position:static;
+ + + diff --git a/tests/z-index3.html b/tests/z-index3.html new file mode 100644 index 0000000..dcce378 --- /dev/null +++ b/tests/z-index3.html @@ -0,0 +1,126 @@ + + + + + z-index tests #3 + + + + + + + + + + + +
+ +
+ LEVEL #1 + +
+ +
+
LEVEL #2 +
z-index: 1; + +
+ +
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+
LEVEL #3
+ +
+ +
+ +
+
LEVEL #2 +
z-index: 1; +
+ +
+
+ +
+ LEVEL #1 +
+ +
+ LEVEL #1 +
+ +
+ LEVEL #1 +
+ +