123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- "use strict";
- var _html2canvas = {},
- previousElement,
- computedCSS,
- html2canvas;
- _html2canvas.Util = {};
- _html2canvas.Util.log = function(a) {
- if (_html2canvas.logging && window.console && window.console.log) {
- window.console.log(a);
- }
- };
- _html2canvas.Util.trimText = (function(isNative){
- return function(input) {
- return isNative ? isNative.apply(input) : ((input || '') + '').replace( /^\s+|\s+$/g , '' );
- };
- })(String.prototype.trim);
- _html2canvas.Util.asFloat = function(v) {
- return parseFloat(v);
- };
- (function() {
- // TODO: support all possible length values
- var TEXT_SHADOW_PROPERTY = /((rgba|rgb)\([^\)]+\)(\s-?\d+px){0,})/g;
- var TEXT_SHADOW_VALUES = /(-?\d+px)|(#.+)|(rgb\(.+\))|(rgba\(.+\))/g;
- _html2canvas.Util.parseTextShadows = function (value) {
- if (!value || value === 'none') {
- return [];
- }
- // find multiple shadow declarations
- var shadows = value.match(TEXT_SHADOW_PROPERTY),
- results = [];
- for (var i = 0; shadows && (i < shadows.length); i++) {
- var s = shadows[i].match(TEXT_SHADOW_VALUES);
- results.push({
- color: s[0],
- offsetX: s[1] ? s[1].replace('px', '') : 0,
- offsetY: s[2] ? s[2].replace('px', '') : 0,
- blur: s[3] ? s[3].replace('px', '') : 0
- });
- }
- return results;
- };
- })();
- _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 (element) {
- var clientRect, bounds = {};
- if (element.getBoundingClientRect){
- clientRect = element.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 = element.offsetWidth;
- bounds.height = element.offsetHeight;
- }
- return bounds;
- };
- // TODO ideally, we'd want everything to go through this function instead of Util.Bounds,
- // but would require further work to calculate the correct positions for elements with offsetParents
- _html2canvas.Util.OffsetBounds = function (element) {
- var parent = element.offsetParent ? _html2canvas.Util.OffsetBounds(element.offsetParent) : {top: 0, left: 0};
- return {
- top: element.offsetTop + parent.top,
- bottom: element.offsetTop + element.offsetHeight + parent.top,
- left: element.offsetLeft + parent.left,
- width: element.offsetWidth,
- height: element.offsetHeight
- };
- };
- function toPX(element, attribute, value ) {
- var rsLeft = element.runtimeStyle && element.runtimeStyle[attribute],
- left,
- style = element.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
- // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
- // 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 ( !/^-?[0-9]+\.?[0-9]*(?:px)?$/i.test( value ) && /^-?\d/.test(value) ) {
- // Remember the original values
- left = style.left;
- // Put in the new values to get a computed value out
- if (rsLeft) {
- element.runtimeStyle.left = element.currentStyle.left;
- }
- style.left = attribute === "fontSize" ? "1em" : (value || 0);
- value = style.pixelLeft + "px";
- // Revert the changed values
- style.left = left;
- if (rsLeft) {
- element.runtimeStyle.left = rsLeft;
- }
- }
- if (!/^(thin|medium|thick)$/i.test(value)) {
- return Math.round(parseFloat(value)) + "px";
- }
- return value;
- }
- function asInt(val) {
- return parseInt(val, 10);
- }
- function parseBackgroundSizePosition(value, element, attribute, index) {
- value = (value || '').split(',');
- value = value[index || 0] || value[0] || 'auto';
- value = _html2canvas.Util.trimText(value).split(' ');
- if(attribute === 'backgroundSize' && (!value[0] || value[0].match(/cover|contain|auto/))) {
- //these values will be handled in the parent function
- } else {
- value[0] = (value[0].indexOf( "%" ) === -1) ? toPX(element, attribute + "X", value[0]) : value[0];
- if(value[1] === undefined) {
- if(attribute === 'backgroundSize') {
- value[1] = 'auto';
- return value;
- } else {
- // IE 9 doesn't return double digit always
- value[1] = value[0];
- }
- }
- value[1] = (value[1].indexOf("%") === -1) ? toPX(element, attribute + "Y", value[1]) : value[1];
- }
- return value;
- }
- _html2canvas.Util.getCSS = function (element, attribute, index) {
- if (previousElement !== element) {
- computedCSS = document.defaultView.getComputedStyle(element, null);
- }
- var value = computedCSS[attribute];
- if (/^background(Size|Position)$/.test(attribute)) {
- return parseBackgroundSizePosition(value, element, attribute, index);
- } else if (/border(Top|Bottom)(Left|Right)Radius/.test(attribute)) {
- var arr = value.split(" ");
- if (arr.length <= 1) {
- arr[1] = arr[0];
- }
- return arr.map(asInt);
- }
- return value;
- };
- _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 {
- width: output_width,
- height: output_height
- };
- };
- 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;
- }
- 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 (/contain|cover/.test(bgposition[0])) {
- 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) {
- _html2canvas.Util.log("html2canvas.Util.Children failed with exception: " + ex.message);
- children = [];
- }
- return children;
- };
- _html2canvas.Util.isTransparent = function(backgroundColor) {
- return (backgroundColor === "transparent" || backgroundColor === "rgba(0, 0, 0, 0)");
- };
|