Compare commits

..

220 Commits
0.3.2 ... 0.4.0

Author SHA1 Message Date
b2df50a858 Allow element node to be passed 2013-01-30 20:12:25 +02:00
8ddf10fc04 Fix taint testing 2013-01-12 22:28:00 +02:00
410537456a Reordered grunt tasks 2013-01-12 19:01:24 +02:00
3aa7d69cc7 updated examples 2013-01-12 01:41:09 +02:00
7a3dd7572c updated readme 2013-01-12 01:34:00 +02:00
1b37c5d1ea Refactored preload 2013-01-11 23:01:29 +02:00
67850f2cee Refactoring 2013-01-11 22:50:46 +02:00
88dd1e41c0 Moved pseudoelement rendering to parse.js 2013-01-11 22:36:23 +02:00
554185ed4a pseudoelement tests 2013-01-11 22:33:40 +02:00
222dfa84b7 remove legacy code 2013-01-11 20:38:33 +02:00
9b0c32c62c Fix firefox pseudoelement bug for images 2013-01-11 20:36:07 +02:00
2bb926c7d0 Fix webkit-gradient() parsing 2013-01-11 20:31:34 +02:00
861a18f977 Fix Chrome background-repeat parse error 2013-01-11 19:51:53 +02:00
cf15c4a59f Updated readme 2013-01-11 19:39:35 +02:00
2f3f27b672 Fix crash for browsers that don't support placeholder attribute 2013-01-11 19:34:56 +02:00
3032dc6ce0 Fix empty content getting rendered on firefox/IE 2013-01-11 19:31:05 +02:00
2b0db917e3 don't process pseudo elements for hidden elements; cleanup pseudo elements after render 2013-01-11 10:46:53 -06:00
d73e53fbf0 Merge remote-tracking branch 'niklasvh/develop' into develop 2013-01-11 09:51:59 -06:00
6d29cc5df3 chinese word rendering 2013-01-04 23:47:59 +02:00
dc21fab450 missing braces 2013-01-03 17:10:57 -06:00
5492d80135 simply resize images to background-size 2013-01-03 17:09:23 -06:00
a313524aa4 refactored renderer 2013-01-03 23:15:06 +02:00
3edf9fa743 Merge remote-tracking branch 'niklasvh/develop' into develop
Conflicts:
	src/Parse.js
	src/Preload.js
2013-01-03 15:07:38 -06:00
7d7deca342 updated results 2013-01-03 22:30:52 +02:00
053a0a4787 switched background rendering to use patterns 2013-01-03 22:25:35 +02:00
65b4bdf282 background clipping support 2013-01-03 20:34:47 +02:00
56780565f4 refactored border radius calculation 2013-01-03 18:37:27 +02:00
55ed0ffde0 render placeholder text 2013-01-02 17:03:16 -06:00
7da4326885 background-size fixes
generated gradients need a unique key (the same value can generate a
different image based on background-size); fix so that a single value
specified for background-size yields a scaled height as the second
parameter
2013-01-02 14:51:03 -06:00
eb57b61859 backgroundPosition should use backgroundSize as a baseline for %'s 2013-01-02 13:45:58 -06:00
bb73d3c15e initial border-radius rendering 2013-01-02 21:26:24 +02:00
9b5ae9e191 support for pseudo elements 2013-01-02 12:58:48 -06:00
2557a83dbe remove todo comment 2013-01-02 10:51:47 -06:00
67ccb33dd5 add tests for resizeBounds 2013-01-02 10:47:36 -06:00
85706166cc trimText regexp needs /g 2013-01-02 10:40:56 -06:00
57d6003b65 backgroundSize needs trimmed before second split
also move trimText to Util
2013-01-02 10:39:00 -06:00
9ce03d6e86 working background-size 2013-01-02 10:10:03 -06:00
3d3f923ed8 implementing background-size; use parseBackgroundImage in render 2013-01-01 10:42:22 -06:00
42abcfe5fc added border radius test 2012-12-31 20:10:18 +02:00
473ff45267 Merge remote-tracking branch 'niklasvh/develop' into develop
Conflicts:
	src/Core.js
	src/Parse.js
	src/Util.js
2012-12-30 17:25:31 -06:00
496c8488bd Moved font metrics to seperate file 2012-12-30 21:26:25 +02:00
df0f436e66 initial support for backgroundSize 2012-12-30 12:30:48 -06:00
6ce619f0c0 refactor Preload 2012-12-30 12:20:35 -06:00
3774f3655c update test names 2012-12-30 11:22:47 -06:00
0c66766d55 replace definition property, w/ args[]
Also fix reference for preloader
2012-12-30 11:21:44 -06:00
ba9ace71ba improved text-decoration: overline accuracy 2012-12-30 16:46:31 +02:00
b19c200c6c renamed results to readme 2012-12-30 16:30:28 +02:00
29bd4c8c05 added result markdown creator 2012-12-30 16:29:01 +02:00
0dd2c24ab4 refactored parsing init 2012-12-30 16:06:59 +02:00
d93e36d768 Moved browser support checks to seperate file 2012-12-30 15:48:55 +02:00
1357057cbf refactored background rendering 2012-12-30 15:38:17 +02:00
74e93cbb93 refactoring backgroundimage rendering 2012-12-30 15:21:36 +02:00
45853a083c refactored text rendering 2012-12-30 04:15:51 +02:00
cb43e09899 refactor parsing 2012-12-30 01:39:37 +02:00
bb1cd21367 refactored background color rendering 2012-12-30 01:11:05 +02:00
5faa45847e refactored image rendering 2012-12-30 01:06:11 +02:00
0c2572b5ce refactoring 2012-12-30 00:27:38 +02:00
aa5b3d41c4 refactoring 2012-12-29 23:35:52 +02:00
516edbceea Improve background-repeat accuracy for non int positions 2012-12-29 23:05:49 +02:00
c72a02bf64 refactoring 2012-12-29 21:06:40 +02:00
c3e9636e4f Moved renderer logic to renderer.js 2012-12-29 17:43:15 +02:00
816ff6d3c5 updated testing instructions 2012-12-29 16:34:56 +02:00
5f1fedf8f0 added npm dependencies 2012-12-29 16:31:57 +02:00
a82234873e updated .gitignore 2012-12-29 16:04:50 +02:00
d1ee6e9d64 removed baseline files 2012-12-29 16:02:46 +02:00
e7b4dd17b9 updated readme 2012-12-29 15:31:24 +02:00
05f3af4901 webdriver grunt task 2012-12-29 15:02:05 +02:00
630bed968e baseline results 2012-12-29 15:01:48 +02:00
7c870a6fb8 add border tests 2012-12-29 14:57:06 +02:00
52033a5d72 Fixed jquery path 2012-12-29 14:34:01 +02:00
07e80df399 Fixed lint error 2012-12-29 14:33:30 +02:00
7e38df782c don't generate gradient on invisible elements 2012-12-28 16:52:48 -06:00
7f1cbc70a8 fully remove regex; simplify whitespace check
jshint complained about case statements w/o break (boo)
2012-12-28 16:26:39 -06:00
b81d7473e3 rewrite parseBackgroundImage to remove RegExp
RegExp couldn't handle parens inside parens:
linear-gradient(rgb(0,0,0),rgb(255,0,0))
2012-12-28 16:22:43 -06:00
d7bef66cc5 export html2canvas, pass value not def to backgroundImage 2012-12-28 15:49:38 -06:00
04782c1716 parse out prefixed methods 2012-12-28 12:54:58 -06:00
a4b7d04e80 move parseBackgroundImage to Util; add tests 2012-12-28 12:33:57 -06:00
62cb111956 style update 2012-12-28 12:24:49 -06:00
3171390f80 satisfy lint task 2012-12-28 12:12:47 -06:00
8fe61a43b0 initial support for multiple background images
Adding code from http://jsbin.com/ebigux/latest
2012-12-28 11:53:15 -06:00
f0ce6917fa updated license formatting 2012-12-28 19:46:23 +02:00
118b42eb7e remove .baseline files 2012-12-28 19:42:59 +02:00
3bbcfe36e0 Test result outputs 2012-12-28 19:41:14 +02:00
cdc7a744e3 Different quote styles 2012-12-28 18:06:44 +02:00
fb0e7ca29d removed external files 2012-12-27 23:57:06 +02:00
4e978c60cc formatted tests into smaller units 2012-12-27 23:53:27 +02:00
c9ed8d91fa updated renderer 2012-12-27 23:07:00 +02:00
582d10e00d webdriver testing 2012-12-27 23:06:47 +02:00
4684177df8 fix ie 9 bug 2012-12-27 23:06:35 +02:00
5198028c7b updated description 2012-12-22 16:29:43 +02:00
d6ddb7e29d Added automated testing with selenium 2012-12-22 16:28:34 +02:00
9df9426c91 update gitignore 2012-12-22 16:27:28 +02:00
76aa1e8feb moved examples 2012-11-25 23:48:08 +02:00
2841f19647 List refactoring 2012-11-25 23:36:28 +02:00
c6baabc99c Text rendering refactoring 2012-11-25 23:26:18 +02:00
44023015b6 Refactoring 2012-11-25 23:05:30 +02:00
bca6458301 Clean up 2012-11-25 22:39:09 +02:00
7c0b893564 Added support for "data-html2canvas-ignore" attribute 2012-11-25 22:25:08 +02:00
084bf4b039 Switched build process to use grunt 2012-11-25 20:59:31 +02:00
e83de7ae00 Merge pull request #130 from CyberShadow/opera-fixes
Opera performance fixes
2012-10-22 04:33:37 -07:00
1b81f7d517 Accept 0px as an acceptable letter-spacing value for per-word rendering
This improves performance in Opera.
2012-10-20 22:18:46 +03:00
3164e5bae0 Don't create zero-width text node after each render
This fixes rendering the same node getting slower each time
when using Opera.
2012-10-20 22:15:58 +03:00
81ae37cbd1 syntax error in example 2012-07-10 22:42:16 +03:00
730ebcfcaa border-radius parsing 2012-06-26 17:18:34 +03:00
cce6e3537c corrected border drawing with multiple colors
initial code for border-radius implemented
2012-06-26 15:15:46 +03:00
311a67ee22 added SVG 2012-06-26 01:55:46 +03:00
be143935cb added usage example 2012-06-26 01:48:41 +03:00
d6cb548a5c updated to version 0.34 2012-06-26 01:35:11 +03:00
1ba911912d fixed firefox iframe permission error 2012-06-26 01:30:45 +03:00
343b86705f removed last jQuery dependencies
should be fully jQuery free now!
2012-06-26 01:17:03 +03:00
9f76f94a82 fix jQuery noconflict 2012-06-13 13:56:01 +03:00
b02bb4d452 Merge pull request #100 from BugHerd/linting
Added a sublime-project file for Sublime Text 2 with linting and standards.
2012-05-28 23:38:20 -07:00
3bdba0617a Merge pull request #99 from BugHerd/makefile
Added a makefile to build html2canvas
2012-05-28 23:32:17 -07:00
1059314258 Added a sublime-project file for Sublime Text 2 that contains the detected linting and standards set. Allows Sublime Text 2 to automatically follow the standards and have live linting enabled. Trimmed useless whitespace. 2012-05-29 11:26:26 +10:00
331c057273 Added a makefile to build html2canvas 2012-05-29 11:18:01 +10:00
8d3a0c2b0d cache computed style 2012-05-24 14:10:40 +03:00
16022b81c3 Merge pull request #92 from bdkzero/master
Support for other renderers than Canvas and fixed image rendering in SVG renderer
2012-05-22 05:19:23 -07:00
17f4701ee5 Created new build target 'build-allrends'. Use this to build html2canvas including all renderers 2012-05-21 00:34:21 +02:00
00c3fb791c Readded /build/ directory to .gitignore and removed /build directory 2012-05-20 23:55:23 +02:00
98bc1f0833 Prebuilt distribution files 2012-05-08 10:59:14 +02:00
a5969be6f6 Fixed custom renderer option 2012-04-23 23:04:23 +02:00
de1d1d7087 Minor changes 2012-04-17 12:43:51 +02:00
d494b8dfbd Added direnv conf file to .gitignore 2012-04-17 11:09:09 +02:00
cfc45e4f6e Fixed image rendering in SVG renderer 2012-04-17 10:58:14 +02:00
8d965029da Fixed support for other Renderers other than Canvas 2012-04-17 10:57:25 +02:00
1ad7ed3e1c Merge pull request #77 from SunboX/background-gradients
ellipse gradient generation should now work
2012-03-14 03:38:05 -07:00
d7f4509253 Merge pull request #78 from cobexer/fix-undefined-refs-and-bookmarklet
fixed a few undefined references, fixed missing files in a few places
2012-03-14 03:37:05 -07:00
b47347d6b8 fixed a few undefined references, fixed missing files in a few places 2012-03-12 07:37:18 +01:00
106b5ff214 "fixed circle gradient generation - image loading bug" 2012-03-11 17:12:24 +00:00
d1dec8712e "added ellipse background gradient generation" 2012-03-10 15:31:16 +00:00
fe4d2c5b81 "added TODO" 2012-03-10 14:28:09 +00:00
6cf3d36624 "added TODO" 2012-03-09 23:27:22 +00:00
4dc4132818 "removed TODO" 2012-03-09 23:26:23 +00:00
1ab9941df6 "big performance boost ;o)" 2012-03-09 23:23:17 +00:00
0fc5f643ba "cleanup" 2012-03-09 23:20:46 +00:00
c7995061c9 "added TODO" 2012-03-09 23:11:01 +00:00
12cf519e37 "some cleanup" 2012-03-09 23:09:16 +00:00
40bce5e84c "added -o-radial-gradient support" 2012-03-09 23:05:42 +00:00
0556892e12 "added -moz-radial-gradient support" 2012-03-09 22:58:32 +00:00
6c29664e35 "added tests for radial gradients" 2012-03-09 22:37:45 +00:00
155ad45292 "added -webkit-radial-gradient support" 2012-03-09 22:20:34 +00:00
66ad7190c0 "ups, missed one radial gradient" 2012-03-09 20:00:56 +00:00
4f22c18043 "added some radial gradient examples to background.html" 2012-03-09 19:58:04 +00:00
d83b06458c "removed IE9 svg gradients from background.html" 2012-03-09 19:55:41 +00:00
0d35571bbf Merge branch 'color-stops' of https://github.com/SunboX/html2canvas.git 2012-03-08 11:35:12 +02:00
211467fcc1 "better unit test for gradient parsing, check inverted width/height" 2012-03-07 18:24:43 +00:00
6390c1c7ac "center gradient BugFix" 2012-03-07 18:20:09 +00:00
a0b498fbf5 "added TODO" 2012-03-06 21:50:09 +00:00
cde96bb17e "added TODO´s" 2012-03-06 21:45:38 +00:00
57bff5292d "added contributors" 2012-03-06 21:41:22 +00:00
82446ee3c3 "cleanup" 2012-03-06 21:36:29 +00:00
ffd998b015 "-o-linear-gradient parsing" 2012-03-06 21:26:43 +00:00
51b2c01b0c "-moz-linear-gradient parsing" 2012-03-06 21:11:01 +00:00
c08ac5d0c4 add svg powered rendering 2012-03-06 17:11:10 +02:00
59306c839b Merge branch 'master' of https://github.com/niklasvh/html2canvas.git 2012-03-06 14:37:28 +02:00
5fb8cb3e0b reverting back to jQuery.contents() 2012-03-06 14:35:33 +02:00
67d3e0d0f5 first commit for SVG powered rendering 2012-03-06 14:32:45 +02:00
f387267c0f "TODO: implement radial gradient generation" 2012-03-05 23:22:01 +00:00
b65a850997 "cleanup test" 2012-03-05 23:15:58 +00:00
163219b656 "added -webkit-gradient parsing + tests" 2012-03-05 23:03:36 +00:00
a4f13de455 "renamed getColorStopsFromGradient to parseGradient" 2012-03-05 22:21:28 +00:00
75ba867988 "added tests for getColorStopsFromGradient" 2012-03-05 21:04:25 +00:00
ae8d499942 "small bugfix" 2012-03-05 19:37:54 +00:00
e479c952f7 "added another background gradient to backgrounds.html" 2012-03-05 19:33:52 +00:00
6637ba1bd7 "-webkit-linear-gradient color stops and rendering" 2012-03-05 19:20:44 +00:00
883d8bb75b Merge pull request #71 from cobexer/some-cleanup
Some cleanup
2012-03-05 02:53:25 -08:00
cfde57cb9f some whitespace/warning cleanup 2012-03-05 07:56:45 +01:00
0674543ab1 cleanup event handers of image objects after use 2012-03-05 07:54:42 +01:00
954631d045 "BugFixes" 2012-03-04 20:18:03 +00:00
9fc366b3f7 "tests: moved Generate into own module; fixed QUnit messages" 2012-03-04 20:15:10 +00:00
8a5b09be70 gradient check fix 2012-03-04 21:20:22 +02:00
7a3ca77471 few bug fixes to getCSS and unit tests 2012-03-04 21:16:18 +02:00
e82d703288 "tests: splitted Generate from CSS; if not supported pass test" 2012-03-04 19:06:25 +00:00
c018166563 exclude children 2012-03-04 20:17:01 +02:00
89d749e30a Merge branch 'master' of https://github.com/niklasvh/html2canvas.git 2012-03-04 20:15:51 +02:00
c056acee43 children test 2012-03-04 20:15:35 +02:00
c6ec65616c Merge pull request #70 from SunboX/tests-background-gradient
Tests background gradient
2012-03-04 10:14:03 -08:00
f47f9025b7 "tests: small bugfix" 2012-03-04 17:30:01 +00:00
d78687a3dc "fixed typo" 2012-03-04 17:00:58 +00:00
2a0dff32b2 "test: backgroundGradient" 2012-03-04 16:59:00 +00:00
00d73c0bf8 "test: backgroundGradients markup" 2012-03-04 15:16:07 +00:00
5e57ebc0ce "preventing JSHint messages" 2012-03-04 15:02:03 +00:00
3d7a6374ad bug fixes 2012-03-03 21:03:59 +02:00
4579fb25c6 removed jQuery.css dependancy and few general CSS bug fixes 2012-03-03 19:18:39 +02:00
e84d505f46 padding width needs to be in pixels 2012-03-03 16:56:31 +02:00
946bdef0d4 Merge pull request #67 from cobexer/some-fixes
Some fixes
2012-03-03 06:42:46 -08:00
b60fc931b5 moved backgroundPosition to utils 2012-03-03 16:39:52 +02:00
8affbc3db5 add unit testing for css 2012-03-03 16:38:05 +02:00
187ae9816e update tests/origin.html to use the new options overriding
allow tests to override selector and rendering options
2012-03-03 15:24:26 +01:00
38fe643b25 clear the canvas with the documentElement background color
see tests/background.html
2012-03-03 15:07:14 +01:00
fb7879fd17 background test: add html and body background-color 2012-03-03 15:07:14 +01:00
7726cd9f39 updated test.js to allow options 2012-03-03 00:52:46 +02:00
0b065ad5d8 bug fixes 2012-03-02 21:53:20 +02:00
ec881018b3 capitalized name 2012-03-02 21:25:08 +02:00
f83fb59053 fix naming 2012-03-02 21:24:21 +02:00
6eab1d5a9c removed screenshots.html, it's available in gh-pages branch 2012-03-02 20:37:10 +02:00
94f2f799a4 Split renderers to their own objects 2012-03-02 20:35:48 +02:00
cad3be2c66 bug fixes, and further simplification of API 2012-03-02 19:07:15 +02:00
c7d526c9ea simplified API and cleaned up code 2012-03-02 18:05:03 +02:00
bf994849e0 bug fixes for body background & firefox font 2012-03-02 14:43:25 +02:00
2dc8b9385e SVG taint fix, and additional taint testing options 2012-03-01 22:31:51 +02:00
6ef6c79f24 todo update proxy 2012-03-01 19:51:07 +02:00
3ad49efa00 added support for CORS images and option to create canvas as tainted 2012-03-01 19:44:25 +02:00
c86d12b915 test if canvas has become tainted 2012-03-01 18:44:52 +02:00
1447b031c6 html2canvas -> h2clog 2012-02-28 12:40:44 +02:00
e01d97df19 fixed an instance of html2canvas.log to h2clog 2012-02-28 12:39:38 +02:00
af60621d4f Update readme.md 2012-02-27 21:24:19 +02:00
f485028d30 Merge pull request #63 from cobexer/minification-improvements
Minification improvements
2012-02-27 11:09:26 -08:00
5878c201b3 added changelog entry 2012-02-26 23:19:39 +01:00
b6d6f44678 make FlashCanvas check closure compiler friendly 2012-02-26 23:04:46 +01:00
19f505214b cleanup .gitignore 2012-02-26 22:57:28 +01:00
c24223ca85 renamed html2canvas.log to h2clog (minifies better)
renamed the html2canvas.canvasContext to h2cRenderContext,
it's used by both backends and thus not canvas specific
2012-02-26 22:57:22 +01:00
b82be022b2 build: improve minification, more verbose 2012-02-26 22:30:34 +01:00
84a676403f Merge pull request #62 from cobexer/for-niklasvh
fix image loaded through the proxy hanging the preload process
2012-02-26 12:52:46 -08:00
afc358fb12 fix image loaded through the proxy hanging the preload process
images loaded through the proxy could hang the preload process if
they finish loading through the proxy but then fail to decode
and thus don't call the onload handler of the image object.
2012-02-26 13:14:16 +01:00
e925719151 added flashcanvas integration and some legacy IE bug fixes 2012-02-26 00:21:01 +02:00
b65357c55d added flashcanvas integration and some legacy IE bug fixes 2012-02-26 00:19:16 +02:00
c4cc1fe180 Update readme.md 2012-02-20 17:26:21 +02:00
abea4a89da Added changelog 2012-02-20 17:25:57 +02:00
0cb252ada9 add support for selecting single elements to render 2012-02-20 17:16:57 +02:00
90 changed files with 17060 additions and 6288 deletions

14
.gitignore vendored
View File

@ -1,15 +1,17 @@
/nbproject/
/images/
/external/
/tests/templates/
/tests/cache/
/tests/flashcanvas.html
/lib/
/dist/
/build/*.js
index.html
/bin/
/build/
image.jpg
screenshots.html
screenshots_local.html
/.project
/.settings/
node_modules/
.envrc
server.js
*.sublime-workspace
chromedriver.log
*.baseline

37
LICENSE
View File

@ -1,21 +1,22 @@
/*
The MIT License
Copyright (c) 2012 Niklas von Hertzen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,57 +0,0 @@
<!doctype html>
<html>
<head>
<title>html2canvas Bookmarklet</title>
<script type="text/javascript" src="external/jquery-1.6.2.min.js"></script>
<script type="text/javascript">
var isDebug = false, origBookmarklet = '';
function patchLinks() {
var bookmarklet = origBookmarklet;
if (isDebug) {
bookmarklet = bookmarklet.replace('//DEBUG: ', '');
}
bookmarklet = bookmarklet.replace(/\s\/\/.*/g, ''); // remove single line comments
bookmarklet = bookmarklet.replace(/[\u000A\u000D]+/g, ''); // remove all linebreaks
bookmarklet = bookmarklet.replace(/\/\*.*?\*\//g, ''); // remove multi line comments
bookmarklet = bookmarklet.replace(/\s\s+/g, ' '); // reduce multiple spaces to single spaces
bookmarklet = bookmarklet.replace(/\s+=\s+/g, '=');
$('a.bookmarklet').each(function(_, el) {
el.href = $(el).attr('data-href') + bookmarklet;
});
}
$(function() {
$('input[type=checkbox]').bind('change', function() {
isDebug = $(this).is(':checked');
patchLinks();
}).change();
$.ajax('src/plugins/bookmarklet.js', {
dataType: 'text',
success: function(data, status, xhr) {
origBookmarklet = data;
patchLinks();
}
});
});
</script>
</head>
<body>
<h1>html2canvas Bookmarklet</h1>
<p>
If you use a normal browser: drag the normal <a class="bookmarklet" data-href="javascript:">html2canvas</a> bookmarklet to your bookmarks toolbar.<br />
If not use the following link: <a class="bookmarklet" data-href="#_remove_this_javascript:">bookmarklet for those special mobile devices</a>
click / tap that link and then bookmark the page, edit the bookmark and remove the start up until including <code>#_remove_this_</code>
part at the beginning of the URL, it must start with: <code>javascript:</code> to be correct.
</p>
<p>
If you are using Firefox and the NoScript Addon: disable the ABE part of it,
took me quite some time to figure out that the reason for an unreliable bookmarklet was in NoScript...
</p>
<h2>For Developers:</h2>
<p>
If you are a developer and want to debug locally (you need the source tree of your html2canvas at:
<code>http(s)://localhost/html2canvas/</code>)
check the following box to get the bookmarklet patched automatically ;)<br />
<label>Debug bookmarklet: <input type="checkbox" /></label>
</p>
</body>
</html>

View File

@ -1,75 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="html2canvas" basedir="." default="build">
<property name="src.dir" location="src"/>
<property name="lib.dir" location="../lib"/>
<property name="build.dir" location="build"/>
<property name="dist" location="dist"/>
<property name="jquery-externs" value="jquery-1.4.4.externs.js"/>
<property name="JS_NAME" value="html2canvas.js"/>
<property name="JS_NAME_MIN" value="html2canvas.min.js"/>
<property name="JQUERY_PLUGIN_NAME" value="jquery.plugin.html2canvas.js"/>
<loadfile property="version" srcfile="version.txt" />
<fileset id="sourcefiles" dir="${src.dir}">
<include name="LICENSE"/>
<include name="Core.js"/>
<include name="Generate.js"/>
<include name="Parse.js"/>
<include name="Preload.js"/>
<include name="Queue.js"/>
<include name="Renderer.js"/>
</fileset>
<path id="jquery-plugin">
<fileset dir="${src.dir}" includes="LICENSE"/>
<fileset dir="${src.dir}/plugins" includes="${JQUERY_PLUGIN_NAME}"/>
</path>
<target name="plugins">
<concat fixlastline="yes" destfile="${build.dir}/${JQUERY_PLUGIN_NAME}">
<path refid="jquery-plugin"/>
</concat>
<replaceregexp match="@VERSION@" replace="${version}" flags="g" byline="true" file="${build.dir}/${JQUERY_PLUGIN_NAME}" />
</target>
<target name="build" depends="plugins">
<concat fixlastline="yes" destfile="${build.dir}/${JS_NAME}">
<fileset refid="sourcefiles"/>
</concat>
<replaceregexp match="@VERSION@" replace="${version}" flags="g" byline="true" file="${build.dir}/${JS_NAME}" />
</target>
<taskdef name="jscomp" classname="com.google.javascript.jscomp.ant.CompileTask"
classpath="${lib.dir}/compiler.jar" onerror="report"/>
<target name="release" depends="build">
<jscomp compilationLevel="simple" warning="verbose"
debug="false"
output="${build.dir}/${JS_NAME_MIN}">
<externs dir="${lib.dir}">
<file name="${jquery-externs}"/>
</externs>
<sources dir="${src.dir}">
<!-- need to write them again here since the closure compiler doesn't understand filesets,... -->
<file name="LICENSE"/>
<file name="Core.js"/>
<file name="Generate.js"/>
<file name="Parse.js"/>
<file name="Preload.js"/>
<file name="Queue.js"/>
<file name="Renderer.js"/>
</sources>
</jscomp>
<replaceregexp match="@VERSION@" replace="${version}" flags="g" byline="true" file="${build.dir}/${JS_NAME_MIN}" />
</target>
<target name="clean">
<delete file="${build.dir}/${JS_NAME}"></delete>
<delete file="${build.dir}/${JS_NAME_MIN}"></delete>
<delete file="${build.dir}/${JQUERY_PLUGIN_NAME}"></delete>
</target>
</project>

