pdfobject.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*global ActiveXObject, window, console, define, module, jQuery */
  2. //jshint unused:false, strict: false
  3. /*
  4. PDFObject v2.1.1
  5. https://github.com/pipwerks/PDFObject
  6. Copyright (c) 2008-2018 Philip Hutchison
  7. MIT-style license: http://pipwerks.mit-license.org/
  8. UMD module pattern from https://github.com/umdjs/umd/blob/master/templates/returnExports.js
  9. */
  10. (function (root, factory) {
  11. if (typeof define === 'function' && define.amd) {
  12. // AMD. Register as an anonymous module.
  13. define([], factory);
  14. } else if (typeof module === 'object' && module.exports) {
  15. // Node. Does not work with strict CommonJS, but
  16. // only CommonJS-like environments that support module.exports,
  17. // like Node.
  18. module.exports = factory();
  19. } else {
  20. // Browser globals (root is window)
  21. root.PDFObject = factory();
  22. }
  23. }(this, function () {
  24. "use strict";
  25. //jshint unused:true
  26. //PDFObject is designed for client-side (browsers), not server-side (node)
  27. //Will choke on undefined navigator and window vars when run on server
  28. //Return boolean false and exit function when running server-side
  29. if(typeof window === "undefined" || typeof navigator === "undefined"){ return false; }
  30. var pdfobjectversion = "2.1.1",
  31. ua = window.navigator.userAgent,
  32. //declare booleans
  33. supportsPDFs,
  34. isIE,
  35. supportsPdfMimeType = (typeof navigator.mimeTypes['application/pdf'] !== "undefined"),
  36. supportsPdfActiveX,
  37. isModernBrowser = (function (){ return (typeof window.Promise !== "undefined"); })(),
  38. isFirefox = (function (){ return (ua.indexOf("irefox") !== -1); } )(),
  39. isFirefoxWithPDFJS = (function (){
  40. //Firefox started shipping PDF.js in Firefox 19.
  41. //If this is Firefox 19 or greater, assume PDF.js is available
  42. if(!isFirefox){ return false; }
  43. //parse userAgent string to get release version ("rv")
  44. //ex: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:57.0) Gecko/20100101 Firefox/57.0
  45. return (parseInt(ua.split("rv:")[1].split(".")[0], 10) > 18);
  46. })(),
  47. isIOS = (function (){ return (/iphone|ipad|ipod/i.test(ua.toLowerCase())); })(),
  48. //declare functions
  49. createAXO,
  50. buildFragmentString,
  51. log,
  52. embedError,
  53. embed,
  54. getTargetElement,
  55. generatePDFJSiframe,
  56. generateEmbedElement;
  57. /* ----------------------------------------------------
  58. Supporting functions
  59. ---------------------------------------------------- */
  60. createAXO = function (type){
  61. var ax;
  62. try {
  63. ax = new ActiveXObject(type);
  64. } catch (e) {
  65. ax = null; //ensure ax remains null
  66. }
  67. return ax;
  68. };
  69. //IE11 still uses ActiveX for Adobe Reader, but IE 11 doesn't expose
  70. //window.ActiveXObject the same way previous versions of IE did
  71. //window.ActiveXObject will evaluate to false in IE 11, but "ActiveXObject" in window evaluates to true
  72. //so check the first one for older IE, and the second for IE11
  73. //FWIW, MS Edge (replacing IE11) does not support ActiveX at all, both will evaluate false
  74. //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed
  75. isIE = function (){ return !!(window.ActiveXObject || "ActiveXObject" in window); };
  76. //If either ActiveX support for "AcroPDF.PDF" or "PDF.PdfCtrl" are found, return true
  77. //Constructed as a method (not a prop) to avoid unneccesarry overhead -- will only be evaluated if needed
  78. supportsPdfActiveX = function (){ return !!(createAXO("AcroPDF.PDF") || createAXO("PDF.PdfCtrl")); };
  79. //Determines whether PDF support is available
  80. supportsPDFs = (
  81. //as of iOS 12, inline PDF rendering is still not supported in Safari or native webview
  82. //3rd-party browsers (eg Chrome, Firefox) use Apple's webview for rendering, and thus the same result as Safari
  83. //Therefore if iOS, we shall assume that PDF support is not available
  84. !isIOS && (
  85. //Modern versions of Firefox come bundled with PDFJS
  86. isFirefoxWithPDFJS ||
  87. //Browsers that still support the original MIME type check
  88. supportsPdfMimeType || (
  89. //Pity the poor souls still using IE
  90. isIE() && supportsPdfActiveX()
  91. )
  92. )
  93. );
  94. //Create a fragment identifier for using PDF Open parameters when embedding PDF
  95. buildFragmentString = function(pdfParams){
  96. var string = "",
  97. prop;
  98. if(pdfParams){
  99. for (prop in pdfParams) {
  100. if (pdfParams.hasOwnProperty(prop)) {
  101. string += encodeURIComponent(prop) + "=" + encodeURIComponent(pdfParams[prop]) + "&";
  102. }
  103. }
  104. //The string will be empty if no PDF Params found
  105. if(string){
  106. string = "#" + string;
  107. //Remove last ampersand
  108. string = string.slice(0, string.length - 1);
  109. }
  110. }
  111. return string;
  112. };
  113. log = function (msg){
  114. if(typeof console !== "undefined" && console.log){
  115. console.log("[PDFObject] " + msg);
  116. }
  117. };
  118. embedError = function (msg){
  119. log(msg);
  120. return false;
  121. };
  122. getTargetElement = function (targetSelector){
  123. //Default to body for full-browser PDF
  124. var targetNode = document.body;
  125. //If a targetSelector is specified, check to see whether
  126. //it's passing a selector, jQuery object, or an HTML element
  127. if(typeof targetSelector === "string"){
  128. //Is CSS selector
  129. targetNode = document.querySelector(targetSelector);
  130. } else if (typeof jQuery !== "undefined" && targetSelector instanceof jQuery && targetSelector.length) {
  131. //Is jQuery element. Extract HTML node
  132. targetNode = targetSelector.get(0);
  133. } else if (typeof targetSelector.nodeType !== "undefined" && targetSelector.nodeType === 1){
  134. //Is HTML element
  135. targetNode = targetSelector;
  136. }
  137. return targetNode;
  138. };
  139. generatePDFJSiframe = function (targetNode, url, pdfOpenFragment, PDFJS_URL, id){
  140. var fullURL = PDFJS_URL + "?file=" + encodeURIComponent(url) + pdfOpenFragment;
  141. var scrollfix = (isIOS) ? "-webkit-overflow-scrolling: touch; overflow-y: scroll; " : "overflow: hidden; ";
  142. var iframe = "<div style='" + scrollfix + "position: absolute; top: 0; right: 0; bottom: 0; left: 0;'><iframe " + id + " src='" + fullURL + "' style='border: none; width: 100%; height: 100%;' frameborder='0'></iframe></div>";
  143. targetNode.className += " pdfobject-container";
  144. targetNode.style.position = "relative";
  145. targetNode.style.overflow = "auto";
  146. targetNode.innerHTML = iframe;
  147. return targetNode.getElementsByTagName("iframe")[0];
  148. };
  149. generateEmbedElement = function (targetNode, targetSelector, url, pdfOpenFragment, width, height, id){
  150. var style = "";
  151. if(targetSelector && targetSelector !== document.body){
  152. style = "width: " + width + "; height: " + height + ";";
  153. } else {
  154. style = "position: absolute; top: 0; right: 0; bottom: 0; left: 0; width: 100%; height: 100%;";
  155. }
  156. targetNode.className += " pdfobject-container";
  157. targetNode.innerHTML = "<embed " + id + " class='pdfobject' src='" + url + pdfOpenFragment + "' type='application/pdf' style='overflow: auto; " + style + "'/>";
  158. return targetNode.getElementsByTagName("embed")[0];
  159. };
  160. embed = function(url, targetSelector, options){
  161. //Ensure URL is available. If not, exit now.
  162. if(typeof url !== "string"){ return embedError("URL is not valid"); }
  163. //If targetSelector is not defined, convert to boolean
  164. targetSelector = (typeof targetSelector !== "undefined") ? targetSelector : false;
  165. //Ensure options object is not undefined -- enables easier error checking below
  166. options = (typeof options !== "undefined") ? options : {};
  167. //Get passed options, or set reasonable defaults
  168. var id = (options.id && typeof options.id === "string") ? "id='" + options.id + "'" : "",
  169. page = (options.page) ? options.page : false,
  170. pdfOpenParams = (options.pdfOpenParams) ? options.pdfOpenParams : {},
  171. fallbackLink = (typeof options.fallbackLink !== "undefined") ? options.fallbackLink : true,
  172. width = (options.width) ? options.width : "100%",
  173. height = (options.height) ? options.height : "100%",
  174. assumptionMode = (typeof options.assumptionMode === "boolean") ? options.assumptionMode : true,
  175. forcePDFJS = (typeof options.forcePDFJS === "boolean") ? options.forcePDFJS : false,
  176. PDFJS_URL = (options.PDFJS_URL) ? options.PDFJS_URL : false,
  177. targetNode = getTargetElement(targetSelector),
  178. fallbackHTML = "",
  179. pdfOpenFragment = "",
  180. fallbackHTML_default = "<p>This browser does not support inline PDFs. Please download the PDF to view it: <a href='[url]'>Download PDF</a></p>";
  181. //If target element is specified but is not valid, exit without doing anything
  182. if(!targetNode){ return embedError("Target element cannot be determined"); }
  183. //page option overrides pdfOpenParams, if found
  184. if(page){
  185. pdfOpenParams.page = page;
  186. }
  187. //Stringify optional Adobe params for opening document (as fragment identifier)
  188. pdfOpenFragment = buildFragmentString(pdfOpenParams);
  189. //Do the dance
  190. //If the forcePDFJS option is invoked, skip everything else and embed as directed
  191. if(forcePDFJS && PDFJS_URL){
  192. return generatePDFJSiframe(targetNode, url, pdfOpenFragment, PDFJS_URL, id);
  193. //If traditional support is provided, or if this is a modern browser and not iOS (see comment for supportsPDFs declaration)
  194. } else if(supportsPDFs || (assumptionMode && isModernBrowser && !isIOS)){
  195. return generateEmbedElement(targetNode, targetSelector, url, pdfOpenFragment, width, height, id);
  196. //If everything else has failed and a PDFJS fallback is provided, try to use it
  197. } else if(PDFJS_URL){
  198. return generatePDFJSiframe(targetNode, url, pdfOpenFragment, PDFJS_URL, id);
  199. } else {
  200. //Display the fallback link if available
  201. if(fallbackLink){
  202. fallbackHTML = (typeof fallbackLink === "string") ? fallbackLink : fallbackHTML_default;
  203. targetNode.innerHTML = fallbackHTML.replace(/\[url\]/g, url);
  204. }
  205. return embedError("This browser does not support embedded PDFs");
  206. }
  207. };
  208. return {
  209. embed: function (a,b,c){ return embed(a,b,c); },
  210. pdfobjectversion: (function () { return pdfobjectversion; })(),
  211. supportsPDFs: (function (){ return supportsPDFs; })()
  212. };
  213. }));