1/* 2 * printThis v1.15.1 3 * @desc Printing plug-in for jQuery 4 * @author Jason Day 5 * 6 * Resources (based on): 7 * - jPrintArea: http://plugins.jquery.com/project/jPrintArea 8 * - jqPrint: https://github.com/permanenttourist/jquery.jqprint 9 * - Ben Nadal: http://www.bennadel.com/blog/1591-Ask-Ben-Print-Part-Of-A-Web-Page-With-jQuery.htm 10 * 11 * Licensed under the MIT licence: 12 * http://www.opensource.org/licenses/mit-license.php 13 * 14 * (c) Jason Day 2015-2019 15 * 16 * Usage: 17 * 18 * $("#mySelector").printThis({ 19 * debug: false, // show the iframe for debugging 20 * importCSS: true, // import parent page css 21 * importStyle: false, // import style tags 22 * printContainer: true, // grab outer container as well as the contents of the selector 23 * loadCSS: "path/to/my.css", // path to additional css file - use an array [] for multiple 24 * pageTitle: "", // add title to print page 25 * removeInline: false, // remove all inline styles from print elements 26 * removeInlineSelector: "body *", // custom selectors to filter inline styles. removeInline must be true 27 * printDelay: 333, // variable print delay 28 * header: null, // prefix to html 29 * footer: null, // postfix to html 30 * base: false, // preserve the BASE tag, or accept a string for the URL 31 * formValues: true, // preserve input/form values 32 * canvas: false, // copy canvas elements 33 * doctypeString: '...', // enter a different doctype for older markup 34 * removeScripts: false, // remove script tags from print content 35 * copyTagClasses: false // copy classes from the html & body tag 36 * beforePrintEvent: null, // callback function for printEvent in iframe 37 * beforePrint: null, // function called before iframe is filled 38 * afterPrint: null // function called before iframe is removed 39 * }); 40 * 41 * Notes: 42 * - the loadCSS will load additional CSS (with or without @media print) into the iframe, adjusting layout 43 */ 44; 45(function($) { 46 47 function appendContent($el, content) { 48 if (!content) return; 49 50 // Simple test for a jQuery element 51 $el.append(content.jquery ? content.clone() : content); 52 } 53 54 function appendBody($body, $element, opt) { 55 // Clone for safety and convenience 56 // Calls clone(withDataAndEvents = true) to copy form values. 57 var $content = $element.clone(opt.formValues); 58 59 if (opt.formValues) { 60 // Copy original select and textarea values to their cloned counterpart 61 // Makes up for inability to clone select and textarea values with clone(true) 62 copyValues($element, $content, 'select, textarea'); 63 } 64 65 if (opt.removeScripts) { 66 $content.find('script').remove(); 67 } 68 69 if (opt.printContainer) { 70 // grab $.selector as container 71 $content.appendTo($body); 72 } else { 73 // otherwise just print interior elements of container 74 $content.each(function() { 75 $(this).children().appendTo($body) 76 }); 77 } 78 } 79 80 // Copies values from origin to clone for passed in elementSelector 81 function copyValues(origin, clone, elementSelector) { 82 var $originalElements = origin.find(elementSelector); 83 84 clone.find(elementSelector).each(function(index, item) { 85 $(item).val($originalElements.eq(index).val()); 86 }); 87 } 88 89 var opt; 90 $.fn.printThis = function(options) { 91 opt = $.extend({}, $.fn.printThis.defaults, options); 92 var $element = this instanceof jQuery ? this : $(this); 93 94 var strFrameName = "printThis-" + (new Date()).getTime(); 95 96 if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) { 97 // Ugly IE hacks due to IE not inheriting document.domain from parent 98 // checks if document.domain is set by comparing the host name against document.domain 99 var iframeSrc = "javascript:document.write(\"<head><script>document.domain=\\\"" + document.domain + "\\\";</s" + "cript></head><body></body>\")"; 100 var printI = document.createElement('iframe'); 101 printI.name = "printIframe"; 102 printI.id = strFrameName; 103 printI.className = "MSIE"; 104 document.body.appendChild(printI); 105 printI.src = iframeSrc; 106 107 } else { 108 // other browsers inherit document.domain, and IE works if document.domain is not explicitly set 109 var $frame = $("<iframe id='" + strFrameName + "' name='printIframe' />"); 110 $frame.appendTo("body"); 111 } 112 113 var $iframe = $("#" + strFrameName); 114 115 // show frame if in debug mode 116 if (!opt.debug) $iframe.css({ 117 position: "absolute",
118 width: "0px", 119 height: "0px", 120 left: "-600px", 121 top: "-600px" 122 }); 123 124 // before print callback 125 if (typeof opt.beforePrint === "function") { 126 opt.beforePrint(); 127 } 128 129 // $iframe.ready() and $iframe.load were inconsistent between browsers 130 setTimeout(function() { 131 132 // Add doctype to fix the style difference between printing and render 133 function setDocType($iframe, doctype){ 134 var win, doc; 135 win = $iframe.get(0); 136 win = win.contentWindow || win.contentDocument || win; 137 doc = win.document || win.contentDocument || win; 138 doc.open(); 139 doc.write(doctype); 140 doc.close(); 141 } 142 143 if (opt.doctypeString){ 144 setDocType($iframe, opt.doctypeString); 145 } 146 147 var $doc = $iframe.contents(), 148 $head = $doc.find("head"), 149 $body = $doc.find("body"), 150 $base = $('base'), 151 baseURL; 152 153 // add base tag to ensure elements use the parent domain 154 if (opt.base === true && $base.length > 0) { 155 // take the base tag from the original page 156 baseURL = $base.attr('href'); 157 } else if (typeof opt.base === 'string') { 158 // An exact base string is provided 159 baseURL = opt.base; 160 } else { 161 // Use the page URL as the base 162 baseURL = document.location.protocol + '//' + document.location.host; 163 } 164 165 $head.append('<base href="' + baseURL + '">'); 166 167 // import page stylesheets 168 if (opt.importCSS) $("link[rel=stylesheet]").each(function() { 169 var href = $(this).attr("href"); 170 if (href) { 171 var media = $(this).attr("media") || "all"; 172 $head.append("<link type='text/css' rel='stylesheet' href='" + href + "' media='" + media + "'>"); 173 } 174 }); 175 176 // import style tags 177 if (opt.importStyle) $("style").each(function() { 178 $head.append(this.outerHTML); 179 }); 180 181 // add title of the page 182 if (opt.pageTitle) $head.append("<title>" + opt.pageTitle + "</title>"); 183 184 // import additional stylesheet(s) 185 if (opt.loadCSS) { 186 if ($.isArray(opt.loadCSS)) { 187 jQuery.each(opt.loadCSS, function(index, value) { 188 $head.append("<link type='text/css' rel='stylesheet' href='" + this + "'>"); 189 }); 190 } else { 191 $head.append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>"); 192 } 193 } 194 195 var pageHtml = $('html')[0]; 196 197 // CSS VAR in html tag when dynamic apply e.g. document.documentElement.style.setProperty("--foo", bar); 198 $doc.find('html').prop('style', pageHtml.style.cssText); 199 200 // copy 'root' tag classes 201 var tag = opt.copyTagClasses; 202 if (tag) { 203 tag = tag === true ? 'bh' : tag; 204 if (tag.indexOf('b') !== -1) { 205 $body.addClass($('body')[0].className); 206 } 207 if (tag.indexOf('h') !== -1) { 208 $doc.find('html').addClass(pageHtml.className); 209 } 210 } 211 212 // print header 213 appendContent($body, opt.header); 214 215 if (opt.canvas) { 216 // add canvas data-ids for easy access after cloning. 217 var canvasId = 0; 218 // .addBack('canvas') adds the top-level element if it is a canvas. 219 $element.find('canvas').addBack('canvas').each(function(){ 220 $(this).attr('data-printthis', canvasId++); 221 }); 222 } 223 224 appendBody($body, $element, opt); 225 226 if (opt.canvas) { 227 // Re-draw new canvases by referencing the originals 228 $body.find('canvas').each(function(){ 229 var cid = $(this).data('printthis'), 230 $src = $('[data-printthis="' + cid + '"]'); 231 232 this.getContext('2d').drawImage($src[0], 0, 0); 233 234 // Remove the markup from the original 235 if ($.isFunction($.fn.removeAttr)) { 236 $src.removeAttr('data-printthis'); 237 } else { 238 $.each($src, function(i, el) { 239 el.removeAttribute('data-printthis'); 240 }); 241 } 242 }); 243 } 244 245 // remove inline styles 246 if (opt.removeInline) { 247 // Ensure there is a selector, even if it's been mistakenly removed 248 var selector = opt.removeInlineSelector || '*'; 249 // $.removeAttr available jQuery 1.7+ 250 if ($.isFunction($.removeAttr)) { 251 $body.find(selector).removeAttr("style"); 252 } else { 253 $body.find(selector).attr("style", ""); 254 } 255 } 256 257 // print "footer" 258 appendContent($body, opt.footer); 259 260 // attach event handler function to beforePrint event 261 function attachOnBeforePrintEvent($iframe, beforePrintHandler) { 262 var win = $iframe.get(0); 263 win = win.contentWindow || win.contentDocument || win; 264 265 if (typeof beforePrintHandler === "function") { 266 if ('matchMedia' in win) { 267 win.matchMedia('print').addListener(function(mql) { 268 if(mql.matches) beforePrintHandler(); 269 }); 270 } else { 271 win.onbeforeprint = beforePrintHandler; 272 } 273 } 274 } 275 attachOnBeforePrintEvent($iframe, opt.beforePrintEvent); 276 277 setTimeout(function() { 278 if ($iframe.hasClass("MSIE")) { 279 // check if the iframe was created with the ugly hack 280 // and perform another ugly hack out of neccessity 281 window.frames["printIframe"].focus(); 282 $head.append("<script> window.print(); </s" + "cript>"); 283 } else { 284 // proper method 285 if (document.queryCommandSupported("print")) { 286 $iframe[0].contentWindow.document.execCommand("print", false, null); 287 } else { 288 $iframe[0].contentWindow.focus(); 289 $iframe[0].contentWindow.print(); 290 } 291 } 292 293 // remove iframe after print 294 if (!opt.debug) { 295 setTimeout(function() { 296 $iframe.remove(); 297 298 }, 1000); 299 } 300 301 // after print callback 302 if (typeof opt.afterPrint === "function") { 303 opt.afterPrint(); 304 } 305 306 }, opt.printDelay); 307 308 }, 333); 309 310 }; 311 312 // defaults 313 $.fn.printThis.defaults = { 314 debug: false, // show the iframe for debugging 315 importCSS: true, // import parent page css 316 importStyle: false, // import style tags 317 printContainer: true, // print outer container/$.selector 318 loadCSS: "", // path to additional css file - use an array [] for multiple 319 pageTitle: "", // add title to print page 320 removeInline: false, // remove inline styles from print elements 321 removeInlineSelector: "*", // custom selectors to filter inline styles. removeInline must be true 322 printDelay: 333, // variable print delay 323 header: null, // prefix to html 324 footer: null, // postfix to html 325 base: false, // preserve the BASE tag or accept a string for the URL 326 formValues: true, // preserve input/form values
327 canvas: false, // copy canvas content 328 doctypeString: '<!DOCTYPE html>', // enter a different doctype for older markup 329 removeScripts: false, // remove script tags from print content 330 copyTagClasses: false, // copy classes from the html & body tag 331 beforePrintEvent: null, // callback function for printEvent in iframe 332 beforePrint: null, // function called before iframe is filled 333 afterPrint: null // function called before iframe is removed 334 }; 335})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.