Commit bdc78148a67dc05443285f442305a1901c09849e
1 parent
3b1703b5
Exists in
master
and in
2 other branches
Print js plugin included
Showing
1 changed file
with
304 additions
and
0 deletions
Show diff stats
| ... | ... | @@ -0,0 +1,304 @@ |
| 1 | +/* | |
| 2 | + * printThis v1.10.0 | |
| 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 | |
| 15 | + * | |
| 16 | + * Usage: | |
| 17 | + * | |
| 18 | + * $("#mySelector").printThis({ | |
| 19 | + * debug: false, // show the iframe for debugging | |
| 20 | + * importCSS: true, // import 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 - us an array [] for multiple | |
| 24 | + * pageTitle: "", // add title to print page | |
| 25 | + * removeInline: false, // remove all inline styles from print elements | |
| 26 | + * printDelay: 333, // variable print delay | |
| 27 | + * header: null, // prefix to html | |
| 28 | + * footer: null, // postfix to html | |
| 29 | + * base: false, // preserve the BASE tag, or accept a string for the URL | |
| 30 | + * formValues: true, // preserve input/form values | |
| 31 | + * canvas: false, // copy canvas elements (experimental) | |
| 32 | + * doctypeString: '...', // enter a different doctype for older markup | |
| 33 | + * removeScripts: false // remove script tags from print content | |
| 34 | + * }); | |
| 35 | + * | |
| 36 | + * Notes: | |
| 37 | + * - the loadCSS will load additional css (with or without @media print) into the iframe, adjusting layout | |
| 38 | + */ | |
| 39 | +; | |
| 40 | +(function($) { | |
| 41 | + | |
| 42 | + function appendContent($el, content) { | |
| 43 | + if (!content) return; | |
| 44 | + | |
| 45 | + // Simple test for a jQuery element | |
| 46 | + $el.append(content.jquery ? content.clone() : content); | |
| 47 | + } | |
| 48 | + | |
| 49 | + function appendBody($body, $element, opt) { | |
| 50 | + // Clone for safety and convenience | |
| 51 | + var $content = $element.clone(); | |
| 52 | + | |
| 53 | + if (opt.removeScripts) { | |
| 54 | + $content.find('script').remove(); | |
| 55 | + } | |
| 56 | + | |
| 57 | + if (opt.printContainer) { | |
| 58 | + // grab $.selector as container | |
| 59 | + $body.append($("<div/>").html($content).html()); | |
| 60 | + } else { | |
| 61 | + // otherwise just print interior elements of container | |
| 62 | + $content.each(function() { | |
| 63 | + $body.append($(this).html()); | |
| 64 | + }); | |
| 65 | + } | |
| 66 | + } | |
| 67 | + | |
| 68 | + var opt; | |
| 69 | + $.fn.printThis = function(options) { | |
| 70 | + opt = $.extend({}, $.fn.printThis.defaults, options); | |
| 71 | + var $element = this instanceof jQuery ? this : $(this); | |
| 72 | + | |
| 73 | + var strFrameName = "printThis-" + (new Date()).getTime(); | |
| 74 | + | |
| 75 | + if (window.location.hostname !== document.domain && navigator.userAgent.match(/msie/i)) { | |
| 76 | + // Ugly IE hacks due to IE not inheriting document.domain from parent | |
| 77 | + // checks if document.domain is set by comparing the host name against document.domain | |
| 78 | + var iframeSrc = "javascript:document.write(\"<head><script>document.domain=\\\"" + document.domain + "\\\";</s" + "cript></head><body></body>\")"; | |
| 79 | + var printI = document.createElement('iframe'); | |
| 80 | + printI.name = "printIframe"; | |
| 81 | + printI.id = strFrameName; | |
| 82 | + printI.className = "MSIE"; | |
| 83 | + document.body.appendChild(printI); | |
| 84 | + printI.src = iframeSrc; | |
| 85 | + | |
| 86 | + } else { | |
| 87 | + // other browsers inherit document.domain, and IE works if document.domain is not explicitly set | |
| 88 | + var $frame = $("<iframe id='" + strFrameName + "' name='printIframe' />"); | |
| 89 | + $frame.appendTo("body"); | |
| 90 | + } | |
| 91 | + | |
| 92 | + var $iframe = $("#" + strFrameName); | |
| 93 | + | |
| 94 | + // show frame if in debug mode | |
| 95 | + if (!opt.debug) $iframe.css({ | |
| 96 | + position: "absolute", | |
| 97 | + width: "0px", | |
| 98 | + height: "0px", | |
| 99 | + left: "-600px", | |
| 100 | + top: "-600px" | |
| 101 | + }); | |
| 102 | + | |
| 103 | + // $iframe.ready() and $iframe.load were inconsistent between browsers | |
| 104 | + setTimeout(function() { | |
| 105 | + | |
| 106 | + // Add doctype to fix the style difference between printing and render | |
| 107 | + function setDocType($iframe, doctype){ | |
| 108 | + var win, doc; | |
| 109 | + win = $iframe.get(0); | |
| 110 | + win = win.contentWindow || win.contentDocument || win; | |
| 111 | + doc = win.document || win.contentDocument || win; | |
| 112 | + doc.open(); | |
| 113 | + doc.write(doctype); | |
| 114 | + doc.close(); | |
| 115 | + } | |
| 116 | + | |
| 117 | + if (opt.doctypeString){ | |
| 118 | + setDocType($iframe, opt.doctypeString); | |
| 119 | + } | |
| 120 | + | |
| 121 | + var $doc = $iframe.contents(), | |
| 122 | + $head = $doc.find("head"), | |
| 123 | + $body = $doc.find("body"), | |
| 124 | + $base = $('base'), | |
| 125 | + baseURL; | |
| 126 | + | |
| 127 | + // add base tag to ensure elements use the parent domain | |
| 128 | + if (opt.base === true && $base.length > 0) { | |
| 129 | + // take the base tag from the original page | |
| 130 | + baseURL = $base.attr('href'); | |
| 131 | + } else if (typeof opt.base === 'string') { | |
| 132 | + // An exact base string is provided | |
| 133 | + baseURL = opt.base; | |
| 134 | + } else { | |
| 135 | + // Use the page URL as the base | |
| 136 | + baseURL = document.location.protocol + '//' + document.location.host; | |
| 137 | + } | |
| 138 | + | |
| 139 | + $head.append('<base href="' + baseURL + '">'); | |
| 140 | + | |
| 141 | + // import page stylesheets | |
| 142 | + if (opt.importCSS) $("link[rel=stylesheet]").each(function() { | |
| 143 | + var href = $(this).attr("href"); | |
| 144 | + if (href) { | |
| 145 | + var media = $(this).attr("media") || "all"; | |
| 146 | + $head.append("<link type='text/css' rel='stylesheet' href='" + href + "' media='" + media + "'>"); | |
| 147 | + } | |
| 148 | + }); | |
| 149 | + | |
| 150 | + // import style tags | |
| 151 | + if (opt.importStyle) $("style").each(function() { | |
| 152 | + $(this).clone().appendTo($head); | |
| 153 | + }); | |
| 154 | + | |
| 155 | + // add title of the page | |
| 156 | + if (opt.pageTitle) $head.append("<title>" + opt.pageTitle + "</title>"); | |
| 157 | + | |
| 158 | + // import additional stylesheet(s) | |
| 159 | + if (opt.loadCSS) { | |
| 160 | + if ($.isArray(opt.loadCSS)) { | |
| 161 | + jQuery.each(opt.loadCSS, function(index, value) { | |
| 162 | + $head.append("<link type='text/css' rel='stylesheet' href='" + this + "'>"); | |
| 163 | + }); | |
| 164 | + } else { | |
| 165 | + $head.append("<link type='text/css' rel='stylesheet' href='" + opt.loadCSS + "'>"); | |
| 166 | + } | |
| 167 | + } | |
| 168 | + | |
| 169 | + // print header | |
| 170 | + appendContent($body, opt.header); | |
| 171 | + | |
| 172 | + if (opt.canvas) { | |
| 173 | + // add canvas data-ids for easy access after cloning. | |
| 174 | + var canvasId = 0; | |
| 175 | + $element.find('canvas').each(function(){ | |
| 176 | + $(this).attr('data-printthis', canvasId++); | |
| 177 | + }); | |
| 178 | + } | |
| 179 | + | |
| 180 | + appendBody($body, $element, opt); | |
| 181 | + | |
| 182 | + if (opt.canvas) { | |
| 183 | + // Re-draw new canvases by referencing the originals | |
| 184 | + $body.find('canvas').each(function(){ | |
| 185 | + var cid = $(this).data('printthis'), | |
| 186 | + $src = $('[data-printthis="' + cid + '"]'); | |
| 187 | + | |
| 188 | + this.getContext('2d').drawImage($src[0], 0, 0); | |
| 189 | + | |
| 190 | + // Remove the markup from the original | |
| 191 | + $src.removeData('printthis'); | |
| 192 | + }); | |
| 193 | + } | |
| 194 | + | |
| 195 | + // capture form/field values | |
| 196 | + if (opt.formValues) { | |
| 197 | + // loop through inputs | |
| 198 | + var $input = $element.find('input'); | |
| 199 | + if ($input.length) { | |
| 200 | + $input.each(function() { | |
| 201 | + var $this = $(this), | |
| 202 | + $name = $(this).attr('name'), | |
| 203 | + $checker = $this.is(':checkbox') || $this.is(':radio'), | |
| 204 | + $iframeInput = $doc.find('input[name="' + $name + '"]'), | |
| 205 | + $value = $this.val(); | |
| 206 | + | |
| 207 | + // order matters here | |
| 208 | + if (!$checker) { | |
| 209 | + $iframeInput.val($value); | |
| 210 | + } else if ($this.is(':checked')) { | |
| 211 | + if ($this.is(':checkbox')) { | |
| 212 | + $iframeInput.attr('checked', 'checked'); | |
| 213 | + } else if ($this.is(':radio')) { | |
| 214 | + $doc.find('input[name="' + $name + '"][value="' + $value + '"]').attr('checked', 'checked'); | |
| 215 | + } | |
| 216 | + } | |
| 217 | + | |
| 218 | + }); | |
| 219 | + } | |
| 220 | + | |
| 221 | + // loop through selects | |
| 222 | + var $select = $element.find('select'); | |
| 223 | + if ($select.length) { | |
| 224 | + $select.each(function() { | |
| 225 | + var $this = $(this), | |
| 226 | + $name = $(this).attr('name'), | |
| 227 | + $value = $this.val(); | |
| 228 | + $doc.find('select[name="' + $name + '"]').val($value); | |
| 229 | + }); | |
| 230 | + } | |
| 231 | + | |
| 232 | + // loop through textareas | |
| 233 | + var $textarea = $element.find('textarea'); | |
| 234 | + if ($textarea.length) { | |
| 235 | + $textarea.each(function() { | |
| 236 | + var $this = $(this), | |
| 237 | + $name = $(this).attr('name'), | |
| 238 | + $value = $this.val(); | |
| 239 | + $doc.find('textarea[name="' + $name + '"]').val($value); | |
| 240 | + }); | |
| 241 | + } | |
| 242 | + } // end capture form/field values | |
| 243 | + | |
| 244 | + // remove inline styles | |
| 245 | + if (opt.removeInline) { | |
| 246 | + // $.removeAttr available jQuery 1.7+ | |
| 247 | + if ($.isFunction($.removeAttr)) { | |
| 248 | + $doc.find("body *").removeAttr("style"); | |
| 249 | + } else { | |
| 250 | + $doc.find("body *").attr("style", ""); | |
| 251 | + } | |
| 252 | + } | |
| 253 | + | |
| 254 | + // print "footer" | |
| 255 | + appendContent($body, opt.footer); | |
| 256 | + | |
| 257 | + setTimeout(function() { | |
| 258 | + if ($iframe.hasClass("MSIE")) { | |
| 259 | + // check if the iframe was created with the ugly hack | |
| 260 | + // and perform another ugly hack out of neccessity | |
| 261 | + window.frames["printIframe"].focus(); | |
| 262 | + $head.append("<script> window.print(); </s" + "cript>"); | |
| 263 | + } else { | |
| 264 | + // proper method | |
| 265 | + if (document.queryCommandSupported("print")) { | |
| 266 | + $iframe[0].contentWindow.document.execCommand("print", false, null); | |
| 267 | + } else { | |
| 268 | + $iframe[0].contentWindow.focus(); | |
| 269 | + $iframe[0].contentWindow.print(); | |
| 270 | + } | |
| 271 | + } | |
| 272 | + | |
| 273 | + // remove iframe after print | |
| 274 | + if (!opt.debug) { | |
| 275 | + setTimeout(function() { | |
| 276 | + $iframe.remove(); | |
| 277 | + }, 1000); | |
| 278 | + } | |
| 279 | + | |
| 280 | + }, opt.printDelay); | |
| 281 | + | |
| 282 | + }, 333); | |
| 283 | + | |
| 284 | + }; | |
| 285 | + | |
| 286 | + // defaults | |
| 287 | + $.fn.printThis.defaults = { | |
| 288 | + debug: false, // show the iframe for debugging | |
| 289 | + importCSS: true, // import parent page css | |
| 290 | + importStyle: false, // import style tags | |
| 291 | + printContainer: true, // print outer container/$.selector | |
| 292 | + loadCSS: "", // load an additional css file - load multiple stylesheets with an array [] | |
| 293 | + pageTitle: "", // add title to print page | |
| 294 | + removeInline: false, // remove all inline styles | |
| 295 | + printDelay: 333, // variable print delay | |
| 296 | + header: null, // prefix to html | |
| 297 | + footer: null, // postfix to html | |
| 298 | + formValues: true, // preserve input/form values | |
| 299 | + canvas: false, // copy canvas content (experimental) | |
| 300 | + base: false, // preserve the BASE tag, or accept a string for the URL | |
| 301 | + doctypeString: '<!DOCTYPE html>', // html doctype | |
| 302 | + removeScripts: false // remove script tags before appending | |
| 303 | + }; | |
| 304 | +})(jQuery); | ... | ... |