mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
added rendering stacks, queues and support z-index positioning
This commit is contained in:
parent
6b9516177a
commit
531d075c8c
@ -22,6 +22,7 @@
|
||||
<fileset dir="${src.dir}" includes="Border.js"/>
|
||||
<fileset dir="${src.dir}" includes="Draw.js"/>
|
||||
<fileset dir="${src.dir}" includes="Images.js"/>
|
||||
<fileset dir="${src.dir}" includes="Renderer.js"/>
|
||||
<fileset dir="${src.dir}" includes="Text.js"/>
|
||||
<fileset dir="${src.dir}" includes="Traversing.js"/>
|
||||
<fileset dir="${src.dir}" includes="Util.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 <img>:" + _.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 <img> 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 (longest<e.zIndex.length){
|
||||
longest = e.zIndex.length;
|
||||
}
|
||||
});
|
||||
|
||||
var counter = 0;
|
||||
//console.log(((queue.length).toString().length)-(count.length).toString().length);
|
||||
this.each(queue,function(i,e){
|
||||
|
||||
var more = ((queue.length).toString().length)-((counter).toString().length);
|
||||
while(longest>e.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;c<text.length;c++){
|
||||
@ -707,20 +927,20 @@ html2canvas.prototype.newText = function(el,textNode){
|
||||
|
||||
|
||||
|
||||
this.printText(oldTextNode.nodeValue,bounds.left,bounds.bottom);
|
||||
this.printText(oldTextNode.nodeValue,bounds.left,bounds.bottom,ctx);
|
||||
|
||||
switch(text_decoration) {
|
||||
case "underline":
|
||||
// Draws a line at the baseline of the font
|
||||
// TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size
|
||||
this.newRect(bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
|
||||
this.newRect(ctx,bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
case "overline":
|
||||
this.newRect(bounds.left,bounds.top,bounds.width,1,color);
|
||||
this.newRect(ctx,bounds.left,bounds.top,bounds.width,1,color);
|
||||
break;
|
||||
case "line-through":
|
||||
// TODO try and find exact position for line-through
|
||||
this.newRect(bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
|
||||
this.newRect(ctx,bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
|
||||
}
|
||||
@ -847,58 +1067,69 @@ html2canvas.prototype.trim = function(text) {
|
||||
}
|
||||
|
||||
|
||||
html2canvas.prototype.parseElement = function(element){
|
||||
html2canvas.prototype.parseElement = function(element,ctx){
|
||||
var _ = this;
|
||||
this.each(element.children,function(index,el){
|
||||
_.parsing(el);
|
||||
_.parsing(el,{
|
||||
ctx:ctx
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
this.canvasRenderer(this.contextStacks);
|
||||
this.finish();
|
||||
}
|
||||
|
||||
|
||||
|
||||
html2canvas.prototype.parsing = function(el){
|
||||
html2canvas.prototype.parsing = function(el,stack){
|
||||
|
||||
var _ = this;
|
||||
|
||||
this.newElement(el);
|
||||
//if (!this.blockElements.test(el.nodeName)){
|
||||
|
||||
stack = this.newElement(el,stack) || stack;
|
||||
|
||||
|
||||
var ctx = stack.ctx;
|
||||
|
||||
|
||||
if (!this.ignoreRe.test(el.nodeName)){
|
||||
if (!this.ignoreRe.test(el.nodeName)){
|
||||
|
||||
|
||||
|
||||
// TODO remove jQuery dependancy
|
||||
// TODO remove jQuery dependancy
|
||||
|
||||
var contents = $(el).contents();
|
||||
var contents = this.contentsInZ(el);
|
||||
|
||||
|
||||
if (contents.length == 1){
|
||||
if (contents.length == 1){
|
||||
|
||||
// check nodeType
|
||||
if (contents[0].nodeType==1){
|
||||
// it's an element, so let's look inside it
|
||||
this.parsing(contents[0]);
|
||||
}else if (contents[0].nodeType==3){
|
||||
// it's a text node, so lets print the text
|
||||
this.newText(el,contents[0]);
|
||||
}
|
||||
}else{
|
||||
|
||||
this.each(contents,function(cid,cel){
|
||||
|
||||
if (cel.nodeType==1){
|
||||
// element
|
||||
_.parsing(cel);
|
||||
}else if (cel.nodeType==3){
|
||||
_.newText(el,cel);
|
||||
}
|
||||
|
||||
});
|
||||
// check nodeType
|
||||
if (contents[0].nodeType==1){
|
||||
// it's an element, so let's look inside it
|
||||
this.parsing(contents[0],stack);
|
||||
}else if (contents[0].nodeType==3){
|
||||
// it's a text node, so lets print the text
|
||||
|
||||
}
|
||||
}
|
||||
this.newText(el,contents[0],stack.ctx);
|
||||
}
|
||||
}else{
|
||||
|
||||
this.each(contents,function(cid,cel){
|
||||
|
||||
if (cel.nodeType==1){
|
||||
// element
|
||||
_.parsing(cel,stack);
|
||||
}else if (cel.nodeType==3){
|
||||
_.newText(el,cel,ctx);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
@ -910,7 +1141,7 @@ html2canvas.prototype.log = function(a){
|
||||
var logger = window.console.log || function(log){
|
||||
alert(log);
|
||||
};
|
||||
/*
|
||||
/*
|
||||
if (typeof(window.console) != "undefined" && console.log){
|
||||
console.log(a);
|
||||
}else{
|
||||
@ -961,6 +1192,21 @@ html2canvas.prototype.each = function(arrayLoop,callbackFunc){
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function to get childNodes of an element in the order they should be rendered (based on z-index)
|
||||
* reference http://www.w3.org/TR/CSS21/zindex.html
|
||||
*/
|
||||
|
||||
html2canvas.prototype.contentsInZ = function(el){
|
||||
|
||||
// TODO remove jQuery dependency
|
||||
|
||||
var contents = $(el).contents();
|
||||
|
||||
return contents;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function for fetching the element attribute
|
||||
@ -979,8 +1225,46 @@ html2canvas.prototype.extendObj = function(options,defaults){
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
|
||||
|
||||
|
||||
html2canvas.prototype.leadingZero = function(num,size){
|
||||
|
||||
var s = "000000000" + num;
|
||||
return s.substr(s.length-size);
|
||||
}
|
||||
|
||||
html2canvas.prototype.formatZ = function(zindex,position,parentZ,parentNode){
|
||||
|
||||
if (!parentZ){
|
||||
parentZ = "0";
|
||||
}
|
||||
|
||||
|
||||
if (position!="static" && parentZ.charAt(0)=="0"){
|
||||
this.needReorder = true;
|
||||
parentZ = "1"+parentZ.slice(1);
|
||||
}
|
||||
|
||||
if (zindex=="auto"){
|
||||
var parentPosition = this.getCSS(parentNode,"position");
|
||||
if (parentPosition!="static" && typeof parentPosition != "undefined"){
|
||||
zindex = 0;
|
||||
}else{
|
||||
return parentZ;
|
||||
}
|
||||
}
|
||||
|
||||
var b = this.leadingZero(this.numDraws,9);
|
||||
|
||||
|
||||
var s = this.leadingZero(zindex+1,9);
|
||||
|
||||
// var s = "000000000" + num;
|
||||
return parentZ+""+""+s+""+b;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get element childNodes
|
||||
|
53
build/html2canvas.min.js
vendored
53
build/html2canvas.min.js
vendored
@ -6,28 +6,37 @@
|
||||
* Released under MIT License
|
||||
*/
|
||||
|
||||
function html2canvas(a,b){this.opts=this.extendObj(b||{},{logging:!1,ready:function(a){document.body.appendChild(a)},iframeDefault:"default",flashCanvasPath:"http://html2canvas.hertzen.com/external/flashcanvas/flashcanvas.js",renderViewport:!1});this.element=a;this.imagesLoaded=0;this.images=[];this.fontData=[];this.numDraws=0;this.ignoreElements="IFRAME|OBJECT|PARAM";this.ignoreRe=RegExp("("+this.ignoreElements+")");this.useRangeBounds=!1;this.init();return this}
|
||||
html2canvas.prototype.init=function(){var a=this;this.canvas=document.createElement("canvas");this.canvas.width=$(document).width();this.canvas.height=$(document).height();if(this.canvas.getContext)this.ctx=this.canvas.getContext("2d");this.ctx?(this.ctx.textBaseline="bottom",this.log("Finding background images"),this.getImages(this.element),this.log("Finding images"),this.each(document.images,function(b,c){a.preloadImage(a.getAttr(c,"src"))}),this.images.length==0&&this.start()):this.log("Canvas not available")};
|
||||
html2canvas.prototype.start=function(){if(this.images.length==0||this.imagesLoaded==this.images.length/2)this.log("Started parsing"),this.bodyOverflow=document.getElementsByTagName("body")[0].style.overflow,document.getElementsByTagName("body")[0].style.overflow="hidden",this.newElement(this.element),this.parseElement(this.element)};
|
||||
function html2canvas(a,b){this.opts=this.extendObj(b||{},{logging:!1,ready:function(a){document.body.appendChild(a)},iframeDefault:"default",flashCanvasPath:"http://html2canvas.hertzen.com/external/flashcanvas/flashcanvas.js",renderViewport:!1,reorderZ:!0});this.element=a;this.imagesLoaded=0;this.images=[];this.fontData=[];this.numDraws=0;this.contextStacks=[];this.ignoreElements="IFRAME|OBJECT|PARAM";this.needReorder=!1;this.blockElements=/(BR|PARAM)/;this.ignoreRe=RegExp("("+this.ignoreElements+
|
||||
")");this.useRangeBounds=!1;this.init();return this}html2canvas.prototype.init=function(){var a=this;(this.ctx=new this.stackingContext($(document).width(),$(document).height()))?(this.canvas=this.ctx.canvas,this.log("Finding background images"),this.getImages(this.element),this.log("Finding images"),this.each(document.images,function(b,c){a.preloadImage(a.getAttr(c,"src"))}),this.images.length==0&&this.start()):this.log("Canvas not available")};
|
||||
html2canvas.prototype.start=function(){if(this.images.length==0||this.imagesLoaded==this.images.length/2)this.log("Started parsing"),this.bodyOverflow=document.getElementsByTagName("body")[0].style.overflow,document.getElementsByTagName("body")[0].style.overflow="hidden",this.parseElement(this.element,this.newElement(this.element,this.ctx)||this.ctx)};
|
||||
html2canvas.prototype.stackingContext=function(){this.canvas=document.createElement("canvas");this.canvas.width=$(document).width();this.canvas.height=$(document).height();if(this.canvas.getContext)this.ctx=this.canvas.getContext("2d");this.ctx.textBaseline="bottom";return this.ctx};
|
||||
html2canvas.prototype.storageContext=function(){this.storage=[];this.fillRect=function(a,b,c,d){this.storage.push({type:"function",name:"fillRect",arguments:[a,b,c,d]})};this.drawImage=function(a,b,c,d,e,g,f,i,h){this.storage.push({type:"function",name:"drawImage",arguments:[a,b,c,d,e,g,f,i,h]})};this.fillText=function(a,b,c){this.storage.push({type:"function",name:"fillText",arguments:[a,b,c]})};return this};
|
||||
html2canvas.prototype.finish=function(){this.log("Finished rendering");document.getElementsByTagName("body")[0].style.overflow=this.bodyOverflow;if(this.opts.renderViewport){var a=document.createElement("canvas");a.getContext("2d");a.width=window.innerWidth;a.height=window.innerHeight}this.opts.ready(this)};
|
||||
html2canvas.prototype.drawBackground=function(a,b){var c=this.getCSS(a,"background-image"),e=this.getCSS(a,"background-repeat");if(typeof c!="undefined"&&/^(1|none)$/.test(c)==!1){var c=this.backgroundImageUrl(c),d=this.loadImage(c),i=this.getBackgroundPosition(a,b,d);if(d)switch(e){case "repeat-x":this.drawbackgroundRepeatX(d,i,b.left,b.top,b.width,b.height);break;case "repeat-y":this.drawbackgroundRepeatY(d,i,b.left,b.top,b.width,b.height);break;case "no-repeat":this.drawBackgroundRepeat(d,i.left+
|
||||
b.left,i.top+b.top,Math.min(b.width,d.width),Math.min(b.height,d.height),b.left,b.top);break;default:var f;i.top-=Math.ceil(i.top/d.height)*d.height;for(c=b.top+i.top;c<b.height+b.top;)e=Math.min(d.height,b.height+b.top-c),e=Math.floor(c+d.height)>e+c?e+c-c:d.height,c<b.top?(f=b.top-c,c=b.top):f=0,this.drawbackgroundRepeatX(d,i,b.left,c,b.width,e),f>0&&(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;d<b.height+b.top;)e=Math.min(g.height,b.height+b.top-d),e=Math.floor(d+g.height)>e+d?e+d-d:g.height,d<b.top?(f=b.top-d,d=b.top):f=0,this.drawbackgroundRepeatX(c,g,a,b.left,d,b.width,e),f>0&&(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;g<i+e;)d=Math.floor(g+a.height)>i+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;g<d+c;)f=Math.floor(g+a.width)>d+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 <img>:"+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;h<f+e;)g=Math.floor(h+b.height)>f+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;h<g+d;)i=Math.floor(h+b.width)>g+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 <img>:"+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<h.length;e++){i=c.splitText(1);
|
||||
if(this.useRangeBounds)document.createRange?(f=document.createRange(),f.selectNode(c)):f=document.body.createTextRange(),f=f.getBoundingClientRect()?f.getBoundingClientRect():{};else{var o=c.parentNode,l=document.createElement("wrapper"),j=c.cloneNode(!0);l.appendChild(c.cloneNode(!0));o.replaceChild(l,c);f=this.getBounds(l);o.replaceChild(j,l)}this.printText(c.nodeValue,f.left,f.bottom);switch(g){case "underline":this.newRect(f.left,Math.round(f.top+k.baseline+k.lineWidth),f.width,1,d);break;case "overline":this.newRect(f.left,
|
||||
f.top,f.width,1,d);break;case "line-through":this.newRect(f.left,Math.ceil(f.top+k.middle+k.lineWidth),f.width,1,d)}c=i}}};
|
||||
html2canvas.prototype.fontMetrics=function(a,b){var c=this.fontData.indexOf(a+"-"+b);if(c>-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;c<a.length;c++)b(c,a[c])};html2canvas.prototype.getAttr=function(a,b){return a.getAttribute(b)};
|
||||
html2canvas.prototype.extendObj=function(a,b){for(var c in a)b[c]=a[c];return b};html2canvas.prototype.getContents=function(a){return a.nodeName=="iframe"?a.contentDocument||a.contentWindow.document:a.childNodes};html2canvas.prototype.getCSS=function(a,b){return $(a).css(b)};
|
||||
html2canvas.prototype.canvasRenderer=function(a){var b=this,a=this.sortQueue(a);this.each(a,function(a,d){d.ctx.storage&&b.each(d.ctx.storage,function(a,c){switch(c.type){case "variable":b.ctx[c.name]=c.arguments;break;case "function":c.name=="fillRect"?b.ctx.fillRect(c.arguments[0],c.arguments[1],c.arguments[2],c.arguments[3]):c.name=="fillText"?b.ctx.fillText(c.arguments[0],c.arguments[1],c.arguments[2]):c.name=="drawImage"?b.ctx.drawImage(c.arguments[0],c.arguments[1],c.arguments[2],c.arguments[3],
|
||||
c.arguments[4],c.arguments[5],c.arguments[6],c.arguments[7],c.arguments[8]):this.log(c)}})})};
|
||||
html2canvas.prototype.sortQueue=function(a){if(!this.opts.reorderZ||!this.needReorder)return a;var b=0;this.each(a,function(a,c){if(b<c.zIndex.length)b=c.zIndex.length});var c=0;this.each(a,function(d,e){for(var g=a.length.toString().length-c.toString().length;b>e.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.zIndex<b.zIndex?-1:a.zIndex>b.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<a.length;d++){e=b.splitText(1);if(this.useRangeBounds)document.createRange?(f=document.createRange(),f.selectNode(b)):f=document.body.createTextRange(),f=f.getBoundingClientRect()?f.getBoundingClientRect():{};else{var i=b.parentNode,l=document.createElement("wrapper"),m=b.cloneNode(!0);l.appendChild(b.cloneNode(!0));i.replaceChild(l,b);f=this.getBounds(l);i.replaceChild(m,l)}this.printText(b.nodeValue,f.left,f.bottom,c);switch(h){case "underline":this.newRect(c,f.left,Math.round(f.top+k.baseline+
|
||||
k.lineWidth),f.width,1,g);break;case "overline":this.newRect(c,f.left,f.top,f.width,1,g);break;case "line-through":this.newRect(c,f.left,Math.ceil(f.top+k.middle+k.lineWidth),f.width,1,g)}b=e}}};
|
||||
html2canvas.prototype.fontMetrics=function(a,b){var c=this.fontData.indexOf(a+"-"+b);if(c>-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;c<a.length;c++)b(c,a[c])};html2canvas.prototype.contentsInZ=function(a){return $(a).contents()};
|
||||
html2canvas.prototype.getAttr=function(a,b){return a.getAttribute(b)};html2canvas.prototype.extendObj=function(a,b){for(var c in a)b[c]=a[c];return b};html2canvas.prototype.leadingZero=function(a,b){var c="000000000"+a;return c.substr(c.length-b)};
|
||||
html2canvas.prototype.formatZ=function(a,b,c,d){c||(c="0");if(b!="static"&&c.charAt(0)=="0")this.needReorder=!0,c="1"+c.slice(1);if(a=="auto")if(a=this.getCSS(d,"position"),a!="static"&&typeof a!="undefined")a=0;else return c;b=this.leadingZero(this.numDraws,9);a=this.leadingZero(a+1,9);return c+""+a+""+b};html2canvas.prototype.getContents=function(a){return a.nodeName=="iframe"?a.contentDocument||a.contentWindow.document:a.childNodes};html2canvas.prototype.getCSS=function(a,b){return $(a).css(b)};
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
|
||||
html2canvas.prototype.drawBackground = function(el,bounds){
|
||||
html2canvas.prototype.drawBackground = function(el,bounds,ctx){
|
||||
|
||||
|
||||
var background_image = this.getCSS(el,"background-image");
|
||||
@ -20,16 +20,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;
|
||||
|
||||
@ -63,7 +63,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;
|
||||
}
|
||||
@ -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++;
|
||||
}
|
123
src/Core.js
123
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");
|
||||
|
79
src/Draw.js
79
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 <img>:" + _.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++;
|
||||
|
||||
}
|
119
src/Renderer.js
Normal file
119
src/Renderer.js
Normal file
@ -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 (longest<e.zIndex.length){
|
||||
longest = e.zIndex.length;
|
||||
}
|
||||
});
|
||||
|
||||
var counter = 0;
|
||||
//console.log(((queue.length).toString().length)-(count.length).toString().length);
|
||||
this.each(queue,function(i,e){
|
||||
|
||||
var more = ((queue.length).toString().length)-((counter).toString().length);
|
||||
while(longest>e.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
|
||||
});
|
||||
}
|
||||
|
||||
}
|
17
src/Text.js
17
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<text.length;c++){
|
||||
@ -76,20 +77,20 @@ html2canvas.prototype.newText = function(el,textNode){
|
||||
|
||||
|
||||
|
||||
this.printText(oldTextNode.nodeValue,bounds.left,bounds.bottom);
|
||||
this.printText(oldTextNode.nodeValue,bounds.left,bounds.bottom,ctx);
|
||||
|
||||
switch(text_decoration) {
|
||||
case "underline":
|
||||
// Draws a line at the baseline of the font
|
||||
// TODO As some browsers display the line as more than 1px if the font-size is big, need to take that into account both in position and size
|
||||
this.newRect(bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
|
||||
this.newRect(ctx,bounds.left,Math.round(bounds.top+metrics.baseline+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
case "overline":
|
||||
this.newRect(bounds.left,bounds.top,bounds.width,1,color);
|
||||
this.newRect(ctx,bounds.left,bounds.top,bounds.width,1,color);
|
||||
break;
|
||||
case "line-through":
|
||||
// TODO try and find exact position for line-through
|
||||
this.newRect(bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
|
||||
this.newRect(ctx,bounds.left,Math.ceil(bounds.top+metrics.middle+metrics.lineWidth),bounds.width,1,color);
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -1,56 +1,67 @@
|
||||
|
||||
|
||||
html2canvas.prototype.parseElement = function(element){
|
||||
html2canvas.prototype.parseElement = function(element,ctx){
|
||||
var _ = this;
|
||||
this.each(element.children,function(index,el){
|
||||
_.parsing(el);
|
||||
_.parsing(el,{
|
||||
ctx:ctx
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
this.canvasRenderer(this.contextStacks);
|
||||
this.finish();
|
||||
}
|
||||
|
||||
|
||||
|
||||
html2canvas.prototype.parsing = function(el){
|
||||
html2canvas.prototype.parsing = function(el,stack){
|
||||
|
||||
var _ = this;
|
||||
|
||||
this.newElement(el);
|
||||
//if (!this.blockElements.test(el.nodeName)){
|
||||
|
||||
stack = this.newElement(el,stack) || stack;
|
||||
|
||||
|
||||
var ctx = stack.ctx;
|
||||
|
||||
|
||||
if (!this.ignoreRe.test(el.nodeName)){
|
||||
if (!this.ignoreRe.test(el.nodeName)){
|
||||
|
||||
|
||||
|
||||
// TODO remove jQuery dependancy
|
||||
// TODO remove jQuery dependancy
|
||||
|
||||
var contents = $(el).contents();
|
||||
var contents = this.contentsInZ(el);
|
||||
|
||||
|
||||
if (contents.length == 1){
|
||||
if (contents.length == 1){
|
||||
|
||||
// check nodeType
|
||||
if (contents[0].nodeType==1){
|
||||
// it's an element, so let's look inside it
|
||||
this.parsing(contents[0]);
|
||||
}else if (contents[0].nodeType==3){
|
||||
// it's a text node, so lets print the text
|
||||
this.newText(el,contents[0]);
|
||||
}
|
||||
}else{
|
||||
|
||||
this.each(contents,function(cid,cel){
|
||||
|
||||
if (cel.nodeType==1){
|
||||
// element
|
||||
_.parsing(cel);
|
||||
}else if (cel.nodeType==3){
|
||||
_.newText(el,cel);
|
||||
}
|
||||
|
||||
});
|
||||
// check nodeType
|
||||
if (contents[0].nodeType==1){
|
||||
// it's an element, so let's look inside it
|
||||
this.parsing(contents[0],stack);
|
||||
}else if (contents[0].nodeType==3){
|
||||
// it's a text node, so lets print the text
|
||||
|
||||
}
|
||||
}
|
||||
this.newText(el,contents[0],stack.ctx);
|
||||
}
|
||||
}else{
|
||||
|
||||
this.each(contents,function(cid,cel){
|
||||
|
||||
if (cel.nodeType==1){
|
||||
// element
|
||||
_.parsing(cel,stack);
|
||||
}else if (cel.nodeType==3){
|
||||
_.newText(el,cel,ctx);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
}
|
||||
|
57
src/Util.js
57
src/Util.js
@ -7,7 +7,7 @@ html2canvas.prototype.log = function(a){
|
||||
var logger = window.console.log || function(log){
|
||||
alert(log);
|
||||
};
|
||||
/*
|
||||
/*
|
||||
if (typeof(window.console) != "undefined" && console.log){
|
||||
console.log(a);
|
||||
}else{
|
||||
@ -58,6 +58,21 @@ html2canvas.prototype.each = function(arrayLoop,callbackFunc){
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function to get childNodes of an element in the order they should be rendered (based on z-index)
|
||||
* reference http://www.w3.org/TR/CSS21/zindex.html
|
||||
*/
|
||||
|
||||
html2canvas.prototype.contentsInZ = function(el){
|
||||
|
||||
// TODO remove jQuery dependency
|
||||
|
||||
var contents = $(el).contents();
|
||||
|
||||
return contents;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function for fetching the element attribute
|
||||
@ -76,8 +91,46 @@ html2canvas.prototype.extendObj = function(options,defaults){
|
||||
}
|
||||
return defaults;
|
||||
}
|
||||
|
||||
|
||||
|
||||
html2canvas.prototype.leadingZero = function(num,size){
|
||||
|
||||
var s = "000000000" + num;
|
||||
return s.substr(s.length-size);
|
||||
}
|
||||
|
||||
html2canvas.prototype.formatZ = function(zindex,position,parentZ,parentNode){
|
||||
|
||||
if (!parentZ){
|
||||
parentZ = "0";
|
||||
}
|
||||
|
||||
|
||||
if (position!="static" && parentZ.charAt(0)=="0"){
|
||||
this.needReorder = true;
|
||||
parentZ = "1"+parentZ.slice(1);
|
||||
}
|
||||
|
||||
if (zindex=="auto"){
|
||||
var parentPosition = this.getCSS(parentNode,"position");
|
||||
if (parentPosition!="static" && typeof parentPosition != "undefined"){
|
||||
zindex = 0;
|
||||
}else{
|
||||
return parentZ;
|
||||
}
|
||||
}
|
||||
|
||||
var b = this.leadingZero(this.numDraws,9);
|
||||
|
||||
|
||||
var s = this.leadingZero(zindex+1,9);
|
||||
|
||||
// var s = "000000000" + num;
|
||||
return parentZ+""+""+s+""+b;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Get element childNodes
|
||||
|
@ -49,7 +49,7 @@
|
||||
|
||||
div{
|
||||
text-decoration:underline;
|
||||
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.lineheight{
|
||||
|
98
tests/z-index1.html
Normal file
98
tests/z-index1.html
Normal file
@ -0,0 +1,98 @@
|
||||
<!--
|
||||
* @author Niklas von Hertzen <niklas at hertzen.com>
|
||||
* @created 15.7.2011
|
||||
* @website http://hertzen.com
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>z-index tests #1</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link href="#" type="text/css" rel="stylesheet">
|
||||
<script type="text/javascript" src="../external/jquery-1.6.2.min.js"></script>
|
||||
<script type="text/javascript" src="../build/html2canvas.js"></script>
|
||||
<script type="text/javascript" src="../build/jquery.plugin.html2canvas.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(window).ready(function() {
|
||||
|
||||
$('body').html2canvas({
|
||||
logging:true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
div { font: 12px Arial; }
|
||||
|
||||
span.bold { font-weight: bold; }
|
||||
|
||||
#div1,#div3 {
|
||||
height: 80px;
|
||||
position: relative;
|
||||
border: 1px dashed #669966;
|
||||
background-color: #ccffcc;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
#div2 {
|
||||
opacity: 0.8;
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
height: 200px;
|
||||
top: 20px;
|
||||
left: 170px;
|
||||
border: 1px dashed #990000;
|
||||
background-color: #ffdddd;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#div4 {
|
||||
opacity: 0.8;
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 70px;
|
||||
top: 65px;
|
||||
left: 50px;
|
||||
border: 1px dashed #000099;
|
||||
background-color: #ddddff;
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<br />
|
||||
|
||||
No z-indexed content
|
||||
<div id="div1">
|
||||
<br /><span class="bold">DIV #1</span>
|
||||
<br />position: relative;
|
||||
<div id="div2">
|
||||
<br /><span class="bold">DIV #2</span>
|
||||
<br />position: absolute;
|
||||
<br />z-index: 1;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div id="div3">
|
||||
<br /><span class="bold">DIV #3</span>
|
||||
<br />position: relative;
|
||||
<div id="div4">
|
||||
<br /><span class="bold">DIV #4</span>
|
||||
<br />position: absolute;
|
||||
<br />z-index: 2;
|
||||
</div>
|
||||
</div>
|
||||
Some more non-zindexed content
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
120
tests/z-index2.html
Normal file
120
tests/z-index2.html
Normal file
@ -0,0 +1,120 @@
|
||||
<!--
|
||||
* @author Niklas von Hertzen <niklas at hertzen.com>
|
||||
* @created 15.7.2011
|
||||
* @website http://hertzen.com
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>z-index tests #2</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link href="#" type="text/css" rel="stylesheet">
|
||||
<script type="text/javascript" src="../external/jquery-1.6.2.min.js"></script>
|
||||
<script type="text/javascript" src="../build/html2canvas.js"></script>
|
||||
<script type="text/javascript" src="../build/jquery.plugin.html2canvas.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(window).ready(function() {
|
||||
|
||||
$('body').html2canvas({
|
||||
logging:true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
div { font: 12px Arial; }
|
||||
|
||||
span.bold { font-weight: bold; }
|
||||
|
||||
#div2 { z-index: 2; }
|
||||
#div3 { z-index: 1; }
|
||||
#div4 { z-index: 10; }
|
||||
|
||||
#div1,#div3 {
|
||||
height: 80px;
|
||||
position: relative;
|
||||
border: 1px dashed #669966;
|
||||
background-color: #ccffcc;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
#div2 {
|
||||
opacity: 0.8;
|
||||
position: absolute;
|
||||
width: 150px;
|
||||
height: 200px;
|
||||
top: 20px;
|
||||
left: 170px;
|
||||
border: 1px dashed #990000;
|
||||
background-color: #ffdddd;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#div4 {
|
||||
opacity: 0.8;
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
height: 70px;
|
||||
top: 65px;
|
||||
left: 50px;
|
||||
border: 1px dashed #000099;
|
||||
background-color: #ddddff;
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
#div5{
|
||||
border: 1px dashed #669966;
|
||||
background-color: #ccffcc;
|
||||
padding-left: 5px;
|
||||
position:relative;
|
||||
margin-bottom:-15px;
|
||||
height:50px;
|
||||
margin-top:10px;
|
||||
|
||||
}
|
||||
|
||||
#div6{
|
||||
border: 1px dashed #000099;
|
||||
background-color: #ddddff;
|
||||
text-align: left;
|
||||
padding-left: 10px;
|
||||
|
||||
}
|
||||
|
||||
</style></head>
|
||||
|
||||
<body>
|
||||
|
||||
<br />
|
||||
|
||||
<div id="div1">
|
||||
<br /><span class="bold">DIV #1</span>
|
||||
<br />position: relative;
|
||||
<div id="div2">
|
||||
<br /><span class="bold">DIV #2</span>
|
||||
<br />position: absolute;
|
||||
<br />z-index: 2;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br />
|
||||
|
||||
<div id="div3">
|
||||
<br /><span class="bold">DIV #3</span>
|
||||
<br />position: relative;
|
||||
<br />z-index: 1;
|
||||
<div id="div4">
|
||||
<br /><span class="bold">DIV #4</span>
|
||||
<br />position: absolute;
|
||||
<br />z-index: 10;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="div5"><br />DIV #5<br />position:relative;<br /></div>
|
||||
|
||||
<div id ="div6"><br />DIV #6<br />position:static;<br /></div>
|
||||
|
||||
</body>
|
||||
</html>
|
126
tests/z-index3.html
Normal file
126
tests/z-index3.html
Normal file
@ -0,0 +1,126 @@
|
||||
<!--
|
||||
* @author Niklas von Hertzen <niklas at hertzen.com>
|
||||
* @created 15.7.2011
|
||||
* @website http://hertzen.com
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>z-index tests #3</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link href="#" type="text/css" rel="stylesheet">
|
||||
<script type="text/javascript" src="../external/jquery-1.6.2.min.js"></script>
|
||||
<script type="text/javascript" src="../build/html2canvas.js"></script>
|
||||
<script type="text/javascript" src="../build/jquery.plugin.html2canvas.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(window).ready(function() {
|
||||
|
||||
$('body').html2canvas({
|
||||
logging:true
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
|
||||
div { font: 12px Arial; }
|
||||
|
||||
span.bold { font-weight: bold; }
|
||||
|
||||
div.lev1 {
|
||||
width: 250px;
|
||||
height: 70px;
|
||||
position: relative;
|
||||
border: 2px outset #669966;
|
||||
background-color: #ccffcc;
|
||||
padding-left: 5px;
|
||||
|
||||
}
|
||||
|
||||
#container1 {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: 75px;
|
||||
}
|
||||
|
||||
div.lev2 {
|
||||
opacity: 0.9;
|
||||
width: 200px;
|
||||
height: 60px;
|
||||
position: relative;
|
||||
border: 2px outset #990000;
|
||||
background-color: #ffdddd;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
#container2 {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
top: 20px;
|
||||
left: 110px;
|
||||
}
|
||||
|
||||
div.lev3 {
|
||||
z-index: 10;
|
||||
width: 100px;
|
||||
position: relative;
|
||||
border: 2px outset #000099;
|
||||
background-color: #ddddff;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
</style></head>
|
||||
|
||||
<body>
|
||||
|
||||
<br />
|
||||
|
||||
<div class="lev1">
|
||||
<span class="bold">LEVEL #1</span>
|
||||
|
||||
<div id="container1">
|
||||
|
||||
<div class="lev2">
|
||||
<br /><span class="bold">LEVEL #2</span>
|
||||
<br />z-index: 1;
|
||||
|
||||
<div id="container2">
|
||||
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
<div class="lev3"><span class="bold">LEVEL #3</span></div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="lev2">
|
||||
<br /><span class="bold">LEVEL #2</span>
|
||||
<br />z-index: 1;
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lev1" style="position:static">
|
||||
<span class="bold">LEVEL #1</span>
|
||||
</div>
|
||||
|
||||
<div class="lev1">
|
||||
<span class="bold">LEVEL #1</span>
|
||||
</div>
|
||||
|
||||
<div class="lev1">
|
||||
<span class="bold">LEVEL #1</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user