View File

2373
demo.html

File diff suppressed because it is too large Load Diff

View File

@ -1,186 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<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">
$(document).ready(function() {
$('body').html2canvas();
// var ss = $('ul').offset();
// alert(ss.left);
});
</script>
<title>
display/box/float/clear test
</title>
<style type="text/css">
/* last modified: 1 Dec 98 */
html {
font: 10px/1 Verdana, sans-serif;
background-color: blue;
color: white;
}
body {
margin: 1.5em;
border: .5em solid black;
padding: 0;
width: 48em;
background-color: white;
}
dl {
margin: 0;
border: 0;
padding: .5em;
}
dt {
background-color: rgb(204,0,0);
margin: 0;
padding: 1em;
width: 10.638%; /* refers to parent element's width of 47em. = 5em or 50px */
height: 28em;
border: .5em solid black;
float: left;
}
dd {
float: right;
margin: 0 0 0 1em;
border: 1em solid black;
padding: 1em;
width: 34em;
height: 27em;
}
ul {
margin: 0;
border: 0;
padding: 0;
}
li {
display: block; /* i.e., suppress marker */
color: black;
height: 9em;
width: 5em;
margin: 0;
border: .5em solid black;
padding: 1em;
float: left;
background-color: #FC0;
}
#bar {
background-color: black;
color: white;
width: 41.17%; /* = 14em */
border: 0;
margin: 0 1em;
}
#baz {
margin: 1em 0;
border: 0;
padding: 1em;
width: 10em;
height: 10em;
background-color: black;
color: white;
}
form {
margin: 0;
display: inline;
}
p {
margin: 0;
}
form p {
line-height: 1.9;
}
blockquote {
margin: 1em 1em 1em 2em;
border-width: 1em 1.5em 2em .5em;
border-style: solid;
border-color: black;
padding: 1em 0;
width: 5em;
height: 9em;
float: left;
background-color: #FC0;
color: black;
}
address {
font-style: normal;
}
h1 {
background-color: black;
color: white;
float: left;
margin: 1em 0;
border: 0;
padding: 1em;
width: 10em;
height: 10em;
font-weight: normal;
font-size: 1em;
}
</style>
</head>
<body>
<dl>
<dt>
toggle
</dt>
<dd>
<ul>
<li>
the way
</li>
<li id="bar">
<p>
the world ends
</p>
<form action="./" method="get">
<p>
bang
<input type="radio" name="foo" value="off">
</p>
<p>
whimper
<input type="radio" name="foo2" value="on">
</p>
</form>
</li>
<li>
i grow old
</li>
<li id="baz">
pluot?
</li>
</ul>
<blockquote>
<address>
bar maids,
</address>
</blockquote>
<h1>
sing to me, erbarme dich
</h1>
</dd>
</dl>
<p style="color: black; font-size: 1em; line-height: 1.3em; clear: both">
This is a nonsensical document, but syntactically valid HTML 4.0. All 100% conformant CSS1 agents should be able to render the document elements above this paragraph <b>indistinguishably</b> (to the pixel) from this reference rendering, (except font rasterization and form widgets). All discrepancies should be traceable to CSS1 implementation shortcomings. Once you have finished evaluating this test, you can return to the <A HREF="sec5526c.htm" style="text-decoration:none">parent page</A>.
</p>
</body>
</html>

View File

@ -1,72 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<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">
$(function(){
$('body').html2canvas();
});
</script>
<style>
.feedback-overlay-black{
background-color:#000;
opacity:0.5;
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
margin:0;
}
</style>
<style>
div{
padding:20px;
margin:0 auto;
border:5px solid black;
}
h1{
border-bottom:2px solid white;
}
h2{
background: #efefef;
padding:10px;
}
</style>
</head>
<body>
<div style="background:red;">
<div style="background:green;">
<div style="background:blue;border-color:white;">
<div style="background:yellow;"><div style="background:orange;"><h1>Heading</h1>
Text that isn't wrapped in anything.
<p>Followed by some text wrapped in a <b>&lt;p&gt; paragraph.</b> </p>
Maybe add a <a href="#">link</a> or a different style of <a href="#" style="background:white;" id="highlight">link with a highlight</a>.
<hr />
<h2>More content</h2>
<div style="width:10px;height:10px;border-width:10px;padding:0;">a</div>
</div></div>
</div>
</div>
</div>
</body>
</html>

186
examples/demo.html Normal file
View File

@ -0,0 +1,186 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
<html>
<head>
<script type="text/javascript" src="../tests/assets/jquery-1.6.2.js"></script>
<script type="text/javascript" src="../build/html2canvas.js"></script>
<script type="text/javascript">
$(document).ready(function() {
html2canvas( [ document.body ], {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
});
</script>
<title>
display/box/float/clear test
</title>
<style type="text/css">
/* last modified: 1 Dec 98 */
html {
font: 10px/1 Verdana, sans-serif;
background-color: blue;
color: white;
}
body {
margin: 1.5em;
border: .5em solid black;
padding: 0;
width: 48em;
background-color: white;
}
dl {
margin: 0;
border: 0;
padding: .5em;
}
dt {
background-color: rgb(204,0,0);
margin: 0;
padding: 1em;
width: 10.638%; /* refers to parent element's width of 47em. = 5em or 50px */
height: 28em;
border: .5em solid black;
float: left;
}
dd {
float: right;
margin: 0 0 0 1em;
border: 1em solid black;
padding: 1em;
width: 34em;
height: 27em;
}
ul {
margin: 0;
border: 0;
padding: 0;
}
li {
display: block; /* i.e., suppress marker */
color: black;
height: 9em;
width: 5em;
margin: 0;
border: .5em solid black;
padding: 1em;
float: left;
background-color: #FC0;
}
#bar {
background-color: black;
color: white;
width: 41.17%; /* = 14em */
border: 0;
margin: 0 1em;
}
#baz {
margin: 1em 0;
border: 0;
padding: 1em;
width: 10em;
height: 10em;
background-color: black;
color: white;
}
form {
margin: 0;
display: inline;
}
p {
margin: 0;
}
form p {
line-height: 1.9;
}
blockquote {
margin: 1em 1em 1em 2em;
border-width: 1em 1.5em 2em .5em;
border-style: solid;
border-color: black;
padding: 1em 0;
width: 5em;
height: 9em;
float: left;
background-color: #FC0;
color: black;
}
address {
font-style: normal;
}
h1 {
background-color: black;
color: white;
float: left;
margin: 1em 0;
border: 0;
padding: 1em;
width: 10em;
height: 10em;
font-weight: normal;
font-size: 1em;
}
</style>
</head>
<body>
<dl>
<dt>
toggle
</dt>
<dd>
<ul>
<li>
the way
</li>
<li id="bar">
<p>
the world ends
</p>
<form action="./" method="get">
<p>
bang
<input type="radio" name="foo" value="off">
</p>
<p>
whimper
<input type="radio" name="foo2" value="on">
</p>
</form>
</li>
<li>
i grow old
</li>
<li id="baz">
pluot?
</li>
</ul>
<blockquote>
<address>
bar maids,
</address>
</blockquote>
<h1>
sing to me, erbarme dich
</h1>
</dd>
</dl>
<p style="color: black; font-size: 1em; line-height: 1.3em; clear: both">
This is a nonsensical document, but syntactically valid HTML 4.0. All 100% conformant CSS1 agents should be able to render the document elements above this paragraph <b>indistinguishably</b> (to the pixel) from this reference rendering, (except font rasterization and form widgets). All discrepancies should be traceable to CSS1 implementation shortcomings. Once you have finished evaluating this test, you can return to the <A HREF="sec5526c.htm" style="text-decoration:none">parent page</A>.
</p>
</body>
</html>

68
examples/demo2.html Normal file
View File

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../tests/assets/jquery-1.6.2.js"></script>
<script type="text/javascript" src="../build/html2canvas.js"></script>
<script type="text/javascript">
$(document).ready(function() {
html2canvas( [ document.body ], {
onrendered: function(canvas) {
document.body.appendChild(canvas);
}
});
});
</script>
<style>
.feedback-overlay-black{
background-color:#000;
opacity:0.5;
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
margin:0;
}
</style>
<style>
div{
padding:20px;
margin:0 auto;
border:5px solid black;
}
h1{
border-bottom:2px solid white;
}
h2{
background: #efefef;
padding:10px;
}
</style>
</head>
<body>
<div style="background:red;">
<div style="background:green;">
<div style="background:blue;border-color:white;">
<div style="background:yellow;"><div style="background:orange;"><h1>Heading</h1>
Text that isn't wrapped in anything.
<p>Followed by some text wrapped in a <b>&lt;p&gt; paragraph.</b> </p>
Maybe add a <a href="#">link</a> or a different style of <a href="#" style="background:white;" id="highlight">link with a highlight</a>.
<hr />
<h2>More content</h2>
<div style="width:10px;height:10px;border-width:10px;padding:0;">a</div>
</div></div>
</div>
</div>
</div>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

73
grunt.js Normal file
View File

@ -0,0 +1,73 @@
/*global module:false*/
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: '<json:package.json>',
meta: {
banner: '/*\n <%= pkg.title || pkg.name %> <%= pkg.version %>' +
'<%= pkg.homepage ? " <" + pkg.homepage + ">\n" : "" %>' +
' Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>' +
'\n\n Released under <%= _.pluck(pkg.licenses, "type").join(", ") %> License\n*/',
pre: '(function(window, document, undefined){',
post: '})(window,document);'
},
lint: {
files: ['build/<%= pkg.name %>.js']
},
qunit: {
files: ['tests/qunit/index.html']
},
concat: {
dist: {
src: ['<banner:meta.banner>', '<banner:meta.pre>','src/*.js', 'src/renderers/Canvas.js', '<banner:meta.post>'],
dest: 'build/<%= pkg.name %>.js'
}
},
min: {
dist: {
src: ['<banner:meta.banner>', '<config:concat.dist.dest>'],
dest: 'build/<%= pkg.name %>.min.js'
}
},
watch: {
files: '<config:lint.files>',
tasks: 'lint qunit'
},
jshint: {
options: {
curly: true,
eqeqeq: true,
immed: true,
latedef: true,
newcap: true,
noarg: true,
sub: true,
undef: true,
boss: true,
eqnull: true,
browser: true
},
globals: {
jQuery: true
}
},
uglify: {}
});
var selenium = require("./tests/selenium.js");
grunt.registerTask('webdriver', 'Browser render tests', function(arg1) {
var done = this.async();
if (arguments.length === 0) {
selenium.tests();
} else {
selenium[arg1].apply(null, arguments);
}
});
// Default task.
grunt.registerTask('default', 'concat lint qunit min webdriver');
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

19
package.json Normal file
View File

@ -0,0 +1,19 @@
{
"title": "html2canvas",
"name": "html2canvas",
"description": "Screenshots with JavaScript",
"version": "0.4.0",
"author": {
"name":"Niklas von Hertzen (@niklasvh)"
},
"dependencies": {
"base64-arraybuffer": ">= 0.1.0",
"png-js": ">= 0.1.1",
"webdriver.js": ">= 0.1.0"
},
"homepage": "http://html2canvas.hertzen.com",
"licenses": [{
"type": "MIT"
}]
}

117
readme.md
View File

@ -2,35 +2,120 @@ html2canvas
===========
#### JavaScript HTML renderer ####
This script allows you to take "screenshots" of webpages or parts of it, directly on the users browser. The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page.
###How does it work?###
The script renders the current page as a canvas image, by reading the DOM and the different styles applied to the elements. However, as many elements are displayed differently on different browsers and operating systems (such as form elements such as radio buttons or checkboxes) as well as
The script renders the current page as a canvas image, by reading the DOM and the different styles applied to the elements.
It does <b>not require any rendering from the server</b>, as the whole image is created on the <b>clients browser</b>. However, for browsers without <code>canvas</code> support alternatives such as <a href="http://flashcanvas.net/">flashcanvas</a> or <a href="http://excanvas.sourceforge.net/">ExplorerCanvas</a> are necessary to create the image.
It does <b>not require any rendering from the server</b>, as the whole image is created on the <b>clients browser</b>. However, as it is heavily dependent on the browser, this library is *not suitable* to be used on for example on node.js.
It doesn't magically circumvent and browser content policy restrictions either, so rendering cross origin content will require a <a href="https://github.com/niklasvh/html2canvas/wiki/Proxies">proxy</a> to get the content to the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin</a>.
Additionally, to render <code>iframe</code> content or images situated outside of the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">same origin policy</a> a proxy will be necessary to load the content to the users browser.
The script is still in a **very experimental state**, so I don't recommend using it in a production environment nor start building applications with it yet, as there will be still major changes made.
The script is still in a very experimental state, so I don't recommend using it in a production environment nor start building applications with it yet, as there will be still major changes made. However, please do test it out and report your findings, especially if something should be working, but is displaying it incorrectly.
###Browser compatibility###
The script should work fine on the following browsers:
* Firefox 3.5+
* Google Chrome
* Newer versions of Opera (exactly how new is yet to be determined)
* >=IE9 (Older versions compatible with the use of flashcanvas)
Note that the compatibility will most likely be increased in future builds, as many of the current restrictions have at least partial work arounds, which can be used with older browser versions.
* Google Chrome
* Opera 12+
* IE9+
###So what isn't included yet?###
There are still a lot of CSS properties missing, including most CSS3 properties such as <code>text-shadow</code>, <code>box-radius</code> etc. as well as all elements created by the browser, such as radio and checkbox buttons and list icons. I will compile a full list of supported elements and CSS properties soon.
There is no support for <code>frame</code> and <code>object</code> content such as Flash.
As each CSS property needs to be manually built to be supported, there are a number of properties that are not yet supported.
### Usage ###
To render an `element` with html2canvas, simply call:
` html2canvas( [ element ], options);`
To access the created canvas, provide the `onrendered` event in the options which returns the canvas element as the first argument, as such:
html2canvas( [ document.body ], {
onrendered: function(canvas) {
/* canvas is the actual canvas element,
to append it to the page call for example
document.body.appendChild( canvas );
*/
}
});
### Building ###
The library uses <a href="http://gruntjs.com/">grunt</a> for building. Alternatively, you can download ready builds from the <a href="https://github.com/niklasvh/html2canvas/downloads">downloads page</a>.
Run the full build process (including lint, qunit and webdriver tests):
$ grunt
Skip lint and tests and simply build from source:
$ grunt concat
$ grunt min
### Running tests ###
The library has two sets of tests. The first set is a number of qunit tests that check that different values parsed by browsers are correctly converted in html2canvas. To run these tests with grunt you'll need <a href="http://phantomjs.org/">phantomjs</a>.
The other set of tests run Firefox, Chrome and Internet Explorer with <a href="https://github.com/niklasvh/webdriver.js">webdriver</a>. The selenium standalone server (runs on Java) is required for these tests and can be downloaded from <a href="http://code.google.com/p/selenium/downloads/list">here</a>. They capture an actual screenshot from the test pages and compare the image to the screenshot created by html2canvas and calculate the percentage differences. These tests generally aren't expected to provide 100% matches, but while commiting changes, these should generally not go decrease from the baseline values.
Start by downloading the dependencies:
$ npm install
Run qunit tests:
$ grunt test
Run webdriver tests:
$ java -jar /path/to/selenium-server-standalone-2.xx.x.jar
$ grunt webdriver
Commiting improvements in baseline values:
$ grunt webdriver:baseline
### Examples ###
For more information and examples, please visit the <a href="http://html2canvas.hertzen.com">homepage</a> or try the <a href="http://html2canvas.hertzen.com/screenshots.html">test console</a>.
For more information and examples, please visit the <a href="http://html2canvas.hertzen.com">homepage</a> or try the <a href="http://html2canvas.hertzen.com/screenshots.html">test console</a>.
### Contributing ###
If you wish to contribute to the project, please send the pull requests to the develop branch. Before making any changes, make sure to run the webdriver tests to create the baseline results. If some CSS property isn't supported or is incomplete, please create appropriate tests for it as well before submitting any code changes.
### Changelog ###
v0.40 -
* Added rendering tests with <a href="https://github.com/niklasvh/webdriver.js">webdriver</a>
* Switched to using grunt for building
* Removed support for IE<9, including any FlashCanvas bits
* Support for border-radius
* Support for multiple background images, size, and clipping
* Support for :before and :after pseudo elements
* Support for placeholder rendering
* Reformatted all tests to small units to test specific features
v0.34 - 26.6.2012
* Removed (last?) jQuery dependencies (<a href="https://github.com/niklasvh/html2canvas/commit/343b86705fe163766fcf735eb0217130e4bd5b17">niklasvh</a>)
* SVG-powered rendering (<a href="https://github.com/niklasvh/html2canvas/commit/67d3e0d0f59a5a654caf71a2e3be6494ff146c75">niklasvh</a>)
* Radial gradients (<a href="https://github.com/niklasvh/html2canvas/commit/4f22c18043a73c0c3bbf3b5e4d62714c56acd3c7">SunboX</a>)
* Split renderers to their own objects (<a href="https://github.com/niklasvh/html2canvas/commit/94f2f799a457cd29a21cc56ef8c06f1697866739">niklasvh</a>)
* Simplified API, cleaned up code (<a href="https://github.com/niklasvh/html2canvas/commit/c7d526c9eaa6a4abf4754d205fe1dee360c7660e">niklasvh</a>)
v0.33 - 2.3.2012
* SVG taint fix, and additional taint testing options for rendering (<a href="https://github.com/niklasvh/html2canvas/commit/2dc8b9385e656696cb019d615bdfa1d98b17d5d4">niklasvh</a>)
* Added support for CORS images and option to create canvas as tainted (<a href="https://github.com/niklasvh/html2canvas/commit/3ad49efa0032cde25c6ed32a39e35d1505d3b2ef">niklasvh</a>)
* Improved minification saved ~1K! (<a href="https://github.com/cobexer/html2canvas/commit/b82be022b2b9240bd503e078ac980bde2b953e43">cobexer</a>)
* Added integrated support for Flashcanvas (<a href="https://github.com/niklasvh/html2canvas/commit/e9257191519f67d74fd5e364d8dee3c0963ba5fc">niklasvh</a>)
* Fixed a variety of legacy IE bugs (<a href="https://github.com/niklasvh/html2canvas/commit/b65357c55d0701017bafcd357bc654b54d458f8f">niklasvh</a>)
v0.32 - 20.2.2012
* Added changelog!
* Added bookmarklet (<a href="https://github.com/niklasvh/html2canvas/commit/b320dd306e1a2d32a3bc5a71b6ebf6d8c060cde5">cobexer</a>)
* Option to select single element to render (<a href="https://github.com/niklasvh/html2canvas/commit/0cb252ada91c84ef411288b317c03e97da1f12ad">niklasvh</a>)
* Fixed closure compiler warnings (<a href="https://github.com/niklasvh/html2canvas/commit/36ff1ec7aadcbdf66851a0b77f0b9e87e4a8e4a1">cobexer</a>)
* Enable profiling in FF (<a href="https://github.com/niklasvh/html2canvas/commit/bbd75286a8406cf9e5aea01fdb7950d547edefb9">cobexer</a>)

View File

@ -1,348 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>JavaScript screenshot creator</title>
<style type="text/css">
a {
color: #0B0B0B;
background-color: #FDF9EE;
padding: 0 8px;
text-decoration: none;
font: normal 12px/16px "Trebuchet MS", Arial, Helvetica, sans-serif;
}
a:hover {
color: #0B0B0B;
background-color: #EFEBDE;
padding: 0 8px;
text-decoration: none;
font: normal 12px/16px "Trebuchet MS", Arial, Helvetica, sans-serif;
}
body {
font: normal 14px/19px Arial, Helvetica, sans-serif;
background-color: white;
color: #4E4628;
}
textarea {
background-color: #EFEBDE;
color: #0B0B0B;
border: #C3BCA4 1px solid;
font: normal 11px Arial, Helvetica, sans-serif;
width:300px;
height:150px;
}
h2 {
background-color: white;
color: #0B0B0B;
font: normal 28px/46px Georgia, "Times New Roman", Times, serif;
margin:0;
clear:both;
}
h3 {
color: #786E4E;
padding: 0 0 10px 55px;
height: 37px;
font: normal 24px/30px Georgia, "Times New Roman", Times, serif;
}
ul{
float:left;
margin:0;
}
table{
margin:0 auto;
width:400px;
border:1px solid black;
}
#content{
clear:both;
text-align:center;
}
#about{
padding:0 10px;
width:450px;
float:left;
}
</style>
<script type="text/javascript" src="external/jquery-1.6.2.min.js"></script>
<script type="text/javascript" src="build/html2canvas.js?221"></script>
<script type="text/javascript" src="build/jquery.plugin.html2canvas.js"></script>
<script type="text/javascript" src="http://www.hertzen.com/js/ganalytics-heatmap.js"></script>
<script type="text/javascript">
var date = new Date();
var message,
timeoutTimer,
timer;
var proxyUrl = "http://html2canvas.appspot.com";
function addRow(table,field,val){
var tr = $('<tr />').appendTo( $(table));
tr.append($('<td />').css('font-weight','bold').text(field)).append($('<td />').text(val));
}
function throwMessage(msg,duration){
window.clearTimeout(timeoutTimer);
timeoutTimer = window.setTimeout(function(){
message.fadeOut(function(){
message.remove();
});
},duration || 2000);
$(message).remove();
message = $('<div />').html(msg).css({
margin:0,
padding:10,
background: "#000",
opacity:0.7,
position:"fixed",
top:10,
right:10,
fontFamily: 'Tahoma' ,
color:'#fff',
fontSize:12,
borderRadius:12,
width:'auto',
height:'auto',
textAlign:'center',
textDecoration:'none'
}).hide().fadeIn().appendTo('body');
}
$(function(){
$('ul li a').click(function(e){
e.preventDefault();
$('#url').val(this.href);
$('button').click();
})
var iframe,d;
$('input[type="button"]').click(function(){
$(iframe.contentWindow).unbind('load');
$(iframe).contents().find('body').html2canvas({
canvasHeight: d.body.scrollHeight,
canvasWidth: d.body.scrollWidth,
logging:true
});
});
$('button').click(function(){
$(this).prop('disabled',true);
var url = $('#url').val();
$('#content').append($('<img />').attr('src','loading.gif').css('margin-top',40));
var urlParts = document.createElement('a');
urlParts.href = url;
$.ajax({
data: {
xhr2:false,
url:urlParts.href
},
url: proxyUrl,
dataType: "jsonp",
success: function(html){
iframe = document.createElement('iframe');
$(iframe).css({
'visibility':'hidden'
}).width($(window).width()).height($(window).height());
$('#content').append(iframe);
d = iframe.contentWindow.document;
d.open();
$(iframe.contentWindow).load(function(){
// timer = date.getTime();
var date = new Date();
var message,
timeoutTimer,
timer = date.getTime();
var body = $(iframe).contents().find('body')[0];
var preload = html2canvas.Preload(body, {
"complete": function(images){
var queue = html2canvas.Parse(body, images);
var canvas = $(html2canvas.Renderer(queue));
var finishTime = new Date();
$("#content").empty().append(canvas);
// throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)/1000) + " seconds<br />",4000);
}
});
/*
$(iframe).contents().find('body').html2canvas({
canvasHeight: d.body.scrollHeight,
canvasWidth: d.body.scrollWidth,
logging:true,
proxyUrl: proxyUrl,
logger:function(msg){
$('#logger').val(function(e,i){
return i+"\n"+msg;
});
},
ready: function(renderer) {
$('button').prop('disabled',false);
$("#content").empty();
var finishTime = new Date();
var table = $('<table />');
$('#content')
.append('<h2>Screenshot</h2>')
.append(renderer.canvas)
.append('<h3>Details</h3>')
.append(table);
addRow(table,"Creation time",((finishTime.getTime()-timer)/1000) + " seconds");
addRow(table,"Total draws", renderer.numDraws);
addRow(table,"Context stacks", renderer.contextStacks.length);
addRow(table,"Loaded images", renderer.images.length/2);
addRow(table,"Performed z-index reorder", renderer.needReorder);
addRow(table,"Used rangeBounds", renderer.support.rangeBounds);
throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)/1000) + " seconds<br />Total of "+renderer.numDraws+" draws performed",4000);
}
});*/
});
$('base').attr('href',urlParts.protocol+"//"+urlParts.hostname+"/");
var base = "<base href='"+urlParts.protocol+"//"+urlParts.hostname+"/' />";
var headIdx = html.indexOf('<head');
var endHeadIdx = html.indexOf('>', headIdx);
html = html.substring(0, endHeadIdx + 1) + base + html.substring(endHeadIdx + 1);
if ($("#disablejs").prop('checked')){
html = html.replace(/\<script/gi,"<!--<script");
html = html.replace(/\<\/script\>/gi,"<\/script>-->");
}
// console.log(html);
d.write(html);
d.close();
}
});
});
});
</script>
<script type="text/javascript">
var _gaq = _gaq || [];_gaq.push(['_setAccount', 'UA-188600-10']);_gaq.push(['_trackPageview']);(function() {var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);})();
</script>
<base />
</head>
<body>
<!-- <div style="background:red;padding:10px;color:#fff">
App engine proxy is <a href="http://twitter.com/#!/Niklasvh/status/96265826713350144">temporarily out of use</a> due to exceeded bandwidth use. Please try again tomorrow or meanwhile check other examples <a href="http://html2canvas.hertzen.com/">here</a>.
</div>-->
<div style="float:left;width:500px;">
<h1>JavaScript screenshot creator</h1>
<label for="url">Website URL:</label>
<input type="url" id="url" value="http://www.yahoo.com" /><button>Get screenshot!</button>
<!-- <input type="button" value="Try anyway" />--><br />
<label for="disablejs">Disable JavaScript (recommended, doesn't work well with the proxy)</label> <input type="checkbox" id="disablejs" checked /><br />
<small>Tested with Google Chrome 12, Firefox 4 and Opera 11.5</small>
</div>
<div style="float:right;">
<div style="margin-left:17px;float:right;">
<!-- Place this tag in your head or just before your close body tag -->
<script type="text/javascript" src="https://apis.google.com/js/plusone.js"></script>
<!-- Place this tag where you want the +1 button to render -->
<g:plusone size="tall"></g:plusone>
</div>
<div style="float:right;">
<a href="http://twitter.com/share" class="twitter-share-button" data-url="http://html2canvas.hertzen.com/" data-text="html2canvas - screenshots with #JavaScript" data-count="vertical" data-via="niklasvh">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
</div>
</div>
<div style="clear:both;"></div>
<h3>Recommended (tested) pages:</h3>
<ul>
<li><a href="http://www.yahoo.com">yahoo.com</a></li>
<li><a href="http://www.google.com">google.com</a></li>
<li><a href="https://github.com/niklasvh/html2canvas">github.com</a></li>
<li><a href="http://www.smashingmagazine.com">smashingmagazine.com</a></li>
<li><a href="http://www.mashable.com">mashable.com</a></li>
<li><a href="http://www.facebook.com/google">facebook.com/google</a></li>
<li><a href="http://www.youtube.com/">youtube.com</a></li>
<li><a href="http://www.cnn.com/">cnn.com</a></li>
<li><a href="http://www.engadget.com/">engadget.com (lot of elements, very slow)</a></li>
<li><a href="http://eu.battle.net/en/">battle.net</a></li>
</ul>
<div id="about"><b> About</b><br />
The whole screenshot is created with JavaScript. The only server interaction that is happening on this page is the proxy for loading the external pages/images into JSONP/CORS enabled page and onwards onto the JavaScript renderer script.
There are a lot of problems of loading external pages, even with a proxy, and as such many pages will not render at all. If you wish to try the script properly, I recommend you get a copy of the source from <a href="https://github.com/niklasvh/html2canvas">here</a> instead.
</div>
<div id="content"></div>
</body>
</html>

View File

@ -1,87 +1,157 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
"use strict";
Released under MIT License
*/
var _html2canvas = {},
previousElement,
computedCSS,
html2canvas;
var html2canvas = {};
html2canvas.logging = false;
html2canvas.log = function (a) {
if (html2canvas.logging && window.console && window.console.log) {
window.console.log(a);
}
};
html2canvas.Util = {};
html2canvas.Util.backgroundImage = function (src) {
if (/data:image\/.*;base64,/i.test( src ) || /^(-webkit|-moz|linear-gradient|-o-)/.test( src )) {
return src;
}
if (src.toLowerCase().substr( 0, 5 ) === 'url("') {
src = src.substr( 5 );
src = src.substr( 0, src.length - 2 );
} else {
src = src.substr( 4 );
src = src.substr( 0, src.length - 1 );
}
return src;
};
html2canvas.Util.Bounds = function getBounds (el) {
var clientRect,
bounds = {};
if (el.getBoundingClientRect){
clientRect = el.getBoundingClientRect();
// TODO add scroll position to bounds, so no scrolling of window necessary
bounds.top = clientRect.top;
bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
bounds.left = clientRect.left;
bounds.width = clientRect.width;
bounds.height = clientRect.height;
return bounds;
} /*else{
p = $(el).offset();
return {
left: p.left + getCSS(el,"borderLeftWidth", true),
top: p.top + getCSS(el,"borderTopWidth", true),
width:$(el).innerWidth(),
height:$(el).innerHeight()
};
} */
function h2clog(a) {
if (_html2canvas.logging && window.console && window.console.log) {
window.console.log(a);
}
}
html2canvas.Util.getCSS = function (el, attribute) {
// return jQuery(el).css(attribute);
/*
var val,
left,
rsLeft = el.runtimeStyle && el.runtimeStyle[ attribute ],
style = el.style;
if ( el.currentStyle ) {
val = el.currentStyle[ attribute ];
} else if (window.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, null)[ attribute ];
_html2canvas.Util = {};
_html2canvas.Util.trimText = (function(isNative){
return function(input){
if(isNative) { return isNative.apply( input ); }
else { return ((input || '') + '').replace( /^\s+|\s+$/g , '' ); }
};
})( String.prototype.trim );
_html2canvas.Util.parseBackgroundImage = function (value) {
var whitespace = ' \r\n\t',
method, definition, prefix, prefix_i, block, results = [],
c, mode = 0, numParen = 0, quote, args;
var appendResult = function(){
if(method) {
if(definition.substr( 0, 1 ) === '"') {
definition = definition.substr( 1, definition.length - 2 );
}
if(definition) {
args.push(definition);
}
if(method.substr( 0, 1 ) === '-' &&
(prefix_i = method.indexOf( '-', 1 ) + 1) > 0) {
prefix = method.substr( 0, prefix_i);
method = method.substr( prefix_i );
}
results.push({
prefix: prefix,
method: method.toLowerCase(),
value: block,
args: args
});
}
args = []; //for some odd reason, setting .length = 0 didn't work in safari
method =
prefix =
definition =
block = '';
};
appendResult();
for(var i = 0, ii = value.length; i<ii; i++) {
c = value[i];
if(mode === 0 && whitespace.indexOf( c ) > -1){
continue;
}
switch(c) {
case '"':
if(!quote) {
quote = c;
}
else if(quote === c) {
quote = null;
}
break;
case '(':
if(quote) { break; }
else if(mode === 0) {
mode = 1;
block += c;
continue;
} else {
numParen++;
}
break;
case ')':
if(quote) { break; }
else if(mode === 1) {
if(numParen === 0) {
mode = 0;
block += c;
appendResult();
continue;
} else {
numParen--;
}
}
break;
case ',':
if(quote) { break; }
else if(mode === 0) {
appendResult();
continue;
}
else if (mode === 1) {
if(numParen === 0 && !method.match(/^url$/i)) {
args.push(definition);
definition = '';
block += c;
continue;
}
}
break;
}
block += c;
if(mode === 0) { method += c; }
else { definition += c; }
}
*/
appendResult();
return results;
};
_html2canvas.Util.Bounds = function getBounds (el) {
var clientRect,
bounds = {};
if (el.getBoundingClientRect){
clientRect = el.getBoundingClientRect();
// TODO add scroll position to bounds, so no scrolling of window necessary
bounds.top = clientRect.top;
bounds.bottom = clientRect.bottom || (clientRect.top + clientRect.height);
bounds.left = clientRect.left;
// older IE doesn't have width/height, but top/bottom instead
bounds.width = clientRect.width || (clientRect.right - clientRect.left);
bounds.height = clientRect.height || (clientRect.bottom - clientRect.top);
return bounds;
}
};
_html2canvas.Util.getCSS = function (el, attribute, index) {
// return $(el).css(attribute);
var val,
isBackgroundSizePosition = attribute.match( /^background(Size|Position)$/ );
function toPX( attribute, val ) {
var rsLeft = el.runtimeStyle && el.runtimeStyle[ attribute ],
left,
style = el.style;
// Check if we are not dealing with pixels, (Opera has issues with this)
// Ported from jQuery css.js
// From the awesome hack by Dean Edwards
@ -89,49 +159,221 @@ html2canvas.Util.getCSS = function (el, attribute) {
// If we're not dealing with a regular pixel number
// but a number that has a weird ending, we need to convert it to pixels
// if ( !/^-?\d+(?:px)?$/i.test( val ) && /^-?\d/.test( val ) ) {
/*
// Remember the original values
left = style.left;
// Put in the new values to get a computed value out
if ( rsLeft ) {
el.runtimeStyle.left = el.currentStyle.left;
if ( !/^-?[0-9]+\.?[0-9]*(?:px)?$/i.test( val ) && /^-?\d/.test( val ) ) {
// Remember the original values
left = style.left;
// Put in the new values to get a computed value out
if ( rsLeft ) {
el.runtimeStyle.left = el.currentStyle.left;
}
style.left = attribute === "fontSize" ? "1em" : (val || 0);
val = style.pixelLeft + "px";
// Revert the changed values
style.left = left;
if ( rsLeft ) {
el.runtimeStyle.left = rsLeft;
}
}
if (!/^(thin|medium|thick)$/i.test( val )) {
return Math.round(parseFloat( val )) + "px";
}
return val;
}
if (previousElement !== el) {
computedCSS = document.defaultView.getComputedStyle(el, null);
}
val = computedCSS[attribute];
if (isBackgroundSizePosition) {
val = (val || '').split( ',' );
val = val[index || 0] || val[0] || 'auto';
val = _html2canvas.Util.trimText(val).split(' ');
if(attribute === 'backgroundSize' && (!val[ 0 ] || val[ 0 ].match( /cover|contain|auto/ ))) {
//these values will be handled in the parent function
} else {
val[ 0 ] = ( val[ 0 ].indexOf( "%" ) === -1 ) ? toPX( attribute + "X", val[ 0 ] ) : val[ 0 ];
if(val[ 1 ] === undefined) {
if(attribute === 'backgroundSize') {
val[ 1 ] = 'auto';
return val;
}
else {
// IE 9 doesn't return double digit always
val[ 1 ] = val[ 0 ];
}
}
style.left = attribute === "fontSize" ? "1em" : (val || 0);
val = style.pixelLeft + "px";
val[ 1 ] = ( val[ 1 ].indexOf( "%" ) === -1 ) ? toPX( attribute + "Y", val[ 1 ] ) : val[ 1 ];
}
} else if ( /border(Top|Bottom)(Left|Right)Radius/.test( attribute) ) {
var arr = val.split(" ");
if ( arr.length <= 1 ) {
arr[ 1 ] = arr[ 0 ];
}
arr[ 0 ] = parseInt( arr[ 0 ], 10 );
arr[ 1 ] = parseInt( arr[ 1 ], 10 );
val = arr;
}
// Revert the changed values
style.left = left;
if ( rsLeft ) {
el.runtimeStyle.left = rsLeft;
}*/
// val = $(el).css(attribute);
// }
return $(el).css(attribute);
return val;
};
html2canvas.Util.Extend = function (options, defaults) {
var key;
for (key in options) {
if (options.hasOwnProperty(key)) {
defaults[key] = options[key];
}
_html2canvas.Util.resizeBounds = function( current_width, current_height, target_width, target_height, stretch_mode ){
var target_ratio = target_width / target_height,
current_ratio = current_width / current_height,
output_width, output_height;
if(!stretch_mode || stretch_mode === 'auto') {
output_width = target_width;
output_height = target_height;
} else {
if(target_ratio < current_ratio ^ stretch_mode === 'contain') {
output_height = target_height;
output_width = target_height * current_ratio;
} else {
output_width = target_width;
output_height = target_width / current_ratio;
}
return defaults;
}
return { width: output_width, height: output_height };
};
html2canvas.Util.Children = function(el) {
// $(el).contents() !== el.childNodes, Opera / IE have issues with that
var children;
try {
children = $(el).contents();
} catch (ex) {
html2canvas.log("html2canvas.Util.Children failed with exception: " + ex.message);
children = [];
function backgroundBoundsFactory( prop, el, bounds, image, imageIndex, backgroundSize ) {
var bgposition = _html2canvas.Util.getCSS( el, prop, imageIndex ) ,
topPos,
left,
percentage,
val;
if (bgposition.length === 1){
val = bgposition[0];
bgposition = [];
bgposition[0] = val;
bgposition[1] = val;
}
return children;
if (bgposition[0].toString().indexOf("%") !== -1){
percentage = (parseFloat(bgposition[0])/100);
left = bounds.width * percentage;
if(prop !== 'backgroundSize') {
left -= (backgroundSize || image).width*percentage;
}
} else {
if(prop === 'backgroundSize') {
if(bgposition[0] === 'auto') {
left = image.width;
} else {
if(bgposition[0].match(/contain|cover/)) {
var resized = _html2canvas.Util.resizeBounds( image.width, image.height, bounds.width, bounds.height, bgposition[0] );
left = resized.width;
topPos = resized.height;
} else {
left = parseInt (bgposition[0], 10 );
}
}
} else {
left = parseInt( bgposition[0], 10 );
}
}
if(bgposition[1] === 'auto') {
topPos = left / image.width * image.height;
} else if (bgposition[1].toString().indexOf("%") !== -1){
percentage = (parseFloat(bgposition[1])/100);
topPos = bounds.height * percentage;
if(prop !== 'backgroundSize') {
topPos -= (backgroundSize || image).height * percentage;
}
} else {
topPos = parseInt(bgposition[1],10);
}
return [left, topPos];
}
_html2canvas.Util.BackgroundPosition = function( el, bounds, image, imageIndex, backgroundSize ) {
var result = backgroundBoundsFactory( 'backgroundPosition', el, bounds, image, imageIndex, backgroundSize );
return { left: result[0], top: result[1] };
};
_html2canvas.Util.BackgroundSize = function( el, bounds, image, imageIndex ) {
var result = backgroundBoundsFactory( 'backgroundSize', el, bounds, image, imageIndex );
return { width: result[0], height: result[1] };
};
_html2canvas.Util.Extend = function (options, defaults) {
for (var key in options) {
if (options.hasOwnProperty(key)) {
defaults[key] = options[key];
}
}
return defaults;
};
/*
* Derived from jQuery.contents()
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
_html2canvas.Util.Children = function( elem ) {
var children;
try {
children = (elem.nodeName && elem.nodeName.toUpperCase() === "IFRAME") ?
elem.contentDocument || elem.contentWindow.document : (function( array ){
var ret = [];
if ( array !== null ) {
(function( first, second ) {
var i = first.length,
j = 0;
if ( typeof second.length === "number" ) {
for ( var l = second.length; j < l; j++ ) {
first[ i++ ] = second[ j ];
}
} else {
while ( second[j] !== undefined ) {
first[ i++ ] = second[ j++ ];
}
}
first.length = i;
return first;
})( ret, array );
}
return ret;
})( elem.childNodes );
} catch (ex) {
h2clog("html2canvas.Util.Children failed with exception: " + ex.message);
children = [];
}
return children;
};

64
src/Font.js Normal file
View File

@ -0,0 +1,64 @@
_html2canvas.Util.Font = (function () {
var fontData = {};
return function(font, fontSize, doc) {
if (fontData[font + "-" + fontSize] !== undefined) {
return fontData[font + "-" + fontSize];
}
var container = doc.createElement('div'),
img = doc.createElement('img'),
span = doc.createElement('span'),
sampleText = 'Hidden Text',
baseline,
middle,
metricsObj;
container.style.visibility = "hidden";
container.style.fontFamily = font;
container.style.fontSize = fontSize;
container.style.margin = 0;
container.style.padding = 0;
doc.body.appendChild(container);
// http://probablyprogramming.com/2009/03/15/the-tiniest-gif-ever (handtinywhite.gif)
img.src = "data:image/gif;base64,R0lGODlhAQABAIABAP///wAAACwAAAAAAQABAAACAkQBADs=";
img.width = 1;
img.height = 1;
img.style.margin = 0;
img.style.padding = 0;
img.style.verticalAlign = "baseline";
span.style.fontFamily = font;
span.style.fontSize = fontSize;
span.style.margin = 0;
span.style.padding = 0;
span.appendChild(doc.createTextNode(sampleText));
container.appendChild(span);
container.appendChild(img);
baseline = (img.offsetTop - span.offsetTop) + 1;
container.removeChild(span);
container.appendChild(doc.createTextNode(sampleText));
container.style.lineHeight = "normal";
img.style.verticalAlign = "super";
middle = (img.offsetTop-container.offsetTop) + 1;
metricsObj = {
baseline: baseline,
lineWidth: 1,
middle: middle
};
fontData[font + "-" + fontSize] = metricsObj;
doc.body.removeChild(container);
return metricsObj;
};
})();

View File

@ -1,160 +1,439 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
(function(){
Released under MIT License
*/
_html2canvas.Generate = {};
html2canvas.Generate = {};
var reGradients = [
/^(-webkit-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
/^(-o-linear-gradient)\(([a-z\s]+)([\w\d\.\s,%\(\)]+)\)$/,
/^(-webkit-gradient)\((linear|radial),\s((?:\d{1,3}%?)\s(?:\d{1,3}%?),\s(?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)\-]+)\)$/,
/^(-moz-linear-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?))([\w\d\.\s,%\(\)]+)\)$/,
/^(-webkit-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z\-]+)([\w\d\.\s,%\(\)]+)\)$/,
/^(-moz-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s?([a-z\-]*)([\w\d\.\s,%\(\)]+)\)$/,
/^(-o-radial-gradient)\(((?:\d{1,3}%?)\s(?:\d{1,3}%?)),\s(\w+)\s([a-z\-]+)([\w\d\.\s,%\(\)]+)\)$/
];
/*
* TODO: Add IE10 vendor prefix (-ms) support
* TODO: Add W3C gradient (linear-gradient) support
* TODO: Add old Webkit -webkit-gradient(radial, ...) support
* TODO: Maybe some RegExp optimizations are possible ;o)
*/
_html2canvas.Generate.parseGradient = function(css, bounds) {
var gradient, i, len = reGradients.length, m1, stop, m2, m2Len, step, m3, tl,tr,br,bl;
for(i = 0; i < len; i+=1){
m1 = css.match(reGradients[i]);
if(m1) {
break;
}
}
if(m1) {
switch(m1[1]) {
case '-webkit-linear-gradient':
case '-o-linear-gradient':
gradient = {
type: 'linear',
x0: null,
y0: null,
x1: null,
y1: null,
colorStops: []
};
// get coordinates
m2 = m1[2].match(/\w+/g);
if(m2){
m2Len = m2.length;
for(i = 0; i < m2Len; i+=1){
switch(m2[i]) {
case 'top':
gradient.y0 = 0;
gradient.y1 = bounds.height;
break;
case 'right':
gradient.x0 = bounds.width;
gradient.x1 = 0;
break;
case 'bottom':
gradient.y0 = bounds.height;
gradient.y1 = 0;
break;
case 'left':
gradient.x0 = 0;
gradient.x1 = bounds.width;
break;
}
}
}
if(gradient.x0 === null && gradient.x1 === null){ // center
gradient.x0 = gradient.x1 = bounds.width / 2;
}
if(gradient.y0 === null && gradient.y1 === null){ // center
gradient.y0 = gradient.y1 = bounds.height / 2;
}
// get colors and stops
m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
if(m2){
m2Len = m2.length;
step = 1 / Math.max(m2Len - 1, 1);
for(i = 0; i < m2Len; i+=1){
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
if(m3[2]){
stop = parseFloat(m3[2]);
if(m3[3] === '%'){
stop /= 100;
} else { // px - stupid opera
stop /= bounds.width;
}
} else {
stop = i * step;
}
gradient.colorStops.push({
color: m3[1],
stop: stop
});
}
}
break;
case '-webkit-gradient':
gradient = {
type: m1[2] === 'radial' ? 'circle' : m1[2], // TODO: Add radial gradient support for older mozilla definitions
x0: 0,
y0: 0,
x1: 0,
y1: 0,
colorStops: []
};
// get coordinates
m2 = m1[3].match(/(\d{1,3})%?\s(\d{1,3})%?,\s(\d{1,3})%?\s(\d{1,3})%?/);
if(m2){
gradient.x0 = (m2[1] * bounds.width) / 100;
gradient.y0 = (m2[2] * bounds.height) / 100;
gradient.x1 = (m2[3] * bounds.width) / 100;
gradient.y1 = (m2[4] * bounds.height) / 100;
}
// get colors and stops
m2 = m1[4].match(/((?:from|to|color-stop)\((?:[0-9\.]+,\s)?(?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)\))+/g);
if(m2){
m2Len = m2.length;
for(i = 0; i < m2Len; i+=1){
m3 = m2[i].match(/(from|to|color-stop)\(([0-9\.]+)?(?:,\s)?((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\)/);
stop = parseFloat(m3[2]);
if(m3[1] === 'from') {
stop = 0.0;
}
if(m3[1] === 'to') {
stop = 1.0;
}
gradient.colorStops.push({
color: m3[3],
stop: stop
});
}
}
break;
case '-moz-linear-gradient':
gradient = {
type: 'linear',
x0: 0,
y0: 0,
x1: 0,
y1: 0,
colorStops: []
};
// get coordinates
m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
// m2[1] == 0% -> left
// m2[1] == 50% -> center
// m2[1] == 100% -> right
// m2[2] == 0% -> top
// m2[2] == 50% -> center
// m2[2] == 100% -> bottom
if(m2){
gradient.x0 = (m2[1] * bounds.width) / 100;
gradient.y0 = (m2[2] * bounds.height) / 100;
gradient.x1 = bounds.width - gradient.x0;
gradient.y1 = bounds.height - gradient.y0;
}
// get colors and stops
m2 = m1[3].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}%)?)+/g);
if(m2){
m2Len = m2.length;
step = 1 / Math.max(m2Len - 1, 1);
for(i = 0; i < m2Len; i+=1){
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%)?/);
if(m3[2]){
stop = parseFloat(m3[2]);
if(m3[3]){ // percentage
stop /= 100;
}
} else {
stop = i * step;
}
gradient.colorStops.push({
color: m3[1],
stop: stop
});
}
}
break;
case '-webkit-radial-gradient':
case '-moz-radial-gradient':
case '-o-radial-gradient':
gradient = {
type: 'circle',
x0: 0,
y0: 0,
x1: bounds.width,
y1: bounds.height,
cx: 0,
cy: 0,
rx: 0,
ry: 0,
colorStops: []
};
// center
m2 = m1[2].match(/(\d{1,3})%?\s(\d{1,3})%?/);
if(m2){
gradient.cx = (m2[1] * bounds.width) / 100;
gradient.cy = (m2[2] * bounds.height) / 100;
}
// size
m2 = m1[3].match(/\w+/);
m3 = m1[4].match(/[a-z\-]*/);
if(m2 && m3){
switch(m3[0]){
case 'farthest-corner':
case 'cover': // is equivalent to farthest-corner
case '': // mozilla removes "cover" from definition :(
tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
gradient.rx = gradient.ry = Math.max(tl, tr, br, bl);
break;
case 'closest-corner':
tl = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.cy, 2));
tr = Math.sqrt(Math.pow(gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
br = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.y1 - gradient.cy, 2));
bl = Math.sqrt(Math.pow(gradient.x1 - gradient.cx, 2) + Math.pow(gradient.cy, 2));
gradient.rx = gradient.ry = Math.min(tl, tr, br, bl);
break;
case 'farthest-side':
if(m2[0] === 'circle'){
gradient.rx = gradient.ry = Math.max(
gradient.cx,
gradient.cy,
gradient.x1 - gradient.cx,
gradient.y1 - gradient.cy
);
} else { // ellipse
gradient.type = m2[0];
gradient.rx = Math.max(
gradient.cx,
gradient.x1 - gradient.cx
);
gradient.ry = Math.max(
gradient.cy,
gradient.y1 - gradient.cy
);
}
break;
case 'closest-side':
case 'contain': // is equivalent to closest-side
if(m2[0] === 'circle'){
gradient.rx = gradient.ry = Math.min(
gradient.cx,
gradient.cy,
gradient.x1 - gradient.cx,
gradient.y1 - gradient.cy
);
} else { // ellipse
gradient.type = m2[0];
gradient.rx = Math.min(
gradient.cx,
gradient.x1 - gradient.cx
);
gradient.ry = Math.min(
gradient.cy,
gradient.y1 - gradient.cy
);
}
break;
// TODO: add support for "30px 40px" sizes (webkit only)
}
}
// color stops
m2 = m1[5].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\)(?:\s\d{1,3}(?:%|px))?)+/g);
if(m2){
m2Len = m2.length;
step = 1 / Math.max(m2Len - 1, 1);
for(i = 0; i < m2Len; i+=1){
m3 = m2[i].match(/((?:rgb|rgba)\(\d{1,3},\s\d{1,3},\s\d{1,3}(?:,\s[0-9\.]+)?\))\s*(\d{1,3})?(%|px)?/);
if(m3[2]){
stop = parseFloat(m3[2]);
if(m3[3] === '%'){
stop /= 100;
} else { // px - stupid opera
stop /= bounds.width;
}
} else {
stop = i * step;
}
gradient.colorStops.push({
color: m3[1],
stop: stop
});
}
}
break;
}
}
return gradient;
};
_html2canvas.Generate.Gradient = function(src, bounds) {
if(bounds.width === 0 || bounds.height === 0) {
return;
}
html2canvas.Generate.Gradient = function(src, bounds) {
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
tmp,
p0 = 0,
p1 = 0,
p2 = 0,
p3 = 0,
steps = [],
position,
i,
len,
lingrad,
increment,
p,
img;
gradient, grad, i, len;
canvas.width = bounds.width;
canvas.height = bounds.height;
function getColors(input) {
var j = -1,
color = '',
chr;
while( j++ < input.length ) {
chr = input.charAt( j );
if (chr === ')') {
color += chr;
steps.push( color );
color = '';
while (j++ < input.length && input.charAt( j ) !== ',') {
}
} else {
color += chr;
}
}
}
if ( tmp = src.match(/-webkit-linear-gradient\((.*)\)/) ) {
position = tmp[1].split( ",", 1 )[0];
getColors( tmp[1].substr( position.length + 2 ) );
position = position.split(' ');
for (p = 0; p < position.length; p+=1) {
switch(position[p]) {
case 'top':
p3 = bounds.height;
break;
case 'right':
p0 = bounds.width;
break;
case 'bottom':
p1 = bounds.height;
break;
case 'left':
p2 = bounds.width;
break;
}
// TODO: add support for multi defined background gradients
gradient = _html2canvas.Generate.parseGradient(src, bounds);
if(gradient) {
if(gradient.type === 'linear') {
grad = ctx.createLinearGradient(gradient.x0, gradient.y0, gradient.x1, gradient.y1);
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
try {
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
}
catch(e) {
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
}
}
} else if (tmp = src.match(/-webkit-gradient\(linear, (\d+)[%]{0,1} (\d+)[%]{0,1}, (\d+)[%]{0,1} (\d+)[%]{0,1}, from\((.*)\), to\((.*)\)\)/)) {
p0 = (tmp[1] * bounds.width) / 100;
p1 = (tmp[2] * bounds.height) / 100;
p2 = (tmp[3] * bounds.width) / 100;
p3 = (tmp[4] * bounds.height) / 100;
steps.push(tmp[5]);
steps.push(tmp[6]);
} else if (tmp = src.match(/-moz-linear-gradient\((\d+)[%]{0,1} (\d+)[%]{0,1}, (.*)\)/)) {
p0 = (tmp[1] * bounds.width) / 100;
p1 = (tmp[2] * bounds.width) / 100;
p2 = bounds.width - p0;
p3 = bounds.height - p1;
getColors( tmp[3] );
} else {
return;
ctx.fillStyle = grad;
ctx.fillRect(0, 0, bounds.width, bounds.height);
} else if(gradient.type === 'circle') {
grad = ctx.createRadialGradient(gradient.cx, gradient.cy, 0, gradient.cx, gradient.cy, gradient.rx);
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
try {
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
}
catch(e) {
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
}
}
ctx.fillStyle = grad;
ctx.fillRect(0, 0, bounds.width, bounds.height);
} else if(gradient.type === 'ellipse') {
// draw circle
var canvasRadial = document.createElement('canvas'),
ctxRadial = canvasRadial.getContext('2d'),
ri = Math.max(gradient.rx, gradient.ry),
di = ri * 2, imgRadial;
canvasRadial.width = canvasRadial.height = di;
grad = ctxRadial.createRadialGradient(gradient.rx, gradient.ry, 0, gradient.rx, gradient.ry, ri);
for (i = 0, len = gradient.colorStops.length; i < len; i+=1) {
try {
grad.addColorStop(gradient.colorStops[i].stop, gradient.colorStops[i].color);
}
catch(e) {
h2clog(['failed to add color stop: ', e, '; tried to add: ', gradient.colorStops[i], '; stop: ', i, '; in: ', src]);
}
}
ctxRadial.fillStyle = grad;
ctxRadial.fillRect(0, 0, di, di);
ctx.fillStyle = gradient.colorStops[i - 1].color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(canvasRadial, gradient.cx - gradient.rx, gradient.cy - gradient.ry, 2 * gradient.rx, 2 * gradient.ry);
}
}
lingrad = ctx.createLinearGradient( p0, p1, p2, p3 );
increment = 1 / (steps.length - 1);
for (i = 0, len = steps.length; i < len; i+=1) {
try {
lingrad.addColorStop(increment * i, steps[i]);
}
catch(e) {
html2canvas.log(['failed to add color stop: ', e, '; tried to add: ', steps[i], '; stop: ', i, '; in: ', src]);
}
}
ctx.fillStyle = lingrad;
// draw shapes
ctx.fillRect(0, 0, bounds.width,bounds.height);
return canvas;
};
img = new Image();
img.src = canvas.toDataURL();
return img;
}
html2canvas.Generate.ListAlpha = function(number) {
_html2canvas.Generate.ListAlpha = function(number) {
var tmp = "",
modulus;
do {
modulus = number % 26;
tmp = String.fromCharCode((modulus) + 64) + tmp;
number = number / 26;
}while((number*26) > 26);
return tmp;
}
html2canvas.Generate.ListRoman = function(number) {
do {
modulus = number % 26;
tmp = String.fromCharCode((modulus) + 64) + tmp;
number = number / 26;
}while((number*26) > 26);
return tmp;
};
_html2canvas.Generate.ListRoman = function(number) {
var romanArray = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"],
decimal = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1],
roman = "",
v,
len = romanArray.length;
if (number <= 0 || number >= 4000) {
return number;
if (number <= 0 || number >= 4000) {
return number;
}
for (v=0; v < len; v+=1) {
while (number >= decimal[v]) {
number -= decimal[v];
roman += romanArray[v];
}
while (number >= decimal[v]) {
number -= decimal[v];
roman += romanArray[v];
}
}
return roman;
}
};
})();

View File

@ -1,7 +0,0 @@
/**
@license html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
Released under MIT License
*/

File diff suppressed because it is too large Load Diff

View File

@ -1,338 +1,330 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
_html2canvas.Preload = function( options ) {
Released under MIT License
*/
var images = {
numLoaded: 0, // also failed are counted here
numFailed: 0,
numTotal: 0,
cleanupDone: false
},
pageOrigin,
methods,
i,
count = 0,
element = options.elements[0] || document.body,
doc = element.ownerDocument,
domImages = doc.images, // TODO probably should limit it to images present in the element only
imgLen = domImages.length,
link = doc.createElement("a"),
supportCORS = (function( img ){
return (img.crossOrigin !== undefined);
})(new Image()),
timeoutTimer;
link.href = window.location.href;
pageOrigin = link.protocol + link.host;
function isSameOrigin(url){
link.href = url;
link.href = link.href; // YES, BELIEVE IT OR NOT, that is required for IE9 - http://jsfiddle.net/niklasvh/2e48b/
var origin = link.protocol + link.host;
return (origin === pageOrigin);
}
function start(){
h2clog("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
if (!images.firstRun && images.numLoaded >= images.numTotal){
h2clog("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")");
if (typeof options.complete === "function"){
options.complete(images);
}
html2canvas.Preload = function(element, opts){
var options = {
proxy: "http://html2canvas.appspot.com/",
timeout: 0 // no timeout
},
images = {
numLoaded: 0, // also failed are counted here
numFailed: 0,
numTotal: 0,
cleanupDone: false
},
pageOrigin,
methods,
i,
count = 0,
doc = element.ownerDocument,
domImages = doc.images, // TODO probably should limit it to images present in the element only
imgLen = domImages.length,
link = doc.createElement("a"),
timeoutTimer;
link.href = window.location.href;
pageOrigin = link.protocol + link.host;
opts = opts || {};
options = html2canvas.Util.Extend(opts, options);
element = element || doc.body;
function isSameOrigin(url){
link.href = url;
var origin = link.protocol + link.host;
return ":" === origin || (origin === pageOrigin);
}
function start(){
html2canvas.log("html2canvas: start: images: " + images.numLoaded + " / " + images.numTotal + " (failed: " + images.numFailed + ")");
if (!images.firstRun && images.numLoaded >= images.numTotal){
/*
this.log('Finished loading '+this.imagesLoaded+' images, Started parsing');
this.bodyOverflow = document.getElementsByTagName('body')[0].style.overflow;
document.getElementsByTagName('body')[0].style.overflow = "hidden";
*/
if (typeof options.complete === "function"){
options.complete(images);
}
}
html2canvas.log("Finished loading images: # " + images.numTotal + " (failed: " + images.numFailed + ")");
}
// TODO modify proxy to serve images with CORS enabled, where available
function proxyGetImage(url, img, imageObj){
var callback_name,
scriptUrl = options.proxy,
script;
link.href = url;
url = link.href; // work around for pages with base href="" set - WARNING: this may change the url
callback_name = 'html2canvas_' + (count++);
imageObj.callbackname = callback_name;
if (scriptUrl.indexOf("?") > -1) {
scriptUrl += "&";
} else {
scriptUrl += "?";
}
function proxyGetImage(url, img){
var callback_name,
scriptUrl = options.proxy,
script,
imgObj = images[url];
scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;
script = doc.createElement("script");
link.href = url;
url = link.href; // work around for pages with base href="" set - WARNING: this may change the url -> so access imgObj from images map before changing that url!
callback_name = 'html2canvas_' + count;
imgObj.callbackname = callback_name;
if (scriptUrl.indexOf("?") > -1) {
scriptUrl += "&";
} else {
scriptUrl += "?";
}
scriptUrl += 'url=' + encodeURIComponent(url) + '&callback=' + callback_name;
window[callback_name] = function(a){
if (a.substring(0,6) === "error:"){
imgObj.succeeded = false;
images.numLoaded++;
images.numFailed++;
start();
} else {
img.onload = function(){
imgObj.succeeded = true;
images.numLoaded++;
start();
};
img.src = a;
}
window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
try {
delete window[callback_name]; // for all browser that support this
} catch(ex) {}
script.parentNode.removeChild(script);
script = null;
imgObj.callbackname = undefined;
};
count += 1;
script = doc.createElement("script");
script.setAttribute("src", scriptUrl);
script.setAttribute("type", "text/javascript");
imgObj.script = script;
window.document.body.appendChild(script);
/*
// enable xhr2 requests where available (no need for base64 / json)
$.ajax({
data:{
xhr2:false,
url:url
},
url: options.proxy,
dataType: "jsonp",
success: function(a){
if (a.substring(0,6) === "error:"){
images.splice(getIndex(images, url), 2);
start();
}else{
img.onload = function(){
imagesLoaded+=1;
start();
};
img.src = a;
}
},
error: function(){
images.splice(getIndex(images, url), 2);
start();
}
});
*/
}
function getImages (el) {
// if (!this.ignoreRe.test(el.nodeName)){
//
var contents = html2canvas.Util.Children(el),
i,
contentsLen = contents.length,
background_image,
src,
img,
elNodeType = false;
for (i = 0; i < contentsLen; i+=1 ){
// var ignRe = new RegExp("("+this.ignoreElements+")");
// if (!ignRe.test(element.nodeName)){
getImages(contents[i]);
// }
}
// }
try {
elNodeType = el.nodeType;
} catch (ex) {
elNodeType = false;
html2canvas.log("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
}
if (elNodeType === 1 || elNodeType === undefined){
background_image = html2canvas.Util.getCSS(el, 'backgroundImage');
if ( background_image && background_image !== "1" && background_image !== "none" ) {
// TODO add multi image background support
if (background_image.substring(0,7) === "-webkit" || background_image.substring(0,3) === "-o-" || background_image.substring(0,4) === "-moz") {
img = html2canvas.Generate.Gradient( background_image, html2canvas.Util.Bounds( el ) );
if ( img !== undefined ){
images[background_image] = { img: img, succeeded: true };
images.numTotal++;
images.numLoaded++;
start();
}
} else {
src = html2canvas.Util.backgroundImage(background_image.match(/data:image\/.*;base64,/i) ? background_image : background_image.split(",")[0]);
methods.loadImage(src);
}
/*
if (background_image && background_image !== "1" && background_image !== "none" && background_image.substring(0,7) !== "-webkit" && background_image.substring(0,3)!== "-o-" && background_image.substring(0,4) !== "-moz"){
// TODO add multi image background support
src = html2canvas.Util.backgroundImage(background_image.split(",")[0]);
methods.loadImage(src); */
}
}
}
methods = {
loadImage: function( src ) {
var img;
if ( src && images[src] === undefined ) {
if ( src.match(/data:image\/.*;base64,/i) ) {
//Base64 src
img = new Image();
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
images[src] = { img: img, succeeded: true };
images.numTotal++;
images.numLoaded++;
start();
}else if ( isSameOrigin( src ) ) {
img = new Image();
images[src] = { img: img };
images.numTotal++;
img.onload = function() {
images.numLoaded++;
images[src].succeeded = true;
start();
};
img.onerror = function() {
images.numLoaded++;
images.numFailed++;
images[src].succeeded = false;
start();
};
img.src = src;
}else if ( options.proxy ){
// console.log('b'+src);
img = new Image();
images[src] = { img: img };
images.numTotal++;
proxyGetImage( src, img );
}
}
},
cleanupDOM: function(cause) {
var img, src;
if (!images.cleanupDone) {
if (cause && typeof cause === "string") {
html2canvas.log("html2canvas: Cleanup because: " + cause);
} else {
html2canvas.log("html2canvas: Cleanup after timeout: " + options.timeout + " ms.");
}
for (src in images) {
if (images.hasOwnProperty(src)) {
img = images[src];
if (typeof img === "object" && img.callbackname && img.succeeded === undefined) {
// cancel proxy image request
window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
try {
delete window[img.callbackname]; // for all browser that support this
} catch(ex) {}
if (img.script && img.script.parentNode) {
img.script.setAttribute("src", "about:blank"); // try to cancel running request
img.script.parentNode.removeChild(img.script);
}
images.numLoaded++;
images.numFailed++;
html2canvas.log("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal);
}
}
}
// cancel any pending requests
if(window.stop !== undefined) {
window.stop();
} else if(document.execCommand !== undefined) {
document.execCommand("Stop", false);
}
if (document.close !== undefined) {
document.close();
}
images.cleanupDone = true;
if (!(cause && typeof cause === "string")) {
start();
}
}
},
renderingDone: function() {
if (timeoutTimer) {
window.clearTimeout(timeoutTimer);
}
}
window[callback_name] = function(a){
if (a.substring(0,6) === "error:"){
imageObj.succeeded = false;
images.numLoaded++;
images.numFailed++;
start();
} else {
setImageLoadHandlers(img, imageObj);
img.src = a;
}
window[callback_name] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
try {
delete window[callback_name]; // for all browser that support this
} catch(ex) {}
script.parentNode.removeChild(script);
script = null;
delete imageObj.script;
delete imageObj.callbackname;
};
if (options.timeout > 0) {
timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
script.setAttribute("type", "text/javascript");
script.setAttribute("src", scriptUrl);
imageObj.script = script;
window.document.body.appendChild(script);
}
function loadPseudoElement(element, type) {
var style = window.getComputedStyle(element, type),
content = style.content;
if (content.substr(0, 3) === 'url') {
methods.loadImage(_html2canvas.Util.parseBackgroundImage(content)[0].args[0]);
}
var startTime = (new Date()).getTime();
html2canvas.log('html2canvas: Preload starts: finding background-images');
images.firstRun = true;
loadBackgroundImages(style.backgroundImage, element);
}
getImages( element );
html2canvas.log('html2canvas: Preload: Finding images');
// load <img> images
for (i = 0; i < imgLen; i+=1){
methods.loadImage( domImages[i].getAttribute( "src" ) );
function loadPseudoElementImages(element) {
loadPseudoElement(element, ":before");
loadPseudoElement(element, ":after");
}
function loadGradientImage(backgroundImage, bounds) {
var img = _html2canvas.Generate.Gradient(backgroundImage, bounds);
if (img !== undefined){
images[backgroundImage] = {
img: img,
succeeded: true
};
images.numTotal++;
images.numLoaded++;
start();
}
images.firstRun = false;
html2canvas.log('html2canvas: Preload: Done.');
if ( images.numTotal === images.numLoaded ) {
start();
}
return methods;
};
}
function invalidBackgrounds(background_image) {
return (background_image && background_image.method && background_image.args && background_image.args.length > 0 );
}
function loadBackgroundImages(background_image, el) {
var bounds;
_html2canvas.Util.parseBackgroundImage(background_image).filter(invalidBackgrounds).forEach(function(background_image) {
if (background_image.method === 'url') {
methods.loadImage(background_image.args[0]);
} else if(background_image.method.match(/\-?gradient$/)) {
if(bounds === undefined) {
bounds = _html2canvas.Util.Bounds(el);
}
loadGradientImage(background_image.value, bounds);
}
});
}
function getImages (el) {
var elNodeType = false;
// Firefox fails with permission denied on pages with iframes
try {
_html2canvas.Util.Children(el).forEach(function(img) {
getImages(img);
});
}
catch( e ) {}
try {
elNodeType = el.nodeType;
} catch (ex) {
elNodeType = false;
h2clog("html2canvas: failed to access some element's nodeType - Exception: " + ex.message);
}
if (elNodeType === 1 || elNodeType === undefined) {
loadPseudoElementImages(el);
try {
loadBackgroundImages(_html2canvas.Util.getCSS(el, 'backgroundImage'), el);
} catch(e) {
h2clog("html2canvas: failed to get background-image - Exception: " + e.message);
}
loadBackgroundImages(el);
}
}
function setImageLoadHandlers(img, imageObj) {
img.onload = function() {
if ( imageObj.timer !== undefined ) {
// CORS succeeded
window.clearTimeout( imageObj.timer );
}
images.numLoaded++;
imageObj.succeeded = true;
img.onerror = img.onload = null;
start();
};
img.onerror = function() {
if (img.crossOrigin === "anonymous") {
// CORS failed
window.clearTimeout( imageObj.timer );
// let's try with proxy instead
if ( options.proxy ) {
var src = img.src;
img = new Image();
imageObj.img = img;
img.src = src;
proxyGetImage( img.src, img, imageObj );
return;
}
}
images.numLoaded++;
images.numFailed++;
imageObj.succeeded = false;
img.onerror = img.onload = null;
start();
};
}
methods = {
loadImage: function( src ) {
var img, imageObj;
if ( src && images[src] === undefined ) {
img = new Image();
if ( src.match(/data:image\/.*;base64,/i) ) {
img.src = src.replace(/url\(['"]{0,}|['"]{0,}\)$/ig, '');
imageObj = images[src] = {
img: img
};
images.numTotal++;
setImageLoadHandlers(img, imageObj);
} else if ( isSameOrigin( src ) || options.allowTaint === true ) {
imageObj = images[src] = {
img: img
};
images.numTotal++;
setImageLoadHandlers(img, imageObj);
img.src = src;
} else if ( supportCORS && !options.allowTaint && options.useCORS ) {
// attempt to load with CORS
img.crossOrigin = "anonymous";
imageObj = images[src] = {
img: img
};
images.numTotal++;
setImageLoadHandlers(img, imageObj);
img.src = src;
// work around for https://bugs.webkit.org/show_bug.cgi?id=80028
img.customComplete = function () {
if (!this.img.complete) {
this.timer = window.setTimeout(this.img.customComplete, 100);
} else {
this.img.onerror();
}
}.bind(imageObj);
img.customComplete();
} else if ( options.proxy ) {
imageObj = images[src] = {
img: img
};
images.numTotal++;
proxyGetImage( src, img, imageObj );
}
}
},
cleanupDOM: function(cause) {
var img, src;
if (!images.cleanupDone) {
if (cause && typeof cause === "string") {
h2clog("html2canvas: Cleanup because: " + cause);
} else {
h2clog("html2canvas: Cleanup after timeout: " + options.timeout + " ms.");
}
for (src in images) {
if (images.hasOwnProperty(src)) {
img = images[src];
if (typeof img === "object" && img.callbackname && img.succeeded === undefined) {
// cancel proxy image request
window[img.callbackname] = undefined; // to work with IE<9 // NOTE: that the undefined callback property-name still exists on the window object (for IE<9)
try {
delete window[img.callbackname]; // for all browser that support this
} catch(ex) {}
if (img.script && img.script.parentNode) {
img.script.setAttribute("src", "about:blank"); // try to cancel running request
img.script.parentNode.removeChild(img.script);
}
images.numLoaded++;
images.numFailed++;
h2clog("html2canvas: Cleaned up failed img: '" + src + "' Steps: " + images.numLoaded + " / " + images.numTotal);
}
}
}
// cancel any pending requests
if(window.stop !== undefined) {
window.stop();
} else if(document.execCommand !== undefined) {
document.execCommand("Stop", false);
}
if (document.close !== undefined) {
document.close();
}
images.cleanupDone = true;
if (!(cause && typeof cause === "string")) {
start();
}
}
},
renderingDone: function() {
if (timeoutTimer) {
window.clearTimeout(timeoutTimer);
}
}
};
if (options.timeout > 0) {
timeoutTimer = window.setTimeout(methods.cleanupDOM, options.timeout);
}
h2clog('html2canvas: Preload starts: finding background-images');
images.firstRun = true;
getImages(element);
h2clog('html2canvas: Preload: Finding images');
// load <img> images
for (i = 0; i < imgLen; i+=1){
methods.loadImage( domImages[i].getAttribute( "src" ) );
}
images.firstRun = false;
h2clog('html2canvas: Preload: Done.');
if ( images.numTotal === images.numLoaded ) {
start();
}
return methods;
};

View File

@ -1,43 +1,122 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
function h2cRenderContext(width, height) {
var storage = [];
return {
storage: storage,
width: width,
height: height,
clip: function() {
storage.push({
type: "function",
name: "clip",
'arguments': arguments
});
},
translate: function() {
storage.push({
type: "function",
name: "translate",
'arguments': arguments
});
},
fill: function() {
storage.push({
type: "function",
name: "fill",
'arguments': arguments
});
},
save: function() {
storage.push({
type: "function",
name: "save",
'arguments': arguments
});
},
restore: function() {
storage.push({
type: "function",
name: "restore",
'arguments': arguments
});
},
fillRect: function () {
storage.push({
type: "function",
name: "fillRect",
'arguments': arguments
});
},
createPattern: function() {
storage.push({
type: "function",
name: "createPattern",
'arguments': arguments
});
},
drawShape: function() {
Released under MIT License
*/
html2canvas.canvasContext = function (width, height) {
var storage = [];
return {
storage: storage,
width: width,
height: height,
fillRect: function () {
storage.push({
type: "function",
name: "fillRect",
'arguments': arguments
});
var shape = [];
storage.push({
type: "function",
name: "drawShape",
'arguments': shape
});
return {
moveTo: function() {
shape.push({
name: "moveTo",
'arguments': arguments
});
},
drawImage: function () {
storage.push({
type: "function",
name: "drawImage",
'arguments': arguments
});
lineTo: function() {
shape.push({
name: "lineTo",
'arguments': arguments
});
},
fillText: function () {
storage.push({
type: "function",
name: "fillText",
'arguments': arguments
});
arcTo: function() {
shape.push({
name: "arcTo",
'arguments': arguments
});
},
setVariable: function (variable, value) {
storage.push({
type: "variable",
name: variable,
'arguments': value
});
bezierCurveTo: function() {
shape.push({
name: "bezierCurveTo",
'arguments': arguments
});
},
quadraticCurveTo: function() {
shape.push({
name: "quadraticCurveTo",
'arguments': arguments
});
}
};
};
};
},
drawImage: function () {
storage.push({
type: "function",
name: "drawImage",
'arguments': arguments
});
},
fillText: function () {
storage.push({
type: "function",
name: "fillText",
'arguments': arguments
});
},
setVariable: function (variable, value) {
storage.push({
type: "variable",
name: variable,
'arguments': value
});
}
};
}

View File

@ -1,394 +1,58 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
_html2canvas.Renderer = function(parseQueue, options){
Released under MIT License
*/
html2canvas.Renderer = function(parseQueue, opts){
function createRenderQueue(parseQueue) {
var queue = [];
var sortZ = function(zStack){
var subStacks = [],
stackValues = [];
var options = {
"width": null,
"height": null,
"renderer": "canvas"
},
queue = [],
canvas,
doc = document;
options = html2canvas.Util.Extend(opts, options);
function sortZ(zStack){
var subStacks = [],
stackValues = [],
zStackChildren = zStack.children,
s,
i,
stackLen,
zValue,
zLen,
stackChild,
b,
subStackLen;
for (s = 0, zLen = zStackChildren.length; s < zLen; s+=1){
stackChild = zStackChildren[s];
if (stackChild.children && stackChild.children.length > 0){
subStacks.push(stackChild);
stackValues.push(stackChild.zindex);
}else{
queue.push(stackChild);
}
zStack.children.forEach(function(stackChild) {
if (stackChild.children && stackChild.children.length > 0){
subStacks.push(stackChild);
stackValues.push(stackChild.zindex);
} else {
queue.push(stackChild);
}
stackValues.sort(function(a, b) {
return a - b;
});
stackValues.sort(function(a, b) {
return a - b;
});
stackValues.forEach(function(zValue) {
var index;
subStacks.some(function(stack, i){
index = i;
return (stack.zindex === zValue);
});
for (i = 0, stackLen = stackValues.length; i < stackLen; i+=1){
zValue = stackValues[i];
for (b = 0, subStackLen = subStacks.length; b <= subStackLen; b+=1){
if (subStacks[b].zindex === zValue){
stackChild = subStacks.splice(b, 1);
sortZ(stackChild[0]);
break;
}
}
}
sortZ(subStacks.splice(index, 1)[0]);
});
};
sortZ(parseQueue.zIndex);
return queue;
}
function getRenderer(rendererName) {
var renderer;
if (typeof options.renderer === "string" && _html2canvas.Renderer[rendererName] !== undefined) {
renderer = _html2canvas.Renderer[rendererName](options);
} else if (typeof rendererName === "function") {
renderer = rendererName(options);
} else {
throw new Error("Unknown renderer");
}
function canvasRenderer(zStack){
sortZ(zStack.zIndex);
var ctx = canvas.getContext("2d"),
storageContext,
i,
queueLen,
a,
storageLen,
renderItem,
fstyle;
canvas.width = options.width || zStack.ctx.width;
canvas.height = options.height || zStack.ctx.height;
fstyle = ctx.fillStyle;
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = fstyle;
for (i = 0, queueLen = queue.length; i < queueLen; i+=1){
storageContext = queue.splice(0, 1)[0];
storageContext.canvasPosition = storageContext.canvasPosition || {};
//this.canvasRenderContext(storageContext,parentctx);
// set common settings for canvas
ctx.textBaseline = "bottom";
if (storageContext.clip){
ctx.save();
ctx.beginPath();
// console.log(storageContext);
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
ctx.clip();
}
if (storageContext.ctx.storage){
for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){
renderItem = storageContext.ctx.storage[a];
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") {
// console.log(renderItem.arguments[0]);
ctx.fillText(renderItem['arguments'][0],renderItem['arguments'][1],renderItem['arguments'][2]);
}else if(renderItem.name === "drawImage") {
// console.log(renderItem);
// console.log(renderItem.arguments[0].width);
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
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]
);
}
}
break;
default:
}
}
}
if (storageContext.clip){
ctx.restore();
}
}
html2canvas.log("html2canvas: Renderer: Canvas renderer done - returning canvas obj");
// this.canvasRenderStorage(queue,this.ctx);
return canvas;
if ( typeof renderer !== "function" ) {
throw new Error("Invalid renderer defined");
}
return renderer;
}
function svgRenderer(zStack){
sortZ(zStack.zIndex);
var svgNS = "http://www.w3.org/2000/svg",
svg = doc.createElementNS(svgNS, "svg"),
xlinkNS = "http://www.w3.org/1999/xlink",
defs = doc.createElementNS(svgNS, "defs"),
i,
a,
queueLen,
storageLen,
storageContext,
renderItem,
el,
settings = {},
text,
fontStyle,
clipId = 0;
svg.setAttribute("version", "1.1");
svg.setAttribute("baseProfile", "full");
svg.setAttribute("viewBox", "0 0 " + Math.max(zStack.ctx.width, options.width) + " " + Math.max(zStack.ctx.height, options.height));
svg.setAttribute("width", Math.max(zStack.ctx.width, options.width) + "px");
svg.setAttribute("height", Math.max(zStack.ctx.height, options.height) + "px");
svg.setAttribute("preserveAspectRatio", "none");
svg.appendChild(defs);
for (i = 0, queueLen = queue.length; i < queueLen; i+=1){
storageContext = queue.splice(0, 1)[0];
storageContext.canvasPosition = storageContext.canvasPosition || {};
//this.canvasRenderContext(storageContext,parentctx);
/*
if (storageContext.clip){
ctx.save();
ctx.beginPath();
// console.log(storageContext);
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
ctx.clip();
}*/
if (storageContext.ctx.storage){
for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){
renderItem = storageContext.ctx.storage[a];
switch(renderItem.type){
case "variable":
settings[renderItem.name] = renderItem['arguments'];
break;
case "function":
if (renderItem.name === "fillRect") {
el = doc.createElementNS(svgNS, "rect");
el.setAttribute("x", renderItem['arguments'][0]);
el.setAttribute("y", renderItem['arguments'][1]);
el.setAttribute("width", renderItem['arguments'][2]);
el.setAttribute("height", renderItem['arguments'][3]);
el.setAttribute("fill", settings.fillStyle);
svg.appendChild(el);
} else if(renderItem.name === "fillText") {
el = doc.createElementNS(svgNS, "text");
fontStyle = settings.font.split(" ");
el.style.fontVariant = fontStyle.splice(0, 1)[0];
el.style.fontWeight = fontStyle.splice(0, 1)[0];
el.style.fontStyle = fontStyle.splice(0, 1)[0];
el.style.fontSize = fontStyle.splice(0, 1)[0];
el.setAttribute("x", renderItem['arguments'][1]);
el.setAttribute("y", renderItem['arguments'][2] - (parseInt(el.style.fontSize, 10) + 3));
el.setAttribute("fill", settings.fillStyle);
// TODO get proper baseline
el.style.dominantBaseline = "text-before-edge";
el.style.fontFamily = fontStyle.join(" ");
text = doc.createTextNode(renderItem['arguments'][0]);
el.appendChild(text);
svg.appendChild(el);
} else if(renderItem.name === "drawImage") {
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
// TODO check whether even any clipping is necessary for this particular image
el = doc.createElementNS(svgNS, "clipPath");
el.setAttribute("id", "clipId" + clipId);
text = doc.createElementNS(svgNS, "rect");
text.setAttribute("x", renderItem['arguments'][5] );
text.setAttribute("y", renderItem['arguments'][6]);
text.setAttribute("width", renderItem['arguments'][3]);
text.setAttribute("height", renderItem['arguments'][4]);
el.appendChild(text);
defs.appendChild(el);
el = doc.createElementNS(svgNS, "image");
el.setAttributeNS(xlinkNS, "xlink:href", renderItem['arguments'][0].src);
el.setAttribute("width", renderItem['arguments'][0].width);
el.setAttribute("height", renderItem['arguments'][0].height);
el.setAttribute("x", renderItem['arguments'][5] - renderItem['arguments'][1]);
el.setAttribute("y", renderItem['arguments'][6] - renderItem['arguments'][2]);
el.setAttribute("clip-path", "url(#clipId" + clipId + ")");
// el.setAttribute("xlink:href", );
el.setAttribute("preserveAspectRatio", "none");
svg.appendChild(el);
clipId += 1;
/*
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]
);
*/
}
}
break;
default:
}
}
}
/*
if (storageContext.clip){
ctx.restore();
}
*/
}
html2canvas.log("html2canvas: Renderer: SVG Renderer done - returning SVG DOM obj");
return svg;
}
//this.each(this.opts.renderOrder.split(" "),function(i,renderer){
//options.renderer = "svg";
switch(options.renderer.toLowerCase()){
case "canvas":
canvas = doc.createElement('canvas');
if (canvas.getContext){
html2canvas.log("html2canvas: Renderer: using canvas renderer");
return canvasRenderer(parseQueue);
}
break;
case "svg":
if (doc.createElementNS){
html2canvas.log("html2canvas: Renderer: using SVG renderer");
return svgRenderer(parseQueue);
}
break;
}
//});
return this;
return getRenderer(options.renderer)(parseQueue, options, document, createRenderQueue(parseQueue), _html2canvas);
};

63
src/Support.js Normal file
View File

@ -0,0 +1,63 @@
_html2canvas.Util.Support = function (options, doc) {
function supportSVGRendering() {
var img = new Image(),
canvas = doc.createElement("canvas"),
ctx = (canvas.getContext === undefined) ? false : canvas.getContext("2d");
if (ctx === false) {
return false;
}
canvas.width = canvas.height = 10;
img.src = [
"data:image/svg+xml,",
"<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'>",
"<foreignObject width='10' height='10'>",
"<div xmlns='http://www.w3.org/1999/xhtml' style='width:10;height:10;'>",
"sup",
"</div>",
"</foreignObject>",
"</svg>"
].join("");
try {
ctx.drawImage(img, 0, 0);
canvas.toDataURL();
} catch(e) {
return false;
}
h2clog('html2canvas: Parse: SVG powered rendering available');
return true;
}
// Test whether we can use ranges to measure bounding boxes
// Opera doesn't provide valid bounds.height/bottom even though it supports the method.
function supportRangeBounds() {
var r, testElement, rangeBounds, rangeHeight, support = false;
if (doc.createRange) {
r = doc.createRange();
if (r.getBoundingClientRect) {
testElement = doc.createElement('boundtest');
testElement.style.height = "123px";
testElement.style.display = "block";
doc.body.appendChild(testElement);
r.selectNode(testElement);
rangeBounds = r.getBoundingClientRect();
rangeHeight = rangeBounds.height;
if (rangeHeight === 123) {
support = true;
}
doc.body.removeChild(testElement);
}
}
return support;
}
return {
rangeBounds: supportRangeBounds(),
svgRendering: options.svgRendering && supportSVGRendering()
};
};

View File

@ -1,7 +1,81 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
window.html2canvas = function(elements, opts) {
elements = (elements.length) ? elements : [elements];
var queue,
canvas,
options = {
// general
logging: false,
elements: elements,
background: "#fff",
Released under MIT License
*/
// preload options
proxy: null,
timeout: 0, // no timeout
useCORS: false, // try to load images as CORS (where available), before falling back to proxy
allowTaint: false, // whether to allow images to taint the canvas, won't need proxy if set to true
// parse options
svgRendering: false, // use svg powered rendering where available (FF11+)
ignoreElements: "IFRAME|OBJECT|PARAM",
useOverflow: true,
letterRendering: false,
chinese: false,
// render options
width: null,
height: null,
taintTest: true, // do a taint test with all images before applying to canvas
renderer: "Canvas"
};
options = _html2canvas.Util.Extend(opts, options);
_html2canvas.logging = options.logging;
options.complete = function( images ) {
if (typeof options.onpreloaded === "function") {
if ( options.onpreloaded( images ) === false ) {
return;
}
}
queue = _html2canvas.Parse( images, options );
if (typeof options.onparsed === "function") {
if ( options.onparsed( queue ) === false ) {
return;
}
}
canvas = _html2canvas.Renderer( queue, options );
if (typeof options.onrendered === "function") {
options.onrendered( canvas );
}
};
// for pages without images, we still want this to be async, i.e. return methods before executing
window.setTimeout( function(){
_html2canvas.Preload( options );
}, 0 );
return {
render: function( queue, opts ) {
return _html2canvas.Renderer( queue, _html2canvas.Util.Extend(opts, options) );
},
parse: function( images, opts ) {
return _html2canvas.Parse( images, _html2canvas.Util.Extend(opts, options) );
},
preload: function( opts ) {
return _html2canvas.Preload( _html2canvas.Util.Extend(opts, options) );
},
log: h2clog
};
};
window.html2canvas.log = h2clog; // for renderers
window.html2canvas.Renderer = {
Canvas: undefined // We are assuming this will be used
};

View File

@ -1,74 +0,0 @@
(function() {
/* options, customize to your needs */
var server = '//html2canvas.hertzen.com/build',
proxy = '//html2canvas.appspot.com',
debug = false,
profile = false;
//DEBUG: server = 'http://localhost/html2canvas'; debug = true;
var debugFiles = [
'external/jquery-1.6.2.min',
'src/Core',
'src/Generate',
'src/Parse',
'src/Preload',
'src/Queue',
'src/Renderer',
'src/plugins/jquery.plugin.html2canvas'
],
relFiles = [
'//code.jquery.com/jquery-1.6.4.js',
'html2canvas',
'jquery.plugin.html2canvas'
],
i = 0, el = null;
var loader = {
index: 0,
head: document.getElementsByTagName('head')[0],
statusline: document.createElement('div'),
files: (debug ? debugFiles : relFiles),
onload: function () {
var _ = this;
if (_.index < _.files.length) {
var el = document.createElement('script');
el.type = 'text/javascript';
el.onload = function() {
_.onload();
};
el.onerror = function() {
_.statusline.style.color = 'red';
_.statusline.innerHTML = _.statusline.innerHTML + ' failed';
_.statusline.onclick = function() {
_.statusline.parentNode.removeChild(_.statusline);
};
};
if (_.files[_.index].substr(0, 2) === '//') {
el.src = _.files[_.index];
}
else {
el.src = server + '/' + _.files[_.index] + '.js';
}
_.head.appendChild(el);
++_.index;
_.statusline.innerHTML = 'html2canvas: loading "' + el.src + '" ' + _.index + ' / ' + _.files.length + '...';
}
else {
_.statusline.parentNode.removeChild(_.statusline);
delete _.statusline;
$(document.documentElement).html2canvas({
logging: debug,
profile: profile
});
}
}
}, statusline = loader.statusline;
statusline.style.position = 'fixed';
statusline.style.bottom = '0px';
statusline.style.right = '20px';
statusline.style.backgroundColor = 'white';
statusline.style.border = '1px solid black';
statusline.style.borderBottomWidth = '0px';
statusline.style.padding = '2px 5px';
statusline.style.zIndex = 9999999;
document.body.appendChild(statusline);
loader.onload();
}());

View File

@ -1,65 +0,0 @@
/*
* jQuery helper plugin for examples and tests
*/
(function( $ ){
$.fn.html2canvas = function(options) {
if (options && options.profile && window.console && window.console.profile) {
console.profile();
}
var date = new Date(),
$message = null,
timeoutTimer = false,
timer = date.getTime();
html2canvas.logging = options && options.logging;
html2canvas.Preload(this[0], $.extend({
complete: function(images){
var queue = html2canvas.Parse(this[0], images, options),
$canvas = $(html2canvas.Renderer(queue, options)),
finishTime = new Date();
if (options && options.profile && window.console && window.console.profileEnd) {
console.profileEnd();
}
$canvas.css({ position: 'absolute', left: 0, top: 0 }).appendTo(document.body);
$canvas.siblings().toggle();
$(window).click(function(){
$canvas.toggle().siblings().toggle();
throwMessage("Canvas Render " + ($canvas.is(':visible') ? "visible" : "hidden"));
});
throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)) + " ms<br />",4000);
}
}, options));
function throwMessage(msg,duration){
window.clearTimeout(timeoutTimer);
timeoutTimer = window.setTimeout(function(){
$message.fadeOut(function(){
$message.remove();
$message = null;
});
},duration || 2000);
if ($message)
$message.remove();
$message = $('<div />').html(msg).css({
margin:0,
padding:10,
background: "#000",
opacity:0.7,
position:"fixed",
top:10,
right:10,
fontFamily: 'Tahoma',
color:'#fff',
fontSize:12,
borderRadius:12,
width:'auto',
height:'auto',
textAlign:'center',
textDecoration:'none',
display:'none'
}).appendTo(document.body).fadeIn();
html2canvas.log(msg);
}
};
})( jQuery );

138
src/renderers/Canvas.js Normal file
View File

@ -0,0 +1,138 @@
_html2canvas.Renderer.Canvas = function(options) {
options = options || {};
var doc = document,
safeImages = [],
testCanvas = document.createElement("canvas"),
testctx = testCanvas.getContext("2d"),
canvas = options.canvas || doc.createElement('canvas');
function createShape(ctx, args) {
ctx.beginPath();
args.forEach(function(arg) {
ctx[arg.name].apply(ctx, arg['arguments']);
});
ctx.closePath();
}
function safeImage(item) {
if (safeImages.indexOf(item['arguments'][0].src ) === -1) {
testctx.drawImage(item['arguments'][0], 0, 0);
try {
testctx.getImageData(0, 0, 1, 1);
} catch(e) {
testCanvas = doc.createElement("canvas");
testctx = testCanvas.getContext("2d");
return false;
}
safeImages.push(item['arguments'][0].src);
}
return true;
}
function isTransparent(backgroundColor) {
return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
}
function renderItem(ctx, item) {
switch(item.type){
case "variable":
ctx[item.name] = item['arguments'];
break;
case "function":
if (item.name === "createPattern") {
if (item['arguments'][0].width > 0 && item['arguments'][0].height > 0) {
try {
ctx.fillStyle = ctx.createPattern(item['arguments'][0], "repeat");
}
catch(e) {
h2clog("html2canvas: Renderer: Error creating pattern", e.message);
}
}
} else if (item.name === "drawShape") {
createShape(ctx, item['arguments']);
} else if (item.name === "drawImage") {
if (item['arguments'][8] > 0 && item['arguments'][7] > 0) {
if (!options.taintTest || (options.taintTest && safeImage(item))) {
ctx.drawImage.apply( ctx, item['arguments'] );
}
}
} else {
ctx[item.name].apply(ctx, item['arguments']);
}
break;
}
}
return function(zStack, options, doc, queue, _html2canvas) {
var ctx = canvas.getContext("2d"),
storageContext,
i,
queueLen,
newCanvas,
bounds,
fstyle;
canvas.width = canvas.style.width = options.width || zStack.ctx.width;
canvas.height = canvas.style.height = options.height || zStack.ctx.height;
fstyle = ctx.fillStyle;
ctx.fillStyle = (isTransparent(zStack.backgroundColor) && options.background !== undefined) ? options.background : zStack.backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = fstyle;
if ( options.svgRendering && zStack.svgRender !== undefined ) {
// TODO: enable async rendering to support this
ctx.drawImage( zStack.svgRender, 0, 0 );
} else {
for ( i = 0, queueLen = queue.length; i < queueLen; i+=1 ) {
storageContext = queue.splice(0, 1)[0];
storageContext.canvasPosition = storageContext.canvasPosition || {};
// set common settings for canvas
ctx.textBaseline = "bottom";
if (storageContext.clip){
ctx.save();
ctx.beginPath();
// console.log(storageContext);
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
ctx.clip();
}
if (storageContext.ctx.storage) {
storageContext.ctx.storage.forEach(renderItem.bind(null, ctx));
}
if (storageContext.clip){
ctx.restore();
}
}
}
h2clog("html2canvas: Renderer: Canvas renderer done - returning canvas obj");
queueLen = options.elements.length;
if (queueLen === 1) {
if (typeof options.elements[0] === "object" && options.elements[0].nodeName !== "BODY") {
// crop image to the bounds of selected (single) element
bounds = _html2canvas.Util.Bounds(options.elements[0]);
newCanvas = doc.createElement('canvas');
newCanvas.width = bounds.width;
newCanvas.height = bounds.height;
ctx = newCanvas.getContext("2d");
ctx.drawImage(canvas, bounds.left, bounds.top, bounds.width, bounds.height, 0, 0, bounds.width, bounds.height);
canvas = null;
return newCanvas;
}
}
return canvas;
};
};

206
src/renderers/SVG.js Normal file
View File

@ -0,0 +1,206 @@
/*
html2canvas @VERSION@ <http://html2canvas.hertzen.com>
Copyright (c) 2011 Niklas von Hertzen. All rights reserved.
http://www.twitter.com/niklasvh
Released under MIT License
*/
// WARNING THIS file is outdated, and hasn't been tested in quite a while
_html2canvas.Renderer.SVG = function( options ) {
options = options || {};
var doc = document,
svgNS = "http://www.w3.org/2000/svg",
svg = doc.createElementNS(svgNS, "svg"),
xlinkNS = "http://www.w3.org/1999/xlink",
defs = doc.createElementNS(svgNS, "defs"),
i,
a,
queueLen,
storageLen,
storageContext,
renderItem,
el,
settings = {},
text,
fontStyle,
clipId = 0,
methods;
methods = {
_create: function( zStack, options, doc, queue, _html2canvas ) {
svg.setAttribute("version", "1.1");
svg.setAttribute("baseProfile", "full");
svg.setAttribute("viewBox", "0 0 " + Math.max(zStack.ctx.width, options.width) + " " + Math.max(zStack.ctx.height, options.height));
svg.setAttribute("width", Math.max(zStack.ctx.width, options.width) + "px");
svg.setAttribute("height", Math.max(zStack.ctx.height, options.height) + "px");
svg.setAttribute("preserveAspectRatio", "none");
svg.appendChild(defs);
for (i = 0, queueLen = queue.length; i < queueLen; i+=1){
storageContext = queue.splice(0, 1)[0];
storageContext.canvasPosition = storageContext.canvasPosition || {};
//this.canvasRenderContext(storageContext,parentctx);
/*
if (storageContext.clip){
ctx.save();
ctx.beginPath();
// console.log(storageContext);
ctx.rect(storageContext.clip.left, storageContext.clip.top, storageContext.clip.width, storageContext.clip.height);
ctx.clip();
}*/
if (storageContext.ctx.storage){
for (a = 0, storageLen = storageContext.ctx.storage.length; a < storageLen; a+=1){
renderItem = storageContext.ctx.storage[a];
switch(renderItem.type){
case "variable":
settings[renderItem.name] = renderItem['arguments'];
break;
case "function":
if (renderItem.name === "fillRect") {
el = doc.createElementNS(svgNS, "rect");
el.setAttribute("x", renderItem['arguments'][0]);
el.setAttribute("y", renderItem['arguments'][1]);
el.setAttribute("width", renderItem['arguments'][2]);
el.setAttribute("height", renderItem['arguments'][3]);
el.setAttribute("fill", settings.fillStyle);
svg.appendChild(el);
} else if(renderItem.name === "fillText") {
el = doc.createElementNS(svgNS, "text");
fontStyle = settings.font.split(" ");
el.style.fontVariant = fontStyle.splice(0, 1)[0];
el.style.fontWeight = fontStyle.splice(0, 1)[0];
el.style.fontStyle = fontStyle.splice(0, 1)[0];
el.style.fontSize = fontStyle.splice(0, 1)[0];
el.setAttribute("x", renderItem['arguments'][1]);
el.setAttribute("y", renderItem['arguments'][2] - (parseInt(el.style.fontSize, 10) + 3));
el.setAttribute("fill", settings.fillStyle);
// TODO get proper baseline
el.style.dominantBaseline = "text-before-edge";
el.style.fontFamily = fontStyle.join(" ");
text = doc.createTextNode(renderItem['arguments'][0]);
el.appendChild(text);
svg.appendChild(el);
} else if(renderItem.name === "drawImage") {
if (renderItem['arguments'][8] > 0 && renderItem['arguments'][7]){
// TODO check whether even any clipping is necessary for this particular image
el = doc.createElementNS(svgNS, "clipPath");
el.setAttribute("id", "clipId" + clipId);
text = doc.createElementNS(svgNS, "rect");
text.setAttribute("x", renderItem['arguments'][5] );
text.setAttribute("y", renderItem['arguments'][6]);
text.setAttribute("width", renderItem['arguments'][3]);
text.setAttribute("height", renderItem['arguments'][4]);
el.appendChild(text);
defs.appendChild(el);
el = doc.createElementNS(svgNS, "image");
el.setAttributeNS(xlinkNS, "xlink:href", renderItem['arguments'][0].src);
el.setAttribute("width", renderItem['arguments'][7]);
el.setAttribute("height", renderItem['arguments'][8]);
el.setAttribute("x", renderItem['arguments'][5]);
el.setAttribute("y", renderItem['arguments'][6]);
el.setAttribute("clip-path", "url(#clipId" + clipId + ")");
// el.setAttribute("xlink:href", );
el.setAttribute("preserveAspectRatio", "none");
svg.appendChild(el);
clipId += 1;
/*
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]
);
*/
}
}
break;
default:
}
}
}
/*
if (storageContext.clip){
ctx.restore();
}
*/
}
h2clog("html2canvas: Renderer: SVG Renderer done - returning SVG DOM obj");
return svg;
}
};
return methods;
};

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

46
tests/assets/image.svg Normal file
View File

@ -0,0 +1,46 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg" height="252.89000pt" width="493.28000pt" version="1.0" y="0.00000000" x="0.00000000" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient id="lg0">
<stop style="stop-color:#ff0000;stop-opacity:1.0000000" offset="0.00000000"/>
<stop style="stop-color:#00ff00;stop-opacity:1.0000000" offset="0.50000000"/>
<stop style="stop-color:#0000ff;stop-opacity:1.0000000" offset="1.0000000"/>
</linearGradient>
<linearGradient id="lg1">
<stop style="stop-color:#ff0000;stop-opacity:0.27450982" offset="0.00000000"/>
<stop style="stop-color:#ff0000;stop-opacity:1.0000000" offset="1.0000000"/>
</linearGradient>
<radialGradient id="rd0" fx="550.28571" fy="155.11731" xlink:href="#lg1" gradientUnits="userSpaceOnUse" cy="155.11731" cx="550.28571" gradientTransform="matrix(0.652228,-1.522906,1.403595,0.601129,-26.34767,869.2927)" r="127.00000"/>
<radialGradient id="rd1" fx="492.85715" fy="379.50504" xlink:href="#lg3" gradientUnits="userSpaceOnUse" cy="379.50504" cx="492.85715" gradientTransform="matrix(0.944964,4.150569e-2,-4.340623e-2,0.988234,43.59757,-15.99113)" r="184.96443"/>
<radialGradient id="rd2" fx="449.12918" fy="345.23175" xlink:href="#lg2" gradientUnits="userSpaceOnUse" cy="345.23175" cx="449.12918" gradientTransform="matrix(1.06455,-4.457048e-3,4.186833e-3,1.000012,-30.43703,1.997764)" r="184.96443"/>
<linearGradient id="lg2">
<stop style="stop-color:#fa4;stop-opacity:1" offset="0"/>
<stop style="stop-color:#c3791f;stop-opacity:1" offset="0.5"/>
<stop style="stop-color:#935000;stop-opacity:1" offset="1"/>
</linearGradient>
<linearGradient id="lg3">
<stop style="stop-color:black;stop-opacity:1" offset="0"/>
<stop style="stop-color:black;stop-opacity:1" offset="0.5"/>
<stop style="stop-color:black;stop-opacity:1" offset="0.75"/>
<stop style="stop-color:black;stop-opacity:0.72164947" offset="0.875"/>
<stop style="stop-color:black;stop-opacity:0.50515461" offset="0.9375"/>
<stop style="stop-color:black;stop-opacity:0.3298969" offset="0.96875"/>
<stop style="stop-color:black;stop-opacity:0" offset="1"/>
</linearGradient>
</defs>
<path d="M300 252.36218C300 307.59065 255.22847 352.36218 200 352.36218 144.77153 352.36218 100 307.59065 100 252.36218 100 197.13371 144.77153 152.36218 200 152.36218 255.22847 152.36218 300 197.13371 300 252.36218L300 252.36218z" style="fill:#00ffff;fill-opacity:0.49999997;fill-rule:evenodd;stroke:#00ffff;stroke-width:4.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" transform="translate(-91.79890,-143.8324)"/>
<path d="M500 252.36218C500 307.59065 455.22847 352.36218 400 352.36218 344.77153 352.36218 300 307.59065 300 252.36218 300 197.13371 344.77153 152.36218 400 152.36218 455.22847 152.36218 500 197.13371 500 252.36218L500 252.36218z" style="fill:#ffff00;fill-opacity:0.49999997;fill-rule:evenodd;stroke:#ffff00;stroke-width:4.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" transform="translate(-242.7989,-42.83241)"/>
<path d="M400 452.36218C400 507.59065 355.22847 552.36218 300 552.36218 244.77153 552.36218 200 507.59065 200 452.36218 200 397.13371 244.77153 352.36218 300 352.36218 355.22847 352.36218 400 397.13371 400 452.36218L400 452.36218z" style="fill:#ff00ff;fill-opacity:0.49999997;fill-rule:evenodd;stroke:#ff00ff;stroke-width:4.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-dasharray:none;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" transform="translate(-90.79890,-342.8324)"/>
<rect style="fill:url(#rd0);fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000;stroke-width:4.0000000;stroke-linecap:butt;stroke-miterlimit:4.0000000;stroke-dasharray:8.0000000 4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" rx="41.428570" ry="41.428570" transform="translate(6.201104,5.167586)" width="250.00000" y="2.3621826" x="351.00000" height="150.00000"/>
<text style="font-size:72px;font-style:oblique;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125.00000%;writing-mode:lr;text-anchor:start;fill:#fff;fill-opacity:0.49999997;stroke:#000;stroke-width:3.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:6.0000000 3.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans" xml:space="preserve" transform="translate(6.201104,5.167586)" y="101.34265" x="398.91016"><tspan y="101.34265" x="398.91016">SVG</tspan></text>
<g transform="matrix(0.403355,0.000000,0.000000,0.403355,284.7118,53.56855)">
<path style="fill:url(#rd1);fill-opacity:1.0000000;stroke:none;stroke-width:4.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" d="M675.82158 379.50504A182.96443 182.96443 0 1 0 309.89272 379.50504 182.96443 182.96443 0 1 0 675.82158 379.50504z" transform="translate(25.71677,42.14162)"/>
<path style="fill:url(#rd2);fill-opacity:1.0000000;stroke:none;stroke-width:4.0000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000" d="M675.82158 379.50504A182.96443 182.96443 0 1 0 309.89272 379.50504 182.96443 182.96443 0 1 0 675.82158 379.50504z" transform="translate(3.000000,1.000000)"/>
<path style="color:#000;fill:#000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:4.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;marker:none" d="M448.21432 203.83901C450.36313 204.6315 453.75174 205.94795 456.34375 207.71875 458.93576 209.48955 460.70727 211.5991 460.84375 214 461.1565 219.5018 462.73056 224.22855 456.3125 234.21875 449.89444 244.20895 435.16134 259.07637 402.75 282.4375 341.89198 326.30215 327.69756 419.11497 324.82774 445.4561L327.9384 453.22053C327.9384 453.22053 336.06337 335.44254 405.09375 285.6875 437.69027 262.19289 452.72065 247.17079 459.65625 236.375 466.59185 225.57921 465.12192 218.64356 464.84375 213.75 464.60642 209.57479 461.69349 206.55518 458.59375 204.4375 457.315 203.56388 455.94644 202.87002 454.65334 202.2368L448.21432 203.83901z"/>
<path style="color:#000;fill:#000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:4.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;marker:none" d="M509.01528 198.02937C499.53358 209.87282 477.91722 245.5091 465.15625 336.75 449.39628 449.43374 450.70852 546.83082 450.91598 557.84038L454.9375 558.75C454.9375 558.75 452.43678 456.60195 469.125 337.28125 482.74755 239.88008 506.43369 206.85787 513.90048 198.46178 513.90048 198.46178 509.01528 198.02937 509.01528 198.02937z"/>
<path style="color:#000;fill:#000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:4.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;marker:none" d="M556.6875 211.625C547.0438 211.8095 537.01703 214.51544 529.96875 222.90625 520.74474 233.88721 520.91652 245.76284 524.5 256.1875 528.08348 266.61216 534.88069 275.92531 538.96875 282.875 541.20112 286.67003 547.45814 295.57779 555.4375 309.1875 563.41686 322.79721 573.02573 340.97669 581.71875 362.78125 599.10479 406.39038 612.72572 464.47037 601.9375 529.59375 601.9375 529.59375 606.5655 526.08172 606.5655 526.08172 616.26061 461.73706 602.63933 404.42832 585.4375 361.28125 576.65129 339.24295 566.92996 320.8949 558.875 307.15625 550.82004 293.4176 544.35231 284.15204 542.40625 280.84375 538.13746 273.5868 531.59217 264.50677 528.28125 254.875 524.97033 245.24323 524.70586 235.41118 533.03125 225.5 541.18293 215.79562 554.20308 214.66443 565.5625 216.125 576.92192 217.58557 586.26153 221.51972 586.26153 221.51972 586.26153 221.51972 568.49535 212.55885 568.49535 212.55885 567.63548 212.41794 566.98202 212.27046 566.09375 212.15625 563.09277 211.77039 559.90207 211.5635 556.6875 211.625z"/>
<path style="color:#000;fill:#000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:4.0000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dashoffset:0.00000000;stroke-opacity:1.0000000;marker:none" d="M458.15625 224.96875C424.33124 226.01594 399.1972 233.81099 381.5 242.40625 376.05652 245.05007 371.36415 247.88263 367.2855 250.51507 362.72383 255.08465 357.48708 260.80582 350.5625 269.40625 350.5625 269.40625 360.3001 257.14641 383.25 246 406.1999 234.85359 442.22471 224.97829 494.53125 230.375 599.18056 241.17215 643.20884 296.98475 675.71875 347 675.71875 347 673.37503 336.37355 673.37503 336.37355 641.03129 288.32441 594.99108 236.69798 494.9375 226.375 481.69006 225.0082 469.43125 224.61969 458.15625 224.96875z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
tests/assets/image2_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
tests/assets/image_1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

8981
tests/assets/jquery-1.6.2.js vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/*
* jQuery helper plugin for examples and tests
*/
(function( $ ){
$.fn.html2canvas = function(options) {
if (options && options.profile && window.console && window.console.profile && window.location.search !== "?selenium2") {
console.profile();
}
var date = new Date(),
html2obj,
$message = null,
timeoutTimer = false,
timer = date.getTime();
options = options || {};
options.onrendered = options.onrendered || function( canvas ) {
var $canvas = $(canvas),
finishTime = new Date();
if (options && options.profile && window.console && window.console.profileEnd) {
console.profileEnd();
}
$canvas.addClass("html2canvas")
.css({
position: 'absolute',
left: 0,
top: 0
}).appendTo(document.body);
if (window.location.search !== "?selenium") {
$canvas.siblings().toggle();
$(window).click(function(){
$canvas.toggle().siblings().toggle();
throwMessage("Canvas Render " + ($canvas.is(':visible') ? "visible" : "hidden"));
});
throwMessage('Screenshot created in '+ ((finishTime.getTime()-timer)) + " ms<br />",4000);
} else {
$canvas.css('display', 'none');
}
// test if canvas is read-able
try {
$canvas[0].toDataURL();
} catch(e) {
if ($canvas[0].nodeName.toLowerCase() === "canvas") {
// TODO, maybe add a bit less offensive way to present this, but still something that can easily be noticed
alert("Canvas is tainted, unable to read data");
}
}
};
html2obj = html2canvas(this, options);
function throwMessage(msg,duration){
window.clearTimeout(timeoutTimer);
timeoutTimer = window.setTimeout(function(){
$message.fadeOut(function(){
$message.remove();
$message = null;
});
},duration || 2000);
if ($message)
$message.remove();
$message = $('<div />').html(msg).css({
margin:0,
padding:10,
background: "#000",
opacity:0.7,
position:"fixed",
top:10,
right:10,
fontFamily: 'Tahoma',
color:'#fff',
fontSize:12,
borderRadius:12,
width:'auto',
height:'auto',
textAlign:'center',
textDecoration:'none',
display:'none'
}).appendTo(document.body).fadeIn();
html2obj.log(msg);
}
};
})( jQuery );

View File

@ -1,109 +0,0 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 15.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>border tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></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: 23px double #669966;
background-color: #ccffcc;
padding-left: 5px;
}
#div2 {
opacity: 0.8;
position: absolute;
width: 150px;
height: 201px;
top: 20px;
left: 170px;
border: 20px dotted #990000;
background-color: #ffdddd;
text-align: center;
}
#div4 {
opacity: 0.8;
position: absolute;
width: 200px;
height: 70px;
top: 65px;
left: 50px;
border: 15px dashed #000099;
background-color: #ddddff;
text-align: left;
padding-left: 10px;
}
#div5{
border: 15px 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" style="background-image:url(image.jpg)">
<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>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:20px solid transparent;
border-width: 10px 20px 30px 40px;
background: green;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
</style>
</head>
<body>
<div class="medium">
<div style="background:url(../../assets/image.jpg);background-clip: border-box;"></div>
<div style="background:url(../../assets/image.jpg);background-clip: padding-box;"></div>
<div style="background:url(../../assets/image.jpg);background-clip: content-box;"></div>
<div style="background:url(../../assets/image.jpg);"></div>
</div>
<div class="medium">
<div style="background-clip: border-box;"></div>
<div style="background-clip: padding-box;"></div>
<div style="background-clip: content-box;"></div>
<div style=""></div>
</div>
</body>
</html>

View File

@ -1,19 +1,19 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 15.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
@ -21,7 +21,7 @@
.medium div{
width:200px;
height:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
@ -31,79 +31,22 @@
clear:both;
}
div{
display:block;
div{
display:block;
}
.encoded {
background:url("data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKCwsNDhIQDQ4RDgsLEBYQERMUFRUVDA8XGBYUGBIUFRT/2wBDAQMEBAUEBQkFBQkUDQsNFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBT/wAARCABLAEsDAREAAhEBAxEB/8QAHAAAAgMBAQEBAAAAAAAAAAAABQcEBggCAwAJ/8QANxAAAgECBQEHAQUIAwEAAAAAAQIDBBEABQYSITEHExQiQVFhcTKBkbHBCCNCUnLR4fAWYqLx/8QAGwEAAQUBAQAAAAAAAAAAAAAAAQIDBAUGAAf/xAAzEQACAgECAwQHCAMAAAAAAAAAAQIDEQQhEjFBIlFhcRMUgZGhsdEFFSNCUsHh8DKi8f/aAAwDAQACEQMRAD8AxREirbfKlv6rYxDz0R6mmj2eohpqrLKmGVTJTVsEpG65sHF8dBSakpLmn8hq5pxTXRo0DlaCn1dB7eJZfxxD0b/FiyFqVmmQ1Yo/KMaRFBIj5tCTFSG3SsgP/sf3x0t0JTJtLTlJa0FSP31+R/0TCcYG8nM0Q9sLAQJoRzgnECoiFjggB7RC5wsSZHTLaGCQpJBSq68EbQ1sUjst72bdU1dy9x1mlPQJlNQY0p+9Rd67YwDcG/HGBVK12JPOPMF1darbUVt4GgoazdmeW1YNxKaea/8AUoJxVafsTj4P9xm5cVcvJjjhljjlRZDtBPt1xqlzMu3tsNjSulMrziigkVUkUOHK9RcdD8Ys6owcStsnJMsFV2ZUrxVDRqQ0luSL9P8AH5YcdUWhtWtC91T2e1mWRPUQx740BLKt7/X6YhTqcd0S4WKWxQZhiOPA+ccYICAy3Y4UAyXS/uwFXLGFv5kX++KCWHu5m6i3y4SbI7y0k0bZbZHQqTtT2/qw3FRUk1P5/QVJtxa4X8PqNHIanxmndMzg+Z6KEc+6kqfyxG4MXuPiyFJ4qcn3F5o9RGrzPbI5aRz6np7D2GLpSbfiZ9xWMD20Fq5MlgpF72PdNIyGE8OFFvMPjn7/ALsWlE3FIrbYcTH5keaw11MtnVz063xZqWSvccMkZhRwT08m4KRY3BwibSW4uCeTJ+qKA5PnuYURBXuZmVQ/Xbe6n8CMVTWGWXQATOCCLjBAQXbzHphQkyTS5XE1HTXpttTtPfB5bruvxt+LdcUc7e08PY3dcez2luTIsm3GwjhF+OW/xhl3eLHuHwLpo1pn0lkrRh5no2qICkSGRmZJSQAo6khhxhmxS9azFc8P3kLsqiUZeQ3dPafhmrFkU7HUh3Exsyi9269LeuL2Me0ZWUsIM6p7EKjtkzTLXi1XVaWaEvfwSkmqJZdq7Qy9LdSeOeD6WlSRAm8YbNDN2f6ry6lpqXRGq6RqjLXjapgzaiM3i4woPdK6sCpYXs3NuOuJXBjkR3JNbjRy+KvkpF8bEaaV1tYi5/8AuI0k2tx1NLkYQ/aB1XmucdrGeHLNQ5jl+X07ikjiptiITGNrNfaSSWvyTf7gMUt2olGxxjyRe0Uw9GnOOWxXyVuoVLM+rc7kBvYeIC2/BcNeszew+qK1+UGTVmdGRj/yjPV+PGH+2HVqJ94PRV/pQtos+1SPs0WVi/S5kP64S9PpespfAlLUaz9Efj9QtkEmuc/roaajgycB2AaRo5NsY9WJB6DHeraVvCcm/Z9BM9Vq4rMlFL2/Dc0dp7L4dO5eKWl6k7pJtoVpGtyxA6dOgxIqpVawipuvldLMgtRzIjbDJsBYeW32sSlAiNkLtI7Y6nRkMcOWGeKYKqrMsO8Ru91Qkeo3bfKP1wpN8XDEXCtSWWGv2Le1nXk2qJn1VXjNVrHWJJpy3euIRtLcKAFAO0X6k8Di+Jzmk4xiQ5UWRUnYsGvO23thyvs60bUVIq0GcV1O4yykU3ldyNvegeiITck8XFuThOqvhRXxN7vkDSUTvsUUtlzPzdzqecS940zOzkvI7HlmuSxPyeuMfF5e/M1/CkerKFiaZQZIiN19wJ+oGE5T2Ow2QGkhc7u7fn6YWmDhYMnyDLGBanrp43JG8TQhx09CtrYs5aaPSTIEPtKf54L2PHzyXrRmVQZTlJZFQyyctIqlbj0HOHKqvRrfdkbUah3yzyXcWnK6lK4Ps+0h2snqDiXFZITeA/leTSV1ZGii537DZbgAjn64kRhljbkkhqt+zkmo6ekLx0s61ZNJJT1se5GABNn4IN/0BxIlpctSi8MajqOcZLKG32e9immtA6berly+nVqaF3ip4dyxR2UndybliR1J4Fhh6FSj2p7sZna32Y8jM+faKzjU2YNmWZ54tZmFSAZJ54mdiB0A6WUDoBYYoZ6C62XHZYm34MtofaNNceCFbS80B6jskrWRQmb0e8g3D07gLb7zfCPuufSa9zF/elfWD96Kzn2iZ8mjqFmmjd46hoN5tGsjKBu2BjubhlPAsAet8Vl+mlTlt9f7jr+xa1aiNuMLpn+9Clyaan3tt7vbfjzjEbLJWUUxqqxBtdR6e+NJgy/IZmlKiTMdPpO8RiuWsL/aAPUYUlsBvvO8glmi1LHGEURzAhh6gAXGFxW4mT2HbpOhTxSSOGWNrbghBJ+behxOgiLKRobSWo6fJKGE11YYYmO9TI/mP8J2jkkm1uP1xNTSW5F3b2CGp9UxHTGZVCkmnaMokbdTu8vP44alPIBCxkKFHJsStwfS5FsN5AfSSkpMyXEaAFiebLwCfxOCAomrshgGofFzw0UVPVoHlqJgu+NhZJG5IFhwbnnzcemKfVVQVnHJJZ69f748zQaO6cqlFNvG2Onev+chT1MEwqZfDyQdxuOwVDhZAL9CPjpjOvbkzQLxFk8TpIA6kpe7WHpjTYMrnI49KVVHmGX0cdOsnhwLI5Ujc3sB1Nr9elz64dSBkFZ+9To7PaatqwsNNFUhWk3G0YY28xP8PNyfS+OinGRzawa07E4IaySCaVVeOQdOoBHS/vixqIFnMtnb8tatHpxcpjgepjqHlKzOYwU2bSoYA26g9PTBtWcYG4y4XuU4Z9mE+TJl88cMUJ2FlDFzcG9gbDi+GEmFyT5AWSInvFFyFJHHXp/nBE5PHLA0Ek9M7EtNEYw59T8/76YMe46W+5W9dd+cm76IWMDhZbRxuAkg2tuDgggMFuBzyeuIesjmviXTwT2fmWOhklY4Pr5815Cxly+GRwxy+lclQdypMoPA5spKj7iR7YoJVtPHAv8AZfLK9xpI2Jr/ACfwItT2YTToVjCsTx5W639Mah0dxkVbgjZVojV+nqhXyeKOeON9yxzuFHwASeAOTb3OBGqaFemj1Gpn2VVuudD51kdRkcFDPWqIvE1dTG7qLLd1CX5JDDn64kcDwMuxE3sNoNWdnarltd3FZRx37mYVQOxFAsGH2r9eelrYEISiGVkZLI3M/wBRTallp5p9qLGuyNAb2FuTf5OHWskdsATRb1L2Fgf9/XCcHZIrRHxJHsdxHryPyIwMCiPLAwa9gHS4t7m/GOwcQ66natgqaSQeWqjaJSSP4hcG5vYggdQbH3wmUOOLj3jlcuCal3CIqWplqJAaWGNtxJSSdkYH1upVbG/wMZnixtlL2r+PkazhT33+P8jGy5iViYnzWBv841hjwplh3RwX9SXPyS2OQcBNpWpYZWiO096E6X8u61vwxyE9AplEjLPmLBjdQFHwOOMFdRL5BOjdmijJJJAU/wC/gMcgs6pnLIpJuTUAH6XtgndWjwy1Qc1qeP5fzwFzO6EOR28dSDcfPVhW56j93x+eB1CBdXVEtLmmWiJzGDOQbH03DCJbNBXJiU1zUyUGtc+p6dzDBFXzqkacBQJDYDGV1F9kLpxi9k38zbaaqE6ISkt2kf/Z");
background-position: center center;
}
.linearGradient {
/*background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(255, 0, 0)), to(rgb(0, 0, 255)));*/
background: -webkit-linear-gradient(top left, #f00, #00f, #BADA55, rgba(0, 0, 255,0.5));
background: -moz-linear-gradient(top right, #f00, #00f, #BADA55, rgba(0, 0, 255,0.5));
}
.linearGradient2 {
background: -webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), to(rgb(232, 232, 232)));
}
</style>
</head>
<body>
<div class="medium">
<div class="linearGradient">&nbsp;</div>
<div class="linearGradient2">&nbsp;</div>
</div>
<div class="medium">
<div style="background:url(image.jpg);"></div>
<div style="background:url(image.jpg) repeat-x;"></div>
<div style="background:url(image.jpg) repeat-y;"></div>
<div style="background:url(image.jpg) no-repeat;"></div>
</div>
<div class="small">
<div style="background:url(image.jpg);"></div>
<div style="background:url(image.jpg) repeat-x;"></div>
<div style="background:url(image.jpg) repeat-y;"></div>
<div style="background:url(image.jpg) no-repeat;"></div>
</div>
<div class="medium">
<div style="background:url(image.jpg) center center;"></div>
<div style="background:url(image.jpg) repeat-x center center;"></div>
<div style="background:url(image.jpg) repeat-y center center;"></div>
<div style="background:url(image.jpg) no-repeat center center;"></div>
</div>
<div class="small">
<div style="background:url(image.jpg) center center;"></div>
<div style="background:url(image.jpg) repeat-x center center;"></div>
<div style="background:url(image.jpg) repeat-y center center;"></div>
<div style="background:url(image.jpg) no-repeat center center;"></div>
</div>
<div class="medium">
<div style="background:url(image.jpg) 50px 50px;"></div>
<div style="background:url(image.jpg) repeat-x 50px 50px;"></div>
<div style="background:url(image.jpg) repeat-y 50px 50px;"></div>
<div style="background:url(image.jpg) no-repeat 50px 50px;"></div>
</div>
<div class="medium">
<div style="background:url(image.jpg) no-repeat -15% 25px;"></div>
<div style="background-image:url(image.jpg), url(image2.jpg); background-repeat: repeat-x; background-position: 50px 50px, 100px 100px;"></div>
</div>
<div class="medium">
<div class="encoded"></div>
</div>
</body>
</html>
</html>

View File

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
.linearGradient {
/*background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgb(255, 0, 0)), to(rgb(0, 0, 255)));*/
background: -webkit-linear-gradient(top left, #f00, #00f, #BADA55, rgba(0, 0, 255,0.5));
background: -moz-linear-gradient(top right, #f00, #00f, #BADA55, rgba(0, 0, 255,0.5));
}
.linearGradient2 {
background: -webkit-gradient(linear, 0% 0, 0% 100%, from(rgb(252, 252, 252)), to(rgb(232, 232, 232)));
}
.linearGradient3 {
/* FF 3.6+ */
background: -moz-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* Chrome,Safari4+ */
background: -webkit-gradient(linear, left top, right top, color-stop(#ff0000), color-stop(#ffff00), color-stop(#00ff00));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* IE 10+ */
background: -ms-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* W3C */
background: linear-gradient(left, #ff0000, #ffff00, #00ff00);
}
.linearGradient4 {
/* FF 3.6+ */
background: -moz-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, left top, right top, color-stop(0%, #cedbe9), color-stop(17%, #aac5de), color-stop(50%, #6199c7), color-stop(51%, #3a84c3), color-stop(59%, #419ad6), color-stop(71%, #4bb8f0), color-stop(84%, #3a8bc2), color-stop(100%, #26558b));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* IE10+ */
background: -ms-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* W3C */
background: linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
}
.linearGradient5 {
/* FF 3.6+ */
background: -moz-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f0b7a1), color-stop(50%, #8c3310), color-stop(51%, #752201), color-stop(100%, #bf6e4e));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* Opera 11.10+ */
background: -o-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* IE 10+ */
background: -ms-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* W3C */
background: linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
}
</style>
</head>
<body>
<div class="medium">
<div class="linearGradient">&nbsp;</div>
<div class="linearGradient2">&nbsp;</div>
<div class="linearGradient3">&nbsp;</div>
<div class="linearGradient4">&nbsp;</div>
<div class="linearGradient5">&nbsp;</div>
</div>
</body>
</html>

View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
</style>
</head>
<body>
<div class="medium">
<div style="background-image:url(../../assets/image.jpg), url(../../assets/image2.jpg); background-repeat: repeat-x; background-position: 50px 50px, 100px 130px;"></div>
<div style="background-image:url(../../assets/image.jpg), url(../../assets/image2.jpg); background-repeat: repeat-x; background-position: 50px 50px, 20px -20px;"></div>
<div style="background-image:url(../../assets/image.jpg), url(../../assets/image2.jpg); background-repeat: repeat-x; background-position: 50px 50px, 450px 100px;"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
</style>
</head>
<body>
<div class="medium">
<div style='background:url("../../assets/image.jpg") center center;'></div>
<div style="background:url('../../assets/image.jpg') repeat-x center center;"></div>
<div style="background:url(../../assets/image.jpg) repeat-y center center;"></div>
<div style="background:url(../../assets/image.jpg) no-repeat center center;"></div>
</div>
<div class="small">
<div style="background:url(../../assets/image.jpg) center center;"></div>
<div style="background:url(../../assets/image.jpg) repeat-x center center;"></div>
<div style="background:url(../../assets/image.jpg) repeat-y center center;"></div>
<div style="background:url(../../assets/image.jpg) no-repeat center center;"></div>
</div>
<div class="medium">
<div style="background:url(../../assets/image.jpg) -15% 25px;"></div>
<div style="background:url(../../assets/image.jpg) repeat-x 50px 50px;"></div>
<div style="background:url(../../assets/image.jpg) repeat-y 50px 50px;"></div>
<div style="background:url(../../assets/image.jpg) no-repeat 50px 50px;"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,161 @@
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
.radialGradient {
/* FF 3.6+ */
background: -moz-radial-gradient(center, ellipse cover, #959595 0%, #0d0d0d 48%, #2f7bd8 50%, #0a0a0a 64%, #4e4e4e 80%, #383838 87%, #1b1b1b 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#959595), color-stop(48%,#0d0d0d), color-stop(50%,#2f7bd8), color-stop(64%,#0a0a0a), color-stop(80%,#4e4e4e), color-stop(87%,#383838), color-stop(100%,#1b1b1b));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-radial-gradient(center, ellipse cover, #959595 0%, #0d0d0d 48%,#2f7bd8 50%,#0a0a0a 64%,#4e4e4e 80%,#383838 87%,#1b1b1b 100%);
/* Opera 12+ */
background: -o-radial-gradient(center, ellipse cover, #959595 0%, #0d0d0d 48%,#2f7bd8 50%,#0a0a0a 64%,#4e4e4e 80%,#383838 87%,#1b1b1b 100%);
/* IE 10+ */
background: -ms-radial-gradient(center, ellipse cover, #959595 0%,#0d0d0d 48%,#2f7bd8 50%,#0a0a0a 64%,#4e4e4e 80%,#383838 87%,#1b1b1b 100%);
/* W3C */
background: radial-gradient(center, ellipse cover, #959595 0%,#0d0d0d 48%,#2f7bd8 50%,#0a0a0a 64%,#4e4e4e 80%,#383838 87%,#1b1b1b 100%);
}
.radialGradient2 {
/* thx to https://twitter.com/#!/markjmclaren/status/13067366701 */
background-color: #FFF;
background-image:
-webkit-gradient(radial, 45 45, 10, 52 50, 30, from(#A7D30C), to(rgba(1,159,98,0)), color-stop(90%, #019F62)),
-webkit-gradient(radial, 105 105, 20, 112 120, 50, from(#ff5f98), to(rgba(255,1,136,0)), color-stop(75%, #ff0188)),
-webkit-gradient(radial, 95 15, 15, 102 20, 40, from(#00c9ff), to(rgba(0,201,255,0)), color-stop(80%, #00b5e2)),
-webkit-gradient(radial, 0 150, 50, 0 140, 90, from(#f4f201), to(rgba(228, 199,0,0)), color-stop(80%, #e4c700));
background-image:
-moz-radial-gradient(42px 42px, circle farthest-corner, #A7D30C 0%, #A7D30C 3%, rgba(1,159,98,0) 11%),
-moz-radial-gradient(45px 45px, circle farthest-corner, #019F62 0%, #019F62 13%, rgba(255,255,255,0) 16%, rgba(255,255,255,0) 100%),
-moz-radial-gradient(102px 102px, circle farthest-corner, #ff5f98 0%, #ff5f98 15%, rgba(255,1,136,0) 27%),
-moz-radial-gradient(105px 105px, circle farthest-corner, #FF0188 0%, #FF0188 28%, rgba(255,255,255,0) 32%, rgba(255,255,255,0) 100%),
-moz-radial-gradient(92px 12px, circle farthest-corner, #00c9ff 0%, #00c9ff 10%, rgba(0,181,226,0) 26%),
-moz-radial-gradient(95px 15px, circle farthest-corner, #00b5e2 0%, #00b5e2 28%, rgba(255,255,255,0) 31%, rgba(255,255,255,0) 100%),
-moz-radial-gradient(0px 150px, circle farthest-corner, #f4f201 0%, #f4f201 25%, rgba(228,199,0,0) 45%),
-moz-radial-gradient(0px 150px, circle farthest-corner, #e4c700 0%, #e4c700 47%, rgba(255,255,255,0) 50%, rgba(255,255,255,0) 100%);
}
.radialGradient3 {
background: -moz-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient4 {
background: -moz-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient5 {
background: -moz-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%)
}
.radialGradient6 {
background: -moz-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient7 {
background: -moz-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, circle contain, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient8 {
background: -moz-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient9 {
background: -moz-radial-gradient(right 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(right 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(right 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(right 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(right 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient10 {
background: -moz-radial-gradient(left 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(left 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(left 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(left 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(left 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient11 {
background: -moz-radial-gradient(left top, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(left top, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(left top, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(left top, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(left top, circle cover, #ababab, #0000ff 33%,#991f1f 100%);
}
</style>
</head>
<body>
<div class="medium">
<div class="radialGradient">&nbsp;</div>
<div class="radialGradient2">&nbsp;</div>
<div class="radialGradient3">&nbsp;</div>
<div class="radialGradient4">&nbsp;</div>
<div class="radialGradient5">&nbsp;</div>
<div class="radialGradient6">&nbsp;</div>
<div class="radialGradient7">&nbsp;</div>
<div class="radialGradient8">&nbsp;</div>
<div class="radialGradient9">&nbsp;</div>
<div class="radialGradient10">&nbsp;</div>
<div class="radialGradient11">&nbsp;</div>
</div>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title>Background attribute tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
html {
background-color: red;
}
body {
background-color: lime;
}
.small div{
width:100px;
height:100px;
float:left;
margin:10px;
border:1px solid #000;
}
.medium div{
width:200px;
height:200px;
float:left;
margin:10px;
border:1px solid #000;
}
.small, .medium{
clear:both;
}
div{
display:block;
}
</style>
</head>
<body>
<div class="medium">
<div style="background:url(../../assets/image.jpg);"></div>
<div style="background:url(../../assets/image.jpg) repeat-x;"></div>
<div style="background:url(../../assets/image.jpg) repeat-y;"></div>
<div style="background:url(../../assets/image.jpg) no-repeat;"></div>
</div>
<div class="small">
<div style="background:url(../../assets/image.jpg);"></div>
<div style="background:url(../../assets/image.jpg) repeat-x;"></div>
<div style="background:url(../../assets/image.jpg) repeat-y;"></div>
<div style="background:url(../../assets/image.jpg) no-repeat;"></div>
</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Borders tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style type="text/css">
div {
width: 200px;
height: 200px;
display: inline-block;
margin: 10px;
background:#6F428C;
border-style: dashed;
}
.box1 {
border-width: 1px;
border-color: #00b5e2;
}
.box2 {
border-width: 3px;
border-color: red;
}
.box3 {
border-width: 10px;
}
.box4 {
border-width: 50px;
border-color: green;
}
html {
background: #3a84c3;
}
</style>
</head>
<body>
<div class="box1">&nbsp;</div>
<div class="box2">&nbsp;</div>
<div class="box3">&nbsp;</div>
<div class="box4">&nbsp;</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Borders tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style type="text/css">
div {
width: 200px;
height: 200px;
display: inline-block;
margin: 10px;
background:#6F428C;
border-style: dotted;
}
.box1 {
border-width: 1px;
border-color: #00b5e2;
}
.box2 {
border-width: 3px;
border-color: red;
}
.box3 {
border-width: 10px;
}
.box4 {
border-width: 50px;
border-color: green;
}
html {
background: #3a84c3;
}
</style>
</head>
<body>
<div class="box1">&nbsp;</div>
<div class="box2">&nbsp;</div>
<div class="box3">&nbsp;</div>
<div class="box4">&nbsp;</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Borders tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style type="text/css">
div {
width: 200px;
height: 200px;
display: inline-block;
margin: 10px;
background:#6F428C;
border-style:double;
}
.box1 {
border-width: 1px;
border-color: #00b5e2;
}
.box2 {
border-width: 3px;
border-color: red;
}
.box3 {
border-width: 10px;
}
.box4 {
border-width: 50px;
border-color: green;
}
html {
background: #3a84c3;
}
</style>
</head>
<body>
<div class="box1">&nbsp;</div>
<div class="box2">&nbsp;</div>
<div class="box3">&nbsp;</div>
<div class="box4">&nbsp;</div>
</body>
</html>

View File

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<title>Borders tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style type="text/css">
div {
width: 200px;
height: 200px;
display: inline-block;
margin: 10px;
background:#6F428C;
border-style: solid;
border-radius: 50px;
}
.box1 {
border-width: 1px;
border-left-color: #00b5e2;
border-top-color: red;
border-right-color: green;
}
.box2 {
border-width: 3px;
border-left-color: #00b5e2;
border-top-color: red;
border-right-color: green;
}
.box3 {
border-width: 10px;
border-left-color: transparent;
border-top-color: red;
border-right-color: green;
}
.box4 {
border-width: 50px;
border-left-color: transparent;
border-top-color: red;
border-top-width: 10px;
border-right-color: green;
border-bottom-right-radius: 190px;
background-clip: padding-box;
}
html {
background: #3a84c3;
}
</style>
</head>
<body>
<div class="box1">&nbsp;</div>
<div class="box2">&nbsp;</div>
<div class="box3">&nbsp;</div>
<div class="box4">&nbsp;</div>
</body>
</html>

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Borders tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style type="text/css">
div {
width: 200px;
height: 200px;
display: inline-block;
margin: 10px;
background:#6F428C;
border-style: solid;
}
.box1 {
border-width: 1px;
border-color: #00b5e2;
}
.box2 {
border-width: 3px;
border-color: red;
}
.box3 {
border-width: 10px;
}
.box4 {
border-width: 50px;
border-color: green;
}
html {
background: #3a84c3;
}
</style>
</head>
<body>
<div class="box1">&nbsp;</div>
<div class="box2">&nbsp;</div>
<div class="box3">&nbsp;</div>
<div class="box4">&nbsp;</div>
</body>
</html>

View File

@ -1,22 +1,15 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Form tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../test.js"></script>
<style>
</style>
</head>
<body>
<body>
<input type="text" value="textbox" />
<input type="text" value="textbox" style="border:5px solid navy;" />
<input type="text" value="textbox" style="border:5px solid navy;height:40px;" />
@ -53,12 +46,12 @@
<input type="submit" value="Submit" style="width:200px;" />
<input type="Button" value="Button" style="width:200px;height:50px;" />
<input type="Reset" value="Reset" style="width:200px;height:50px;text-align:left;" />
<hr />
<textarea> </textarea>
<textarea style="border-width:10px;"></textarea>
<textarea> text </textarea>
<textarea style="border-width:10px;">text</textarea>
</body>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<title>Image tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
if ($('#testcanvas')[0].getContext) {
var ctx = $('#testcanvas')[0].getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect (30, 30, 55, 50);
} else {
$('#testcanvas').remove();
}
};
</script>
</head>
<body>
<canvas id="testcanvas" style="width:700px;height:300px;"></canvas>
</body>
</html>

View File

@ -3,16 +3,19 @@
<head>
<title>External content tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../test.js"></script>
<base href="http://www.google.com/" />
<base href="http://www.google.com/" />
</head>
<body>
<body>
<h1>External image</h1>
<img src="http://www.google.com/logos/2011/gregormendel11-hp.jpg" style="border:5px solid black;" />
<h1>External image (using &lt;base&gt; href)</h1>
<img src="/logos/2011/gregormendel11-res.jpg" />
<h1>External image (CORS)</h1>
<img src="http://publishmydata.com/assets/home/blue_bg.png" />
</body>
</html>

View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>Image tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
</head>
<body>
Image without src attribute, should not crash:
<img style="width:50px;height:50px;border:1px solid red;display:block;" />
</body>
</html>

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html>
<head>
<title>Image tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
</head>
<body>
<img src="../../assets/image.jpg" />
<img src="../../assets/image.jpg" style="width:50px;height:400px;" />
<img src="../../assets/image.jpg" style="width:500px;" />
<img src="../../assets/image.jpg" style="width:500px;height:40px;" />
<img src="../../assets/image.jpg" style="padding:20px;border:5px solid black;" />
<img src="../../assets/image.jpg" style="padding-bottom:20px;border-top:5px solid black;clear:both;" />
<img src="../../assets/image.jpg" style="padding-top:20px;border-top:5px solid black;clear:both;width:50px;" />
<img src="../../assets/image.jpg" style="padding-top:20px;border-top:5px solid black;clear:both;width:50px;height:25px;" />
<img src="../../assets/image.jpg" style="width:0px;height:0px;border:1px solid black" />
<img src="../../assets/image.jpg" style="width:0px;height:0px;" />
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>Image tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
</head>
<body>
SVG taints image:<br /> <!-- http://fi.wikipedia.org/wiki/Tiedosto:Svg.svg -->
<img src="../../assets/image.svg" />
</body>
</html>

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=100;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[1]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-position: inside;
font-size:20px;
line-height:50px;
}
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
li{
border:1px solid black;
width:100px;
margin:0;
}
ol{
margin:0;
}
</style>
</head>
<body>
<ol id="dynamic"></ol>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=100;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[0]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-position: inside;
font-size:20px;
line-height:50px;
}
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
li{
border:1px solid black;
width:100px;
margin:0;
}
ol{
margin:0;
}
</style>
</head>
<body>
<ol id="dynamic"></ol>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=100;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[4]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-position: inside;
font-size:20px;
line-height:50px;
}
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
li{
border:1px solid black;
width:100px;
margin:0;
}
ol{
margin:0;
}
</style>
</head>
<body>
<ol id="dynamic"></ol>
</body>
</html>

View File

@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=100;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[2]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-position: inside;
font-size:20px;
line-height:50px;
}
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
li{
border:1px solid black;
width:100px;
margin:0;
}
ol{
margin:0;
}
</style>
</head>
<body>
<ol id="dynamic"></ol>
</body>
</html>

View File

@ -3,8 +3,7 @@
<head>
<title>Overflow tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../test.js"></script>
<style>
.small{
font-size:14px;
@ -29,22 +28,22 @@
</style>
</head>
<body>
<body>
<h1>Overflow: visible</h1>
<div> Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like <b>Aldus PageMaker</b> including versions of Lorem Ipsum.
</div>
<h1>Overflow: hidden</h1>
<div style="overflow:hidden;">
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s
with the release of <div style="border-width:10px 0 5px 0;background:green;">a</div>Letraset sheets containing Lorem Ipsum passages, <img src="image.jpg" /> and more recently with desktop publishing software like <b>Aldus PageMaker</b> including versions of Lorem Ipsum.
<div style="overflow:visible;position:relative;"><u>position:relative within a overflow:hidden element</u><br /> <br />
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like <b>Aldus PageMaker</b> including versions of Lorem Ipsum.
</div>
</div>

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html>
<head>
<title>Pseudoelement tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../test.js"></script>
<style>
.text *::before {
content:" before!";
}
.text *::after {
content:" after!";
}
.img *::before{
content: url(../assets/image.jpg);
}
.img *::after{
content: url(../assets/image2.jpg);
}
.background *::before{
background: url(../assets/image_1.jpg);
}
.background *::after{
background: url(../assets/image2_1.jpg);
}
.none *::before {
display:none;
}
.none *::after {
display:none;
}
</style>
</head>
<body>
<div class="text">
<span>Content 1</span>
<span>Content 2</span>
</div>
<div class="text none">
<span>Content 1</span>
<span>Content 2</span>
</div>
<div class="text img">
<span>Content 1</span>
<span>Content 2</span>
</div>
<div class="text background">
<span>Content 1</span>
<span>Content 2</span>
</div>
</body>
</html>

View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<title>Chinese text</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<script>
h2cOptions = {
chinese: true
}
</script>
<style>
.chn-text-block {
width: 500px;
font-family: serif;
float: left;
}
</style>
</head>
<body>
<div id="text" class="chn-text-block">
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;1 见本书第一卷《实践论》注6
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;2 见列宁《党的组织和党的出版物》。列宁在这篇论文中说“这将是自由的写作因为把一批又一批新生力量吸引到写作队伍中来的不是私利贪欲也不是名誉地位而是社会主义思想和对劳动人民的同情。这将是自由的写作因为它不是为饱食终日的贵妇人服务不是为百无聊赖、胖得发愁的一万个上层分子服务而是为千千万万劳动人民为这些国家的精华、国家的力量、国家的未来服务。这将是自由的写作它要用社会主义无产阶级的经验和生气勃勃的工作去丰富人类革命思想的最新成就它要使过去的经验从原始空想的社会主义发展而成的科学社会主义和现在的经验工人同志们当前的斗争之间经常发生相互作用。”《列宁全集》第12卷人民出版社1987年版第96—97页
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;3 梁实秋一九○三——一九八七北京人。新月社主要成员。先后在复旦大学、北京大学等校任教。曾写过一些文艺评论长时期致力于文学翻译工作和散文的写作。鲁迅对梁实秋的批评见《三闲集·新月社批评家的任务》、《二心集·“硬译”与“文学的阶级性”》等文。《鲁迅全集》第4卷人民文学出版社1981年版第159、195—212页
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;4 周作人(一八八五——一九六七),浙江绍兴人。曾在北京大学、燕京大学等校任教。五四运动时从事新文学写作。他的著述很多,有大量的散文集、文学专著和翻译作品。张资平(一八九三——一九五九),广东梅县人。他写过很多小说,曾在暨南大学、大夏大学兼任教职。周作人、张资平于一九三八年和一九三九年先后在北平、上海依附侵略中国的日本占领者。
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;5 见鲁迅《二心集·对于左翼作家联盟的意见》《鲁迅全集》第4卷人民文学出版社1981年版第237—238页
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;6 参见鲁迅《且介亭杂文末编·附集·死》《鲁迅全集》第6卷人民文学出版社1981年版第612页
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;7 “小放牛”是中国一出传统的小歌舞剧。全剧只有两个角色,男角是牧童,女角是乡村小姑娘,以互相对唱的方式表现剧的内容。抗日战争初期,革命的文艺工作者利用这个歌舞剧的形式,变动其原来的词句,宣传抗日,一时颇为流行。
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;8 “人、手、口、刀、牛、羊”是笔画比较简单的汉字,旧时一些小学国语读本把这几个字编在第一册的最初几课里。
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;9 “阳春白雪”和“下里巴人”,都是公元前三世纪楚国的歌曲。“阳春白雪”是供少数人欣赏的较高级的歌曲;“下里巴人”是流传很广的民间歌曲。《文选·宋玉对楚王问》记载一个故事,说有人在楚都唱歌,唱“阳春白雪”时,“国中属而和者(跟着唱的),不过数十人”;但唱“下里巴人”时,“国中属而和者数千人”。
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;10 见列宁《党的组织和党的出版物》。列宁在这篇论文中说“写作事业应当成为整个无产阶级事业的一部分成为由整个工人阶级的整个觉悟的先锋队所开动的一部巨大的社会民主主义机器的齿轮和螺丝钉。”《列宁全集》第12卷人民出版社1987年版第93页
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;11 亭子间是上海里弄房子中的一种小房间,位置在房子后部的楼梯中侧,狭小黑暗,因此租金比较低廉。解放以前,贫苦的作家、艺术家、知识分子和机关小职员,多半租这种房间居住。
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;12 见本书第二卷《和中央社、扫荡报、新民报三记者的谈话》注3
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;13 法捷耶夫(一九○一——一九五六),苏联名作家。他所作的小说《毁灭》于一九二七年出版,内容是描写苏联国内战争时期由苏联远东滨海边区工人、农民和革命知识分子所组成的一支游击队同国内反革命白卫军以及日本武装干涉军进行斗争的故事。这部小说曾由鲁迅译为汉文。
</p><p>&nbsp;&nbsp;&nbsp;&nbsp;14 见鲁迅《集外集·自嘲》《鲁迅全集》第7卷人民文学出版社1981年版第147页</p>
</div>
</body>
</html>

View File

@ -1,22 +1,15 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Text-decoration:line-through tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
$('body').empty();
$.each(['arial','verdana','tahoma','courier new'],function(i,e){
var div = $('<div />').css('font-family',e).appendTo('body');
for(var i=0;i<=20;i++){
for(var i=0;i<=10;i++){
$('<div />').text('Testing texts').css('margin-top',1).css('border','1px solid black').css('font-size',(16+i*6)).appendTo(div);
}
});
@ -34,23 +27,23 @@
.large{
font-size:24px;
}
div{
text-decoration:line-through;
}
.lineheight{
line-height:40px;
}
h2 {
clear:both;
}
</style>
</head>
<body>
<body>
Creating content through JavaScript
</body>
</html>

View File

@ -1,16 +1,9 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Text tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../test.js"></script>
<style>
.small{
font-size:14px;
@ -39,20 +32,20 @@
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
<ol class="medium">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
<ol class="large">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
</div>
<div style="font-family:Verdana;">
@ -62,20 +55,20 @@
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
<ol class="medium">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
<ol class="large">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
</div>
<div style="font-family:Tahoma;">
@ -85,26 +78,26 @@
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
<ol class="medium">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
<ol class="large">
<li style="text-decoration:none;">text-decoration:none;</li>
<li style="text-decoration:underline;">text-decoration:underline;</li>
<li style="text-decoration:overline;">text-decoration:overline;</li>
<li style="text-decoration:line-through;">text-decoration:line-through;</li>
</ol>
</ol>
</div>
<h2>&lt;h2&gt; text-transform</h2>
<ul>
<li style="text-transform:none;">text-transform:none;</li>
<li style="text-transform:capitalize;">text-transform:capitalize; (including foreign characters such as Öaäå)</li>
<li style="text-transform:capitalize;">text-transform: capitalize; (including foreign characters such as Öaäå)</li>
<li style="text-transform:uppercase;">text-transform:uppercase;</li>
<li style="text-transform:lowercase;">text-transform:lowercase;</li>
</ul>

View File

@ -1,25 +1,18 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Text-decoration:underline tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
$('body').empty();
$.each(['arial','verdana','tahoma','courier new'],function(i,e){
var div = $('<div />').css('font-family',e).appendTo('body');
for(var i=0;i<=20;i++){
for(var i=0;i<=10;i++){
$('<div />').text('Testing texts').css('margin-top',1).css('border','1px solid black').css('font-size',(16+i*6)).appendTo(div);
}
}
});
}
</script>
@ -49,7 +42,7 @@
</style>
</head>
<body>
<body>
Creating content through JavaScript
</body>
</html>

View File

@ -1,25 +1,18 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Text-decoration:underline tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../../test.js"></script>
<script type="text/javascript">
function setUp() {
$('body').empty();
$.each(['arial','verdana','tahoma','courier new'],function(i,e){
var div = $('<div />').css('font-family',e).appendTo('body');
for(var i=0;i<=20;i++){
for(var i=0;i<=10;i++){
$('<div />').text('Testing texts').css('margin-top',1).css('border','1px solid black').css('font-size',(16+i*6)).appendTo(div);
}
}
});
}
</script>
@ -50,7 +43,7 @@
</style>
</head>
<body>
<body>
Creating content through JavaScript
</body>
</html>

View File

@ -1,16 +1,9 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>Visible elements tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript" src="../test.js"></script>
<style>
div{
border:2px solid black;
@ -18,7 +11,7 @@
</style>
</head>
<body>
<body>
<h1>Display:none and visible:hidden tests</h1>
<div>This should be visible </div>
<div style="display:none">display:none, This should be <b>hidden</b></div>
@ -26,6 +19,6 @@
<hr />
<div style="display:none">display:none, This should be <b>hidden</b></div>
<div style="visibility:hidden">visibility:hidden, This should be <b>hidden</b></div>
</body>
</html>

View File

@ -0,0 +1,81 @@
<!DOCTYPE html>
<html>
<head>
<title>z-index tests #1</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style>
div { font: 12px Arial; }
span.bold { font-weight: bold; }
#div1,#div3 {
height: 80px;
position: relative;
border: 1px solid #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 solid #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 solid #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>

View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<title>z-index tests #2</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></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 solid #669966;
background-color: #ccffcc;
padding-left: 5px;
}
#div2 {
opacity: 0.8;
position: absolute;
width: 150px;
height: 200px;
top: 20px;
left: 170px;
border: 1px solid #990000;
background-color: #ffdddd;
text-align: center;
}
#div4 {
opacity: 0.8;
position: absolute;
width: 200px;
height: 70px;
top: 65px;
left: 50px;
border: 1px solid #000099;
background-color: #ddddff;
text-align: left;
padding-left: 10px;
}
#div5{
border: 1px solid #669966;
background-color: #ccffcc;
padding-left: 5px;
position:relative;
margin-bottom:-15px;
height:50px;
margin-top:10px;
}
#div6{
border: 1px solid #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>

View File

@ -0,0 +1,109 @@
<!DOCTYPE html>
<html>
<head>
<title>z-index tests #3</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="../../test.js"></script>
<style type="text/css">
div { font: 12px Arial; }
span.bold { font-weight: bold; }
div.lev1 {
width: 250px;
height: 70px;
position: relative;
border: 2px solid #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 solid #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>

View File

@ -1,14 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>External content tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
</head>
<body>
<h1>Iframe</h1>
<iframe src="http://www.google.com" style="width:400px;height:300px;border:5px solid black;"></iframe>
</body>
</html>

View File

@ -1,66 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Image tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link href="#" type="text/css" rel="stylesheet">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript">
function setUp() {
var ctx = $('#testcanvas')[0].getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect (10, 10, 55, 50);
ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
ctx.fillRect (30, 30, 55, 50);
};
</script>
<style>
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
</style>
</head>
<body>
<img src="image.jpg" />
<img src="image.jpg" style="width:50px;height:400px;" />
<img src="image.jpg" style="width:500px;" />
<img src="image.jpg" style="width:500px;height:40px;" />
<img src="image.jpg" style="padding:20px;border:5px solid black;" />
<img src="image.jpg" style="padding-bottom:20px;border-top:5px solid black;clear:both;" />
<img src="image.jpg" style="padding-top:20px;border-top:5px solid black;clear:both;width:50px;" />
<img src="image.jpg" style="padding-top:20px;border-top:5px solid black;clear:both;width:50px;height:25px;" />
<img src="image.jpg" style="width:0px;height:0px;border:1px solid black" />
<img src="image.jpg" style="width:0px;height:0px;" />
<canvas id="testcanvas" style="width:100px;height:100px;"></canvas>
<br />
Image without src attribute, should not crash:
<img style="width:50px;height:50px;border:1px solid red;display:block;" />
</body>
</html>

View File

@ -1,80 +0,0 @@
<!--
* @author Niklas von Hertzen <niklas at hertzen.com>
* @created 16.7.2011
* @website http://hertzen.com
-->
<!DOCTYPE html>
<html>
<head>
<title>List tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="test.js"></script>
<script type="text/javascript">
function setUp() {
var supportedTypes = ["decimal","decimal-leading-zero","upper-roman","lower-roman","lower-alpha","upper-alpha"];
for (var i = 1;i<=100;i++){
$('#dynamic').append($('<li />').text(i).css('list-style-type',supportedTypes[Math.round(Math.random()*supportedTypes.length)]));
}
}
</script>
<style>
#dynamic{
list-style-type:decimal;
list-style-position: inside;
font-size:20px;
line-height:50px;
}
.small{
font-size:14px;
}
.medium{
font-size:18px;
}
.large{
font-size:24px;
}
div{
float:left;
}
h2 {
clear:both;
}
li{
border:1px solid black;
width:100px;
margin:0;
}
ol{
margin:0;
}
</style>
</head>
<body>
<ul>
<li>First</li>
<li style="list-style-position:inside; ">Second</li>
<li>Third</li>
</ul>
<ol>
<li>First</li>
<li style="list-style-position:inside; ">Second<br />new line</li>
<li style="list-style-position:inside; "></li>
<li style="list-style-position:outside;">Third</li>
</ol>
<ol id="dynamic">
</ol>
</body>
</html>

212
tests/qunit/index.html Normal file
View File

@ -0,0 +1,212 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>QUnit Test Suite</title>
<link rel="stylesheet" href="lib/qunit.css">
<script src="lib/qunit.js"></script>
<!-- src files -->
<script type="text/javascript" src="../assets/jquery-1.6.2.js"></script>
<!-- 'Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'renderers/Canvas' -->
<script type="text/javascript" src="../../src/Core.js"></script>
<script type="text/javascript" src="../../src/Generate.js"></script>
<script type="text/javascript" src="../../src/Parse.js"></script>
<script type="text/javascript" src="../../src/Preload.js"></script>
<script type="text/javascript" src="../../src/Queue.js"></script>
<script type="text/javascript" src="../../src/Renderer.js"></script>
<script type="text/javascript" src="../../src/Util.js"></script>
<script type="text/javascript" src="../../src/renderers/Canvas.js"></script>
<script src="unit/css.js"></script>
<script src="unit/generate.js"></script>
<!-- <script src="unit/utils.js"></script> -->
<style>
#borders div {
border-color: #000;
border-style: solid;
}
#backgroundPosition div {
width:50px;
height:50px;
}
#paddingPercentage div {
width:50px;
height:50px;
}
</style>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture" style="visibility:none; height:1px; overflow:scroll;">
All the tests here. <b>Testing different <span>stuff</span> for contents()</b>
<div id="borders">Yep, here's some more.
<div style="border-width: 1px 0;">Div 1</div>
<div style="border-width: 1em 0;">Div 2</div>
<div style="border-width: thin medium thick;">Some more divs</div>
<div style="border-width: 5% 6px 12%;"></div> <!-- percentages aren't valid -->
<div style="border-width: 5em 5ex 5in 5cm;"></div>
<div style="border-width: 500em 500ex 500in 500cm;"></div>
<div style="border-width: 5mm 5pt 5pc 5px;"></div>
<div style="border-width: auto inherit;"></div>
<div style="border-width: 500mm 500pt 500pc 500px;"></div>
</div>
<div id="padding">
<div style="padding: 1px 0;"></div>
<div style="padding: 1em 0;"></div>
<div style="padding: thin medium thick;"></div>
<div style="padding: 5em 5ex 5in 5cm;"></div>
<div style="padding: 500em 500ex 500in 500cm;"></div>
<div style="padding: 5mm 5pt 5pc 5px;"></div>
<div style="padding: 500mm 500pt 500pc 500px;"></div>
<div style="padding: 1px 5%;"></div>
<div style="padding: 15% 0 3%;"></div>
</div>
<div id="backgroundPosition">
<div style="background-position: 1px 0;"></div>
<div style="background-position: 1em 0;"></div>
<div style="background-position: thin medium;"></div>
<div style="background-position: 5em 5ex;"></div>
<div style="background-position: 5in 5cm;"></div>
<div style="background-position: 500in 500cm;"></div>
<div style="background-position: 500em 500ex;"></div>
<div style="background-position: 5pc 5px;"></div>
<div style="background-position: 500pc 500px;"></div>
<div style="background-position: 5mm 5pt;"></div>
<div style="background-position: 500mm 500pt;"></div>
</div>
<div id="backgroundPositionPercentage">
<div style="background-position: 5% 6px;"></div>
<div style="background-position: center center;"></div>
<div style="background-position: left bottom;"></div>
</div>
<style>
.linearGradientSimple {
/* FF 3.6+ */
background: -moz-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* Chrome,Safari4+ */
background: -webkit-gradient(linear, left center, right center, color-stop(#ff0000), color-stop(#ffff00), color-stop(#00ff00));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* IE 10+ */
background: -ms-linear-gradient(left, #ff0000, #ffff00, #00ff00);
/* W3C */
background: linear-gradient(left, #ff0000, #ffff00, #00ff00);
}
.linearGradientWithStops {
/* FF 3.6+ */
background: -moz-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, left center, right center, color-stop(0%, #cedbe9), color-stop(17%, #aac5de), color-stop(50%, #6199c7), color-stop(51%, #3a84c3), color-stop(59%, #419ad6), color-stop(71%, #4bb8f0), color-stop(84%, #3a8bc2), color-stop(100%, #26558b));
/* Chrome 10+, Safari 5.1+ */
background: -webkit-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* Opera 11.10+ */
background: -o-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* IE 10+ */
background: -ms-linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
/* W3C */
background: linear-gradient(left, #cedbe9 0%, #aac5de 17%, #6199c7 50%, #3a84c3 51%, #419ad6 59%, #4bb8f0 71%, #3a8bc2 84%, #26558b 100%);
}
.linearGradient3 {
/* FF 3.6+ */
background: -moz-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* Chrome, Safari 4+ */
background: -webkit-gradient(linear, center top, center bottom, color-stop(0%, #f0b7a1), color-stop(50%, #8c3310), color-stop(51%, #752201), color-stop(100%, #bf6e4e));
/* Opera 11.10+ */
background: -o-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* IE 10+ */
background: -ms-linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
/* W3C */
background: linear-gradient(top, #f0b7a1 0%, #8c3310 50%, #752201 51%, #bf6e4e 100%);
}
.radialGradient {
background: -moz-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse closest-side, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient2 {
background: -moz-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse closest-corner, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient3 {
background: -moz-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse farthest-side, #ababab, #0000ff 33%,#991f1f 100%)
}
.radialGradient4 {
background: -moz-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse farthest-corner, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient5 {
background: -moz-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse contain, #ababab, #0000ff 33%,#991f1f 100%);
}
.radialGradient6 {
background: -moz-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -webkit-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -o-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: -ms-radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
background: radial-gradient(75% 19%, ellipse cover, #ababab, #0000ff 33%,#991f1f 100%);
}
</style>
<div id="backgroundGradients">
<div class="linearGradientSimple"></div>
<div class="linearGradientWithStops"></div>
<div class="linearGradient3"></div>
<div class="radialGradient"></div>
<div class="radialGradient2"></div>
<div class="radialGradient3"></div>
<div class="radialGradient4"></div>
<div class="radialGradient5"></div>
<div class="radialGradient6"></div>
</div>
</div>
<!--
<div id="fixture-iframes"></div>
<script>
var pages = ["background","borders","external-content","forms","images","lists","origin","overflow","proxy","text-linethrough"],
fixtures = $("#fixture-iframes");
$.each(pages, function(i, page){
var iframe = $('<iframe />').attr('src',"../" + page + ".html");
iframe.insertAfter( fixtures );
});
</script>
<iframe src="../borders.html" id="borders"></iframe> -->
</body>
</html>

232
tests/qunit/lib/qunit.css Normal file
View File

@ -0,0 +1,232 @@
/**
* QUnit v1.4.0pre - A JavaScript Unit Testing Framework
*
* http://docs.jquery.com/QUnit
*
* Copyright (c) 2012 John Resig, Jörn Zaefferer
* Dual licensed under the MIT (MIT-LICENSE.txt)
* or GPL (GPL-LICENSE.txt) licenses.
*/
/** Font Family and Sizes */
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
}
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
#qunit-tests { font-size: smaller; }
/** Resets */
#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult {
margin: 0;
padding: 0;
}
/** Header */
#qunit-header {
padding: 0.5em 0 0.5em 1em;
color: #8699a4;
background-color: #0d3349;
font-size: 1.5em;
line-height: 1em;
font-weight: normal;
border-radius: 15px 15px 0 0;
-moz-border-radius: 15px 15px 0 0;
-webkit-border-top-right-radius: 15px;
-webkit-border-top-left-radius: 15px;
}
#qunit-header a {
text-decoration: none;
color: #c2ccd1;
}
#qunit-header a:hover,
#qunit-header a:focus {
color: #fff;
}
#qunit-header label {
display: inline-block;
}
#qunit-banner {
height: 5px;
}
#qunit-testrunner-toolbar {
padding: 0.5em 0 0.5em 2em;
color: #5E740B;
background-color: #eee;
}
#qunit-userAgent {
padding: 0.5em 0 0.5em 2.5em;
background-color: #2b81af;
color: #fff;
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
}
/** Tests: Pass/Fail */
#qunit-tests {
list-style-position: inside;
}
#qunit-tests li {
padding: 0.4em 0.5em 0.4em 2.5em;
border-bottom: 1px solid #fff;
list-style-position: inside;
}
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
display: none;
}
#qunit-tests li strong {
cursor: pointer;
}
#qunit-tests li a {
padding: 0.5em;
color: #c2ccd1;
text-decoration: none;
}
#qunit-tests li a:hover,
#qunit-tests li a:focus {
color: #000;
}
#qunit-tests ol {
margin-top: 0.5em;
padding: 0.5em;
background-color: #fff;
border-radius: 15px;
-moz-border-radius: 15px;
-webkit-border-radius: 15px;
box-shadow: inset 0px 2px 13px #999;
-moz-box-shadow: inset 0px 2px 13px #999;
-webkit-box-shadow: inset 0px 2px 13px #999;
}
#qunit-tests table {
border-collapse: collapse;
margin-top: .2em;
}
#qunit-tests th {
text-align: right;
vertical-align: top;
padding: 0 .5em 0 0;
}
#qunit-tests td {
vertical-align: top;
}
#qunit-tests pre {
margin: 0;
white-space: pre-wrap;
word-wrap: break-word;
}
#qunit-tests del {
background-color: #e0f2be;
color: #374e0c;
text-decoration: none;
}
#qunit-tests ins {
background-color: #ffcaca;
color: #500;
text-decoration: none;
}
/*** Test Counts */
#qunit-tests b.counts { color: black; }
#qunit-tests b.passed { color: #5E740B; }
#qunit-tests b.failed { color: #710909; }
#qunit-tests li li {
margin: 0.5em;
padding: 0.4em 0.5em 0.4em 0.5em;
background-color: #fff;
border-bottom: none;
list-style-position: inside;
}
/*** Passing Styles */
#qunit-tests li li.pass {
color: #5E740B;
background-color: #fff;
border-left: 26px solid #C6E746;
}
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
#qunit-tests .pass .test-name { color: #366097; }
#qunit-tests .pass .test-actual,
#qunit-tests .pass .test-expected { color: #999999; }
#qunit-banner.qunit-pass { background-color: #C6E746; }
/*** Failing Styles */
#qunit-tests li li.fail {
color: #710909;
background-color: #fff;
border-left: 26px solid #EE5757;
white-space: pre;
}
#qunit-tests > li:last-child {
border-radius: 0 0 15px 15px;
-moz-border-radius: 0 0 15px 15px;
-webkit-border-bottom-right-radius: 15px;
-webkit-border-bottom-left-radius: 15px;
}
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
#qunit-tests .fail .test-name,
#qunit-tests .fail .module-name { color: #000000; }
#qunit-tests .fail .test-actual { color: #EE5757; }
#qunit-tests .fail .test-expected { color: green; }
#qunit-banner.qunit-fail { background-color: #EE5757; }
/** Result */
#qunit-testresult {
padding: 0.5em 0.5em 0.5em 2.5em;
color: #2b81af;
background-color: #D2E0E6;
border-bottom: 1px solid white;
}
/** Fixture */
#qunit-fixture {
position: absolute;
top: -10000px;
left: -10000px;
width: 1000px;
height: 1000px;
}

1632
tests/qunit/lib/qunit.js Normal file

File diff suppressed because it is too large Load Diff

238
tests/qunit/unit/css.js Normal file
View File

@ -0,0 +1,238 @@
// declare vars (preventing JSHint messages)
/* this breaks the testing for IE<9, haven't really looked into why
var test = test || function(){},
QUnit = QUnit || {},
_html2canvas = _html2canvas || {};
*/
module("CSS");
$(function() {
var propsToTest = {},
numDivs = {};
propsToTest['border-width'] = ["borderTopWidth", "borderRightWidth", "borderBottomWidth", "borderLeftWidth"],
numDivs['border-width'] = $('#borders div').length;
/*
expecting = [
// #1
"1px",
"0px",
"1px",
"0px",
// #2
"16px",
"0px",
"16px",
"0px",
// #3
"1px",
"3px",
"5px",
"3px",
// #4
"3px",
"3px",
"3px",
"3px",
// #5
"80px",
"35px",
"480px",
"188px",
// #6
"3904px",
"3500px",
"2944px",
"2513px",
// #7
"18px",
"6px",
"80px",
"5px",
// #8
"1889px",
"666px",
"3904px",
"500px"
];
*/
test('border-width', propsToTest['border-width'].length * numDivs['border-width'], function() {
$('#borders div').each(function(i, el) {
$.each(propsToTest['border-width'], function(s, prop) {
var expect = $(el).css(prop);
// older IE's don't necessarily return px even with jQuery
if (expect === "thin") {
expect = "1px";
} else if (expect === "medium") {
expect = "3px";
} else if (expect === "thick") {
expect = "5px";
}
QUnit.equal( _html2canvas.Util.getCSS(el, prop), expect, "div #" + (i + 1) + " property " + prop + " equals " + expect );
});
});
});
propsToTest['padding width'] = ["paddingTop", "paddingRight", "paddingBottom", "paddingLeft"];
numDivs['padding width'] = $('#padding div').length;
test('padding width', propsToTest['padding width'].length * numDivs['padding width'] * 2, function() {
$('#padding div').each(function(i, el) {
$.each(propsToTest['padding width'], function(s, prop) {
var isPx = _html2canvas.Util.getCSS(el, prop).indexOf("px");
QUnit.notEqual( isPx, -1, "div #" + (i + 1) + " property " + prop + " is in pixels" );
QUnit.equal( _html2canvas.Util.getCSS(el, prop), $(el).css(prop), "div #" + (i + 1) + " property " + prop + " equals " + $(el).css(prop) );
});
});
});
propsToTest['background-position'] = ["backgroundPosition"];
numDivs['background-position'] = $('#backgroundPosition div').length;
test('background-position', propsToTest['background-position'].length * numDivs['background-position'] * 2, function() {
$('#backgroundPosition div').each(function(i, el) {
$.each(propsToTest['background-position'], function(s, prop) {
var img = new Image();
img.width = 50;
img.height = 50;
var item = _html2canvas.Util.getCSS(el, prop),
pos = _html2canvas.Util.BackgroundPosition(el, _html2canvas.Util.Bounds(el), img),
split;
if ( window.getComputedStyle ) {
split = $(el).css(prop).split(" ");
} else {
split = [$(el).css(prop+"X"),$(el).css(prop+"Y")];
}
var testEl = $('<div />').css({
'position': 'absolute',
'left': split[0],
'top': split[1]
});
testEl.appendTo(el);
QUnit.equal( pos.left, Math.round(parseFloat(testEl.css('left'), 10)), "div #" + (i + 1) + " background-position-x equals " + pos.left + " from " + item );
QUnit.equal( pos.top, Math.round(parseFloat(testEl.css('top'), 10)), "div #" + (i + 1) + " background-position-y equals " + pos.top );
testEl.remove();
});
});
});
test('background-image', function () {
test_parse_background_image(
'url("te)st")',
{ prefix: '', method: 'url', value: 'url("te)st")', args: ['te)st'] },
'test quoted'
);
test_parse_background_image(
'url("te,st")',
{ prefix: '', method: 'url', value: 'url("te,st")', args: ['te,st'] },
'test quoted'
);
test_parse_background_image(
'url(te,st)',
{ prefix: '', method: 'url', value: 'url(te,st)', args: ['te,st'] },
'test quoted'
);
test_parse_background_image(
'url(test)',
{ prefix: '', method: 'url', value: 'url(test)', args: ['test'] },
'basic url'
);
test_parse_background_image(
'url("test")',
{ prefix: '', method: 'url', value: 'url("test")', args: ['test'] },
'quoted url'
);
test_parse_background_image(
'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
{
prefix: '', method: 'url',
value: 'url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)',
args: ['data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7']
},
'data url'
);
test_parse_background_image(
'linear-gradient(red,black)',
{ prefix: '', method: 'linear-gradient', value: 'linear-gradient(red,black)', args: ['red','black'] },
'linear-gradient'
);
test_parse_background_image(
'linear-gradient(top,rgb(255,0,0),rgb(0,0,0))',
{
prefix: '', method: 'linear-gradient',
value: 'linear-gradient(top,rgb(255,0,0),rgb(0,0,0))',
args: ['top', 'rgb(255,0,0)', 'rgb(0,0,0)']
},
'linear-gradient w/ rgb()'
);
test_parse_background_image(
'-webkit-linear-gradient(red,black)',
{
prefix: '-webkit-', method: 'linear-gradient',
value: '-webkit-linear-gradient(red,black)',
args: ['red','black']
},
'prefixed linear-gradient'
);
test_parse_background_image(
'linear-gradient(red,black), url(test), url("test"),\n none, ', [
{ prefix: '', method: 'linear-gradient', value: 'linear-gradient(red,black)', args: ['red','black'] },
{ prefix: '', method: 'url', value: 'url(test)', args: ['test'] },
{ prefix: '', method: 'url', value: 'url("test")', args: ['test'] },
{ prefix: '', method: 'none', value: 'none', args: [] }
],
'multiple backgrounds'
);
});
function test_parse_background_image(value, expected, name) {
deepEqual(
_html2canvas.Util.parseBackgroundImage(value),
Array.isArray(expected) ? expected : [expected],
name
);
}
// TODO add backgroundPosition % tests
});

View File

@ -0,0 +1,329 @@
// declare vars (preventing JSHint messages)
/* this breaks the testing for IE<9
var test = test || function(){},
QUnit = QUnit || {},
_html2canvas = _html2canvas || {};
*/
//module("Generate"); // <- overwrites predefined CSS-module ?
$(function() {
var propsToTest = {},
numDivs = {},
expected = {};
propsToTest['Generate.parseGradient'] = ["backgroundImage"];
numDivs['Generate.parseGradient'] = $('#backgroundGradients div').length;
expected['Generate.parseGradient'] = [
{
type: 'linear',
x0: 0,
y0: 35,
x1: 50,
y1: 35,
colorStops: [
{
color: "rgb(255, 0, 0)",
stop: 0
},
{
color: "rgb(255, 255, 0)",
stop: 0.5
},
{
color: "rgb(0, 255, 0)",
stop: 1
}
]
},
{
type: 'linear',
x0: 0,
y0: 35,
x1: 50,
y1: 35,
colorStops: [
{
color: "rgb(206, 219, 233)",
stop: 0
},
{
color: "rgb(170, 197, 222)",
stop: 0.17
},
{
color: "rgb(97, 153, 199)",
stop: 0.5
},
{
color: "rgb(58, 132, 195)",
stop: 0.51
},
{
color: "rgb(65, 154, 214)",
stop: 0.59
},
{
color: "rgb(75, 184, 240)",
stop: 0.71
},
{
color: "rgb(58, 139, 194)",
stop: 0.84
},
{
color: "rgb(38, 85, 139)",
stop: 1
}
]
},
{
type: "linear",
x0: 25,
y0: 0,
x1: 25,
y1: 70,
colorStops: [
{
color: "rgb(240, 183, 161)",
stop: 0
},
{
color: "rgb(140, 51, 16)",
stop: 0.5
},
{
color: "rgb(117, 34, 1)",
stop: 0.51
},
{
color: "rgb(191, 110, 78)",
stop: 1
}
]
},
{
type: "ellipse",
x0: 0,
y0: 0,
x1: 50,
y1: 70,
cx: 37.5,
cy: 13.3,
rx: 12.5,
ry: 13.3,
colorStops: [
{
color: "rgb(171, 171, 171)",
stop: 0
},
{
color: "rgb(0, 0, 255)",
stop: 0.33
},
{
color: "rgb(153, 31, 31)",
stop: 1
}
]
},
{
type: "circle",
x0: 0,
y0: 0,
x1: 50,
y1: 70,
cx: 37.5,
cy: 13.3,
rx: 18.25212316416915,
ry: 18.25212316416915,
colorStops: [
{
color: "rgb(171, 171, 171)",
stop: 0
},
{
color: "rgb(0, 0, 255)",
stop: 0.33
},
{
color: "rgb(153, 31, 31)",
stop: 1
}
]
},
{
type: "ellipse",
x0: 0,
y0: 0,
x1: 50,
y1: 70,
cx: 37.5,
cy: 13.3,
rx: 37.5,
ry: 56.7,
colorStops: [
{
color: "rgb(171, 171, 171)",
stop: 0
},
{
color: "rgb(0, 0, 255)",
stop: 0.33
},
{
color: "rgb(153, 31, 31)",
stop: 1
}
]
},
{
type: "circle",
x0: 0,
y0: 0,
x1: 50,
y1: 70,
cx: 37.5,
cy: 13.3,
rx: 67.97896733549283,
ry: 67.97896733549283,
colorStops: [
{
color: "rgb(171, 171, 171)",
stop: 0
},
{
color: "rgb(0, 0, 255)",
stop: 0.33
},
{
color: "rgb(153, 31, 31)",
stop: 1
}
]
},
{
type: "ellipse",
x0: 0,
y0: 0,
x1: 50,
y1: 70,
cx: 37.5,
cy: 13.3,
rx: 12.5,
ry: 13.3,
colorStops: [
{
color: "rgb(171, 171, 171)",
stop: 0
},
{
color: "rgb(0, 0, 255)",
stop: 0.33
},
{
color: "rgb(153, 31, 31)",
stop: 1
}
]
},
{
type: "circle",
x0: 0,
y0: 0,
x1: 50,
y1: 70,
cx: 37.5,
cy: 13.3,
rx: 67.97896733549283,
ry: 67.97896733549283,
colorStops: [
{
color: "rgb(171, 171, 171)",
stop: 0
},
{
color: "rgb(0, 0, 255)",
stop: 0.33
},
{
color: "rgb(153, 31, 31)",
stop: 1
}
]
}
];
test('Generate.parseGradient', propsToTest['Generate.parseGradient'].length * numDivs['Generate.parseGradient'], function() {
$('#backgroundGradients div').each(function(i, el) {
$.each(propsToTest['Generate.parseGradient'], function(s, prop) {
var src, gradient;
src = _html2canvas.Util.getCSS(el, prop);
if (/^(-webkit|-o|-moz|-ms|linear)-/.test(src)) {
gradient = _html2canvas.Generate.parseGradient(src, {
width: 50,
height: 70
});
//QUnit.deepEqual(gradient, expected['Generate.parseGradient'][i], 'Parsed gradient; got: ' + JSON.stringify(gradient));
QUnit.deepEqual(gradient, expected['Generate.parseGradient'][i], 'Parsed gradient with CSS: ' + src);
} else {
QUnit.ok(true, 'No CSS Background Gradient support');
}
});
});
});
propsToTest['Generate.Gradient'] = ["backgroundImage"];
numDivs['Generate.Gradient'] = $('#backgroundGradients div').length;
test('Generate.Gradient', propsToTest['Generate.Gradient'].length * numDivs['Generate.Gradient'], function() {
$('#backgroundGradients div').each(function(i, el) {
$.each(propsToTest['Generate.Gradient'], function(s, prop) {
var src, img, canvas, ctx, id, data, len, red, green, blue, overallColor = 0;
src = _html2canvas.Util.getCSS(el, prop);
if (/^(-webkit|-o|-moz|-ms|linear)-/.test(src)) {
img = _html2canvas.Generate.Gradient(src, {
width: 50,
height: 50
});
canvas = document.createElement('canvas');
canvas.width = 50;
canvas.height = 50;
ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
id = ctx.getImageData(0, 0, 50, 50);
data = id.data;
len = data.length;
//console.log(img);
for (var i = 0; i < len; i += 4) {
red = data[i]; // red
green = data[i + 1]; // green
blue = data[i + 2]; // blue
// i+3 is alpha (the fourth element)
overallColor += (red + green + blue) / 3;
}
overallColor /= (len / 4);
QUnit.notEqual(overallColor, 255, 'Background Gradient drawn with CSS: ' + src);
} else {
QUnit.ok(true, 'No CSS Background Gradient support');
}
});
});
});
});

46
tests/qunit/unit/utils.js Normal file
View File

@ -0,0 +1,46 @@
$(function() {
var el = $('#qunit-fixture');
test('Children()', 1, function() {
var arr = [],
cont = el.contents();
$.each(cont, function(i,e){
arr.push(e);
});
// text nodes differ
QUnit.equal( _html2canvas.Util.Children(el[0]), arr, "Util.Children === jQuery.children()" );
});
test('resizeBounds', function(){
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 100, 100),
{ width: 100, height: 100 },
'no resize'
);
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 2, 100),
{ width: 20, height: 100 },
'stretch'
);
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 2, 100, 'contain'),
{ width: 2, height: 2 },
'contain'
);
QUnit.deepEqual(
_html2canvas.Util.resizeBounds(100, 100, 2, 100, 'cover'),
{ width: 100, height: 100 },
'contain'
);
});
});

37
tests/rangetest.html Normal file
View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<title>Range tests</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style>
#tests {
font-family:Arial;
}
</style>
</head>
<body>
<div id="tests"></div>
<script>
var div = document.getElementById("tests"), item, range, textNode, bounds;
for (var i = 6; i < 72; i++) {
item = document.createElement("div");
item.style.fontSize = i + "px";
item.style.lineHeight = (10 + i * 2) + "px";
textNode = document.createTextNode(i);
item.appendChild(textNode);
div.appendChild(item);
range = document.createRange();
range.setStart(textNode, 0);
range.setEnd(textNode, i.toString().length);
bounds = range.getBoundingClientRect();
textNode.nodeValue += " " + bounds.height + " " + bounds.bottom + (i % 3 === 0);
}
</script>
<script src="test.js"></script>
</body>
</html>

35
tests/readme.md Normal file
View File

@ -0,0 +1,35 @@
<table><thead><tr><td></td><th>chrome<br />23.0.1271.97</th><th>firefox<br />12.0</th><th>iexplorer<br />9</th></tr></thead><tbody>
<tr><td>background/clip.html</td><td>100%</td><td>100%</td><td>99.89%</td></tr>
<tr><td>background/encoded.html</td><td>100%</td><td>100%</td><td>100%</td></tr>
<tr><td>background/linear-gradient.html</td><td>89.87%</td><td>90.73%</td><td>100%</td></tr>
<tr><td>background/multi.html</td><td>100%</td><td>100%</td><td>99.93%</td></tr>
<tr><td>background/position.html</td><td>100%</td><td>100%</td><td>99.87%</td></tr>
<tr><td>background/radial-gradient.html</td><td>73.23%</td><td>70.32%</td><td>94.02%</td></tr>
<tr><td>background/repeat.html</td><td>100%</td><td>100%</td><td>99.92%</td></tr>
<tr><td>border/dashed.html</td><td>96.45%</td><td>98.38%</td><td>97.7%</td></tr>
<tr><td>border/dotted.html</td><td>97.41%</td><td>96.46%</td><td>95.93%</td></tr>
<tr><td>border/double.html</td><td>97.96%</td><td>97.87%</td><td>97.95%</td></tr>
<tr><td>border/radius.html</td><td>99.74%</td><td>99.77%</td><td>99.75%</td></tr>
<tr><td>border/solid.html</td><td>99.97%</td><td>99.97%</td><td>99.98%</td></tr>
<tr><td>forms.html</td><td>95.96%</td><td>94.55%</td><td>95.01%</td></tr>
<tr><td>images/canvas.html</td><td>99.86%</td><td>100%</td><td>100%</td></tr>
<tr><td>images/cross-origin.html</td><td>97.99%</td><td>97.58%</td><td>99.35%</td></tr>
<tr><td>images/empty.html</td><td>99.86%</td><td>99.87%</td><td>99.85%</td></tr>
<tr><td>images/images.html</td><td>83.72%</td><td>96.93%</td><td>55.09%</td></tr>
<tr><td>images/svg.html</td><td>99.92%</td><td>96.79%</td><td>99.93%</td></tr>
<tr><td>list/decimal-leading-zero.html</td><td>99.63%</td><td>99.72%</td><td>35.88%</td></tr>
<tr><td>list/decimal.html</td><td>99.64%</td><td>99.73%</td><td>35.89%</td></tr>
<tr><td>list/lower-alpha.html</td><td>99.65%</td><td>99.73%</td><td>35.89%</td></tr>
<tr><td>list/upper-roman.html</td><td>99.45%</td><td>99.61%</td><td>35.94%</td></tr>
<tr><td>overflow.html</td><td>96.85%</td><td>97.49%</td><td>96.5%</td></tr>
<tr><td>pseudoelements.html</td><td>97.36%</td><td>97.94%</td><td>99.37%</td></tr>
<tr><td>text/chinese.html</td><td>99.75%</td><td>99.74%</td><td>65.76%</td></tr>
<tr><td>text/linethrough.html</td><td>97.14%</td><td>94.12%</td><td>47.08%</td></tr>
<tr><td>text/text.html</td><td>95.71%</td><td>94.67%</td><td>85.01%</td></tr>
<tr><td>text/underline-lineheight.html</td><td>97.06%</td><td>92.35%</td><td>53%</td></tr>
<tr><td>text/underline.html</td><td>97.65%</td><td>93.5%</td><td>47.02%</td></tr>
<tr><td>visibility.html</td><td>99.19%</td><td>98.92%</td><td>99.39%</td></tr>
<tr><td>zindex/z-index1.html</td><td>96.99%</td><td>99.27%</td><td>99.44%</td></tr>
<tr><td>zindex/z-index2.html</td><td>95.85%</td><td>98.06%</td><td>97.72%</td></tr>
<tr><td>zindex/z-index3.html</td><td>98.6%</td><td>98.29%</td><td>98.56%</td></tr>
</tbody></table>

2
tests/results/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

272
tests/selenium.js Normal file
View File

@ -0,0 +1,272 @@
(function(){
"use strict;"
var webdriver = require("webdriver.js").webdriver,
http = require("http"),
url = require("url"),
path = require("path"),
base64_arraybuffer = require('base64-arraybuffer'),
PNG = require('png-js'),
fs = require("fs");
function createServer(port) {
return http.createServer(function(request, response) {
var uri = url.parse(request.url).pathname,
filename = path.join(process.cwd(), uri);
fs.exists(filename, function(exists) {
if(!exists) {
response.writeHead(404, {
"Content-Type": "text/plain"
});
response.write("404 Not Found\n");
response.end();
return;
}
if (fs.statSync(filename).isDirectory()) filename += '/index.html';
fs.readFile(filename, "binary", function(err, file) {
if(err) {
response.writeHead(500, {
"Content-Type": "text/plain"
});
response.write(err + "\n");
response.end();
return;
}
response.writeHead(200);
response.write(file, "binary");
response.end();
});
});
}).listen(port);
}
function walkDir(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var i = 0;
(function next() {
var file = list[i++];
if (!file) return done(null, results);
file = dir + '/' + file;
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walkDir(file, function(err, res) {
results = results.concat(res);
next();
});
} else {
results.push(file);
next();
}
});
})();
});
};
function getPixelArray(base64, func) {
var arraybuffer = base64_arraybuffer.decode(base64);
(new PNG(arraybuffer)).decode(func);
}
function getBaselineFiles() {
return fs.readdirSync("tests/results/").filter(function(name) {
return /\.baseline$/.test(name);
}).map(function(item) {
return "tests/results/" + item;
});
}
function testPage(browser, url, done) {
browser.url(url)
.$(".html2canvas", 5000, function(){
this.execute(function(){
var canvas = $('.html2canvas')[0];
return canvas.toDataURL("image/png").substring(22);
},[], function(dataurl) {
getPixelArray(dataurl, function(h2cPixels) {
browser.screenshot(function(base64){
getPixelArray(base64, function(screenPixels) {
var len = h2cPixels.length, index = 0, diff = 0;
for (; index < len; index++) {
if (screenPixels[index] - h2cPixels[index] !== 0) {
diff++;
}
}
done(100 - (Math.round((diff/h2cPixels.length) * 10000) / 100));
});
})
});
});
});
}
var writeResultFile = function(filename, json, append) {
fs.writeFile(filename + (append || ""), json);
};
var openResultFile = function(stats, browser) {
var tests = stats[browser].tests,
filename = "tests/results/" + browser + ".json",
write = writeResultFile.bind(null, filename, JSON.stringify(stats[browser]));
fs.exists(filename, function(exists) {
if(exists) {
fs.readFile(filename, "binary", parseResultFile.bind(null, tests, browser, write));
} else {
write();
}
});
};
var setColor = function(color, text) {
return [color, " * ", ((isNaN(text.amount)) ? "NEW" : text.amount + "%"), " ", text.test].join("");
};
var parseResultFile = function(tests, browser, createResultFile, err, file) {
if (err) throw err;
var data = JSON.parse(file),
improved = [],
regressed = [],
newItems = [],
colors = {
red: "\x1b[1;31m",
blue: "\x1b[1;36m",
violet: "\x1b[0;35m",
green: "\x1b[0;32m"
};
Object.keys(tests).forEach(function(test){
var testResult = tests[test],
dataResult = data.tests[test],
dataObject = {
amount: (Math.abs(testResult - dataResult) < 0.02) ? 0 : testResult - dataResult,
test: test
};
if (dataObject.amount > 0) {
improved.push(dataObject);
} else if (dataObject.amount < 0) {
regressed.push(dataObject);
} else if (dataResult === undefined) {
newItems.push(dataObject);
}
});
if (newItems.length > 0 || improved.length > 0 || regressed.length > 0) {
if (regressed.length === 0) {
createResultFile(".baseline");
}
console.log(colors.violet, "********************");
console.log((regressed.length > 0) ? colors.red : colors.green, browser);
improved.map(setColor.bind(null, colors.green))
.concat(regressed.map(setColor.bind(null, colors.red)))
.concat(newItems.map(setColor.bind(null, colors.blue)))
.forEach(function(item) {
console.log(item);
});
}
};
function handleResults(stats) {
Object.keys(stats).forEach(openResultFile.bind(null, stats));
}
function runBrowsers(pages){
var port = 5555,
stats = {},
browsers = ["chrome", "firefox", "internet explorer"],
browsersDone = 0,
server = createServer(port),
numPages = pages.length;
var browserDone = function() {
if (++browsersDone >= browsers.length) {
server.close();
handleResults(stats);
}
};
browsers.forEach(function(browserName){
var browser = new webdriver({
browser: browserName
}),
browserType;
browserName = browserName.replace("internet explorer", "iexplorer");
browser.status(function(browserInfo){
browserType = [browserName, browser.version, browserInfo.os.name.replace(/\s+/g, "-").toLowerCase()].join("-");
var date = new Date(),
obj = {
tests: {},
date: date.toISOString(),
version: browser.version
};
stats[browserType] = obj;
stats[browserName] = obj;
processPage(0);
});
function processPage(index) {
var page = pages[index++];
testPage(browser, "http://localhost:" + port + "/" + page + "?selenium", function(result) {
if (numPages > index) {
processPage(index);
} else {
browser.close(browserDone);
}
stats[browserType].tests[page] = result;
});
}
});
}
exports.tests = function() {
getBaselineFiles().forEach(fs.unlinkSync.bind(fs));
walkDir("tests/cases", function(err, results) {
if (err) throw err;
runBrowsers(results);
});
};
exports.baseline = function() {
getBaselineFiles().forEach(function(file) {
var newName = file.substring(0, file.length - 9);
fs.renameSync(file, newName);
console.log(newName, "created");
});
};
exports.markdown = function() {
var data = {}, html = "<table><thead><tr><td></td>",
browsers = ["chrome", "firefox", "iexplorer"];
browsers.forEach(function(browser) {
data[browser] = JSON.parse(fs.readFileSync("tests/results/" + browser + ".json"));
html += "<th>" + browser + "<br />" + data[browser].version + "</th>";
});
html += "</tr></thead><tbody>\n";
Object.keys(data[browsers[0]].tests).forEach(function(testFile) {
html += "<tr><td>" + testFile.substring(12) + "</td>";
browsers.forEach(function(browser) {
html += "<td>" + Math.round(data[browser].tests[testFile] * 100) / 100 + "%</td>";
});
html += "</tr>\n"
});
html += "</tbody></table>";
fs.writeFileSync("tests/readme.md", html);
};
})();

View File

@ -5,22 +5,32 @@
Released under MIT License
*/
var h2cSelector, h2cOptions;
(function(document, window) {
var scrStart = '<script type="text/javascript" src="', scrEnd = '"></script>';
document.write(scrStart + '../external/jquery-1.6.2.min.js' + scrEnd);
var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'plugins/jquery.plugin.html2canvas'], i;
for (i = 0; i < html2canvas.length; ++i) {
document.write(scrStart + '../src/' + html2canvas[i] + '.js' + scrEnd);
}
window.onload = function() {
if (window.setUp) {
window.setUp();
var srcStart = '<script type="text/javascript" src="', scrEnd = '"></script>';
document.write(srcStart + '/tests/assets/jquery-1.6.2.js' + scrEnd);
document.write(srcStart + '/tests/assets/jquery.plugin.html2canvas.js' + scrEnd);
var html2canvas = ['Core', 'Generate', 'Parse', 'Preload', 'Queue', 'Renderer', 'Util', 'Support', 'Font', 'renderers/Canvas'], i;
for (i = 0; i < html2canvas.length; ++i) {
document.write(srcStart + '/src/' + html2canvas[i] + '.js?' + Math.random() + scrEnd);
}
setTimeout(function() {
$(document.body).html2canvas({
logging: true,
profile: true
});
}, 100);
};
window.onload = function() {
h2cSelector = [document.body];
if (window.setUp) {
window.setUp();
}
setTimeout(function() {
$(h2cSelector).html2canvas($.extend({
flashcanvas: "../external/flashcanvas.min.js",
logging: true,
profile: true,
proxy: "http://html2canvas.appspot.com/query",
useCORS: true
}, h2cOptions));
}, 100);
};
}(document, window));

View File

@ -1,87 +0,0 @@
<!--
* @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="test.js"></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>

View File

@ -1,109 +0,0 @@
<!--
* @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="test.js"></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>

View File

@ -1,115 +0,0 @@
<!--
* @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="test.js"></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>

View File

@ -1 +0,0 @@
v0.32