jQuery.print

jQuery.print库,网页打印库

Dette script bør ikke installeres direkte. Det er et bibliotek, som andre scripts kan inkludere med metadirektivet // @require https://update.greatest.deepsurf.us/scripts/38955/939949/jQueryprint.js

  1. /* @license
  2. * jQuery.print, version 1.6.2
  3. * Licence: CC-By (http://creativecommons.org/licenses/by/3.0/)
  4. *--------------------------------------------------------------------------*/
  5. (function ($) {
  6. "use strict";
  7. // A nice closure for our definitions
  8.  
  9. function jQueryCloneWithSelectAndTextAreaValues(elmToClone, withDataAndEvents, deepWithDataAndEvents) {
  10. // Replacement jQuery clone that also clones the values in selects and textareas as jQuery doesn't for performance reasons - https://stackoverflow.com/questions/742810/clone-isnt-cloning-select-values
  11. // Based on https://github.com/spencertipping/jquery.fix.clone
  12. var $elmToClone = $(elmToClone),
  13. $result = $elmToClone.clone(withDataAndEvents, deepWithDataAndEvents),
  14. $myTextareas = $elmToClone.find('textarea').add($elmToClone.filter('textarea')),
  15. $resultTextareas = $result.find('textarea').add($result.filter('textarea')),
  16. $mySelects = $elmToClone.find('select').add($elmToClone.filter('select')),
  17. $resultSelects = $result.find('select').add($result.filter('select')),
  18. $myCanvas = $elmToClone.find('canvas').add($elmToClone.filter('canvas')),
  19. $resultCanvas = $result.find('canvas').add($result.filter('canvas')),
  20. i, l, j, m, myCanvasContext;
  21.  
  22. for (i = 0, l = $myTextareas.length; i < l; ++i) {
  23. $($resultTextareas[i]).val($($myTextareas[i]).val());
  24. }
  25. for (i = 0, l = $mySelects.length; i < l; ++i) {
  26. for (j = 0, m = $mySelects[i].options.length; j < m; ++j) {
  27. if ($mySelects[i].options[j].selected === true) {
  28. $resultSelects[i].options[j].selected = true;
  29. }
  30. }
  31. }
  32. for (i = 0, l = $myCanvas.length; i < l; ++i) {
  33. // https://stackoverflow.com/a/41242597
  34. myCanvasContext = $myCanvas[i].getContext('2d');
  35. if(myCanvasContext) {
  36. $resultCanvas[i].getContext('2d').drawImage($myCanvas[i], 0,0);
  37. $($resultCanvas[i]).attr("data-jquery-print", myCanvasContext.canvas.toDataURL());
  38. }
  39. }
  40. return $result;
  41. }
  42.  
  43. function getjQueryObject(string) {
  44. // Make string a vaild jQuery thing
  45. var jqObj = $("");
  46. try {
  47. jqObj = jQueryCloneWithSelectAndTextAreaValues(string);
  48. } catch (e) {
  49. jqObj = $("<span />")
  50. .html(string);
  51. }
  52. return jqObj;
  53. }
  54.  
  55. function printFrame(frameWindow, content, options) {
  56. // Print the selected window/iframe
  57. var def = $.Deferred();
  58. try {
  59. frameWindow = frameWindow.contentWindow || frameWindow.contentDocument || frameWindow;
  60. try {
  61. frameWindow.resizeTo(window.innerWidth, window.innerHeight);
  62. } catch (err) {
  63. console.warn(err);
  64. }
  65. var wdoc = frameWindow.document || frameWindow.contentDocument || frameWindow;
  66. if(options.doctype) {
  67. wdoc.write(options.doctype);
  68. }
  69. wdoc.write(content);
  70. try {
  71. var canvas = wdoc.querySelectorAll('canvas');
  72. for(var i = 0; i < canvas.length; i++) {
  73. var ctx = canvas[i].getContext("2d");
  74. var image = new Image();
  75. image.onload = function() {
  76. ctx.drawImage(image, 0, 0);
  77. };
  78. image.src = canvas[i].getAttribute("data-jquery-print");
  79. }
  80. } catch (err) {
  81. console.warn(err);
  82. }
  83. wdoc.close();
  84. var printed = false,
  85. callPrint = function () {
  86. if(printed) {
  87. return;
  88. }
  89. // Fix for IE : Allow it to render the iframe
  90. frameWindow.focus();
  91. try {
  92. // Fix for IE11 - printng the whole page instead of the iframe content
  93. if (!frameWindow.document.execCommand('print', false, null)) {
  94. // document.execCommand returns false if it failed -http://stackoverflow.com/a/21336448/937891
  95. frameWindow.print();
  96. }
  97. // focus body as it is losing focus in iPad and content not getting printed
  98. $('body').focus();
  99. } catch (e) {
  100. frameWindow.print();
  101. }
  102. frameWindow.close();
  103. printed = true;
  104. def.resolve();
  105. };
  106. // Print once the frame window loads - seems to work for the new-window option but unreliable for the iframe
  107. $(frameWindow).on("load", callPrint);
  108. // Fallback to printing directly if the frame doesn't fire the load event for whatever reason
  109. setTimeout(callPrint, options.timeout);
  110. } catch (err) {
  111. def.reject(err);
  112. }
  113. return def;
  114. }
  115.  
  116. function printContentInIFrame(content, options) {
  117. var $iframe = $(options.iframe + "");
  118. var iframeCount = $iframe.length;
  119. if (iframeCount === 0) {
  120. // Create a new iFrame if none is given
  121. $iframe = $('<iframe height="0" width="0" border="0" wmode="Opaque"/>')
  122. .prependTo('body')
  123. .css({
  124. "position": "absolute",
  125. "top": -999,
  126. "left": -999
  127. });
  128. }
  129. var frameWindow = $iframe.get(0);
  130. return printFrame(frameWindow, content, options)
  131. .done(function () {
  132. // Success
  133. setTimeout(function () {
  134. // Wait for IE
  135. if (iframeCount === 0) {
  136. // Destroy the iframe if created here
  137. $iframe.remove();
  138. }
  139. }, 1000);
  140. })
  141. .fail(function (err) {
  142. // Use the pop-up method if iframe fails for some reason
  143. console.error("Failed to print from iframe", err);
  144. printContentInNewWindow(content, options);
  145. })
  146. .always(function () {
  147. try {
  148. options.deferred.resolve();
  149. } catch (err) {
  150. console.warn('Error notifying deferred', err);
  151. }
  152. });
  153. }
  154.  
  155. function printContentInNewWindow(content, options) {
  156. // Open a new window and print selected content
  157. var frameWindow = window.open();
  158. return printFrame(frameWindow, content, options)
  159. .always(function () {
  160. try {
  161. options.deferred.resolve();
  162. } catch (err) {
  163. console.warn('Error notifying deferred', err);
  164. }
  165. });
  166. }
  167.  
  168. function isNode(o) {
  169. /* http://stackoverflow.com/a/384380/937891 */
  170. return !!(typeof Node === "object" ? o instanceof Node : o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string");
  171. }
  172. $.print = $.fn.print = function () {
  173. // Print a given set of elements
  174. var options, $this, self = this;
  175. // console.log("Printing", this, arguments);
  176. if (self instanceof $) {
  177. // Get the node if it is a jQuery object
  178. self = self.get(0);
  179. }
  180. if (isNode(self)) {
  181. // If `this` is a HTML element, i.e. for
  182. // $(selector).print()
  183. $this = $(self);
  184. if (arguments.length > 0) {
  185. options = arguments[0];
  186. }
  187. } else {
  188. if (arguments.length > 0) {
  189. // $.print(selector,options)
  190. $this = $(arguments[0]);
  191. if (isNode($this[0])) {
  192. if (arguments.length > 1) {
  193. options = arguments[1];
  194. }
  195. } else {
  196. // $.print(options)
  197. options = arguments[0];
  198. $this = $("html");
  199. }
  200. } else {
  201. // $.print()
  202. $this = $("html");
  203. }
  204. }
  205. // Default options
  206. var defaults = {
  207. globalStyles: true,
  208. mediaPrint: false,
  209. stylesheet: null,
  210. noPrintSelector: ".no-print",
  211. iframe: true,
  212. append: null,
  213. prepend: null,
  214. manuallyCopyFormValues: true,
  215. deferred: $.Deferred(),
  216. timeout: 750,
  217. title: null,
  218. doctype: '<!doctype html>'
  219. };
  220. // Merge with user-options
  221. options = $.extend({}, defaults, (options || {}));
  222. var $styles = $("");
  223. if (options.globalStyles) {
  224. // Apply the stlyes from the current sheet to the printed page
  225. $styles = $("style, link, meta, base, title");
  226. } else if (options.mediaPrint) {
  227. // Apply the media-print stylesheet
  228. $styles = $("link[media=print]");
  229. }
  230. if (options.stylesheet) {
  231. // Add a custom stylesheet(s) if given
  232. if (!(($.isArray ? $.isArray : Array.isArray)(options.stylesheet))) {
  233. options.stylesheet = [options.stylesheet]
  234. }
  235. for(var i = 0; i < options.stylesheet.length; i++) {
  236. $styles = $.merge($styles, $('<link rel="stylesheet" href="' + options.stylesheet[i] + '">'));
  237. }
  238. }
  239. // Create a copy of the element to print
  240. var copy = jQueryCloneWithSelectAndTextAreaValues($this, true, true);
  241. // Wrap it in a span to get the HTML markup string
  242. copy = $("<span/>")
  243. .append(copy);
  244. // Remove unwanted elements
  245. copy.find(options.noPrintSelector)
  246. .remove();
  247. // Add in the styles
  248. copy.append(jQueryCloneWithSelectAndTextAreaValues($styles));
  249. // Update title
  250. if (options.title) {
  251. var title = $("title", copy);
  252. if (title.length === 0) {
  253. title = $("<title />");
  254. copy.append(title);
  255. }
  256. title.text(options.title);
  257. }
  258. // Appedned content
  259. copy.append(getjQueryObject(options.append));
  260. // Prepended content
  261. copy.prepend(getjQueryObject(options.prepend));
  262. if (options.manuallyCopyFormValues) {
  263. // Manually copy form values into the HTML for printing user-modified input fields
  264. // http://stackoverflow.com/a/26707753
  265. copy.find("input")
  266. .each(function () {
  267. var $field = $(this);
  268. if ($field.is("[type='radio']") || $field.is("[type='checkbox']")) {
  269. if ($field.prop("checked")) {
  270. $field.attr("checked", "checked");
  271. }
  272. } else {
  273. $field.attr("value", $field.val());
  274. }
  275. });
  276. copy.find("select").each(function () {
  277. var $field = $(this);
  278. $field.find(":selected").attr("selected", "selected");
  279. });
  280. copy.find("textarea").each(function () {
  281. // Fix for https://github.com/DoersGuild/jQuery.print/issues/18#issuecomment-96451589
  282. var $field = $(this);
  283. $field.text($field.val());
  284. });
  285. }
  286. // Get the HTML markup string
  287. var content = copy.html();
  288. // Notify with generated markup & cloned elements - useful for logging, etc
  289. try {
  290. options.deferred.notify('generated_markup', content, copy);
  291. } catch (err) {
  292. console.warn('Error notifying deferred', err);
  293. }
  294. // Destroy the copy
  295. copy.remove();
  296. if (options.iframe) {
  297. // Use an iframe for printing
  298. try {
  299. printContentInIFrame(content, options);
  300. } catch (e) {
  301. // Use the pop-up method if iframe fails for some reason
  302. console.error("Failed to print from iframe", e.stack, e.message);
  303. printContentInNewWindow(content, options);
  304. }
  305. } else {
  306. // Use a new window for printing
  307. printContentInNewWindow(content, options);
  308. }
  309. return this;
  310. };
  311. })(jQuery);