It looks like this is a web page, not a feed. I looked for a feed associated with this page, but couldn't find one. Please enter the address of your feed to validate.

Source: https://jedok.com/converter/jpg-to-pdf

  1.  
  2.  
  3. <!DOCTYPE html>
  4. <html lang="en">
  5. <head>
  6. <meta charset="utf-8" />
  7. <meta name="viewport" content="width=device-width, initial-scale=1" />
  8. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  9.  
  10.  
  11. <title>Convert JPG to PDF Online Free - JPG Converter | jedok.com</title>
  12. <meta name="description" content="Convert JPG to PDF online in seconds with jedok - free, secure JPG converter. Upload a .jpg file and save as TO without installing any software.">
  13. <link rel="canonical" href="https://jedok.com/converter/jpg-to-pdf" />
  14. <meta property="og:title" content="Convert JPG to PDF Online Free - JPG Converter - jedok.com">
  15. <meta property="og:description" content="Convert JPG to PDF online in seconds with jedok - free, secure JPG converter. Upload a .jpg file and save as TO without installing any software.">
  16. <meta property="og:url" content="https://jedok.com/converter/jpg-to-pdf">
  17. <meta property="og:type" content="website">
  18. <meta property="og:image" content="https://jedok.com/jedok-og-image.jpg" />
  19. <meta property="og:image:width" content="1200" />
  20. <meta property="og:image:height" content="630" />
  21. <meta property="og:image:type" content="image/jpeg" />
  22. <meta name="twitter:card" content="summary_large_image">
  23.  
  24. <script type="application/ld&#x2B;json">
  25. {
  26. "@context":"https://schema.org",
  27. "@type":"SoftwareApplication",
  28. "name":"Convert JPG to PDF Online Free - JPG Converter - jedok.com",
  29. "applicationCategory":"UtilitiesApplication",
  30. "operatingSystem":"Web",
  31. "description":"Convert JPG to PDF online in seconds with jedok - free, secure JPG converter. Upload a .jpg file and save as TO without installing any software.",
  32. "offers": {"@type":"Offer","price":"0","priceCurrency":"USD"},
  33. "url":"https://jedok.com/converter/jpg-to-pdf"
  34. }
  35. </script>
  36. <script type="application/ld&#x2B;json">
  37. {
  38. "@context":"https://schema.org",
  39. "@type":"WebSite",
  40. "name":"JeDok",
  41. "url":"https://jedok.com/converter/jpg-to-pdf",
  42. "potentialAction":{"@type":"SearchAction","target":"https://jedok.com/formats/{format}","query-input":"required name=format"}
  43. }
  44. </script>
  45.  
  46.  
  47. <!-- ✅ Performance: Preconnect to CDNs -->
  48. <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin>
  49. <link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin>
  50. <link rel="preconnect" href="https://code.jquery.com" crossorigin>
  51. <link rel="preconnect" href="https://www.googletagmanager.com" crossorigin>
  52.  
  53. <!-- ✅ CSS -->
  54. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" defer crossorigin>
  55. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css" defer crossorigin>
  56. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" defer crossorigin>
  57.  
  58. <!-- ✅ Favicons -->
  59. <link rel="icon" type="image/png" sizes="32x32" href="/favicon.png">
  60. <link rel="icon" type="image/png" sizes="64x64" href="/favicon.png">
  61. <link rel="apple-touch-icon" href="/favicon.png">
  62.  
  63. <!-- ✅ Google Analytics -->
  64. <script async src="https://www.googletagmanager.com/gtag/js?id=G-K6FQF5LSG9" type="5af166b0d89d5b77817c3979-text/javascript"></script>
  65. <script type="5af166b0d89d5b77817c3979-text/javascript">
  66. window.dataLayer = window.dataLayer || [];
  67. function gtag(){dataLayer.push(arguments);}
  68. gtag('js', new Date());
  69. gtag('config', 'G-K6FQF5LSG9', { anonymize_ip: true });
  70. </script>
  71.  
  72. <!-- ✅ App Config -->
  73. <script type="5af166b0d89d5b77817c3979-text/javascript">
  74. window.APP_CONFIG = Object.freeze({
  75.  apiBaseUrl: "https://api.jedok.com/api",
  76.  appBaseUrl: "https://jedok.com"
  77. });
  78. </script>
  79.  
  80. <!-- Your site styles -->
  81. <script src="/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js" data-cf-settings="5af166b0d89d5b77817c3979-|49"></script><link rel="preload" href="/css/site.css?v=85IF2Oi2NMeLED_gSW3dFrZjKfMm5lOm5QjDu-HU9c4" as="style" onload="this.onload=null;this.rel='stylesheet'">
  82. <noscript b-2u57mvn44z><link rel="stylesheet" href="/css/site.css?v=85IF2Oi2NMeLED_gSW3dFrZjKfMm5lOm5QjDu-HU9c4"></noscript>
  83.  
  84. <!-- Tiny critical inline CSS -->
  85. <style>
  86. /* Base + top bar */
  87. body {
  88. font-family: "Open Sans",Arial,sans-serif;
  89. font-size: .875rem;
  90. color: #333;
  91. margin-bottom: 5px
  92. }
  93.  
  94. .top-bar {
  95. background: #333;
  96. color: #fff;
  97. font-size: 14px;
  98. padding: 5px 0
  99. }
  100.  
  101. .navbar-brand {
  102. font-weight: 700;
  103. font-size: 24px
  104. }
  105. </style>
  106.  
  107. <!-- jQuery: must load before inline scripts -->
  108. <script src="https://code.jquery.com/jquery-3.6.4.min.js" crossorigin type="5af166b0d89d5b77817c3979-text/javascript"></script>
  109.  
  110. <link rel="preconnect" href="https://pagead2.googlesyndication.com" crossorigin>
  111. <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-0313867933438659" crossorigin="anonymous" type="5af166b0d89d5b77817c3979-text/javascript"></script>
  112.  
  113. </head>
  114.  
  115. <body>
  116. <!-- Top Bar -->
  117. <div b-2u57mvn44z class="top-bar text-center">
  118. <span b-2u57mvn44z>
  119. <a b-2u57mvn44z rel="nofollow" href="https://fileproinfo.com/free-online-viewer" class="text-white" target="_blank" title="Free online file viewer">Online File Viewer</a> |
  120. <a b-2u57mvn44z class="text-white" href="/contact">[Contact for this Slot]</a>
  121. </span>
  122. </div>
  123.  
  124. <!-- Navbar -->
  125. <nav b-2u57mvn44z class="navbar navbar-expand-lg navbar-light bg-light shadow-sm">
  126. <div b-2u57mvn44z class="container">
  127. <a b-2u57mvn44z class="navbar-brand text-danger" href="/"><img b-2u57mvn44z src="/jedok-logo.png" width="130" alt="jedok" /></a>
  128.  
  129. <button b-2u57mvn44z class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav"
  130. aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
  131. <span b-2u57mvn44z class="navbar-toggler-icon"></span>
  132. </button>
  133.  
  134. <div b-2u57mvn44z class="collapse navbar-collapse" id="navbarNav">
  135. <ul b-2u57mvn44z class="navbar-nav ms-auto align-items-lg-center">
  136. <li b-2u57mvn44z class="nav-item"><a b-2u57mvn44z class="nav-link" href="/">Home</a></li>
  137.  
  138. <!-- Mega menu -->
  139. <li b-2u57mvn44z class="nav-item dropdown megamenu position-static">
  140. <a b-2u57mvn44z class="nav-link dropdown-toggle" href="#" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
  141. Convert
  142. </a>
  143.  
  144. <!-- Full-width on desktop, stacked on mobile -->
  145. <div b-2u57mvn44z class="dropdown-menu w-100 mt-0 border-0 shadow">
  146. <div b-2u57mvn44z class="container py-3">
  147. <div b-2u57mvn44z class="row gy-4">
  148.  
  149. <!-- Col 1 (11 items) -->
  150. <div b-2u57mvn44z class="col-12 col-md-6 col-lg-3">
  151. <ul b-2u57mvn44z class="list-unstyled mb-0">
  152. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/3d-file-converter"><i b-2u57mvn44z class="bi bi-box"></i><span b-2u57mvn44z>3D Converter</span></a></li>
  153. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/archive-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-zip"></i><span b-2u57mvn44z>Archive Converter</span></a></li>
  154. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/audio-file-converter"><i b-2u57mvn44z class="bi bi-music-note"></i><span b-2u57mvn44z>Audio Converter</span></a></li>
  155. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/backup-file-converter"><i b-2u57mvn44z class="bi bi-cloud-arrow-up"></i><span b-2u57mvn44z>Backups Converter</span></a></li>
  156. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/cad-file-converter"><i b-2u57mvn44z class="bi bi-dice-3"></i><span b-2u57mvn44z>CAD Converter</span></a></li>
  157. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/camera-raw-file-converter"><i b-2u57mvn44z class="bi bi-camera"></i><span b-2u57mvn44z>Camera Raw File Converter</span></a></li>
  158. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/common-file-converter"><i b-2u57mvn44z class="bi bi-collection"></i><span b-2u57mvn44z>Common Files Converter</span></a></li>
  159. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/compression-file-converter"><i b-2u57mvn44z class="bi bi-arrows-collapse"></i><span b-2u57mvn44z>Compression Converter</span></a></li>
  160. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/data-file-converter"><i b-2u57mvn44z class="bi bi-file-binary"></i><span b-2u57mvn44z>Data File Converter</span></a></li>
  161. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/database-file-converter"><i b-2u57mvn44z class="bi bi-database"></i><span b-2u57mvn44z>Database Converter</span></a></li>
  162. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/developer-file-converter"><i b-2u57mvn44z class="bi bi-code-slash"></i><span b-2u57mvn44z>Developer Files Converter</span></a></li>
  163. </ul>
  164. </div>
  165.  
  166. <!-- Col 2 (11 items) -->
  167. <div b-2u57mvn44z class="col-12 col-md-6 col-lg-3">
  168. <ul b-2u57mvn44z class="list-unstyled mb-0">
  169. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/diagram-file-converter"><i b-2u57mvn44z class="bi bi-diagram-3"></i><span b-2u57mvn44z>Diagram Converter</span></a></li>
  170. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/disk-image-file-converter"><i b-2u57mvn44z class="bi bi-device-hdd"></i><span b-2u57mvn44z>Disk Image Converter</span></a></li>
  171. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/document-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-text"></i><span b-2u57mvn44z>Document Converter</span></a></li>
  172. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/ebook-file-converter"><i b-2u57mvn44z class="bi bi-book"></i><span b-2u57mvn44z>eBook Converter</span></a></li>
  173. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/email-file-converter"><i b-2u57mvn44z class="bi bi-envelope"></i><span b-2u57mvn44z>Email Converter</span></a></li>
  174. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/excel-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-excel"></i><span b-2u57mvn44z>Excel Converter</span></a></li>
  175. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/executable-file-converter"><i b-2u57mvn44z class="bi bi-terminal"></i><span b-2u57mvn44z>Executable File Converter</span></a></li>
  176. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/font-file-converter"><i b-2u57mvn44z class="bi bi-type"></i><span b-2u57mvn44z>Font Converter</span></a></li>
  177. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/game-file-converter"><i b-2u57mvn44z class="bi bi-controller"></i><span b-2u57mvn44z>Game Files Converter</span></a></li>
  178. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/gis-file-converter"><i b-2u57mvn44z class="bi bi-geo-alt"></i><span b-2u57mvn44z>GIS Converter</span></a></li>
  179. </ul>
  180. </div>
  181.  
  182. <!-- Col 3 (11 items) -->
  183. <div b-2u57mvn44z class="col-12 col-md-6 col-lg-3">
  184. <ul b-2u57mvn44z class="list-unstyled mb-0">
  185. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/image-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-image"></i><span b-2u57mvn44z>Image Converter</span></a></li>
  186. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/misc-file-converter"><i b-2u57mvn44z class="bi bi-three-dots"></i><span b-2u57mvn44z>Misc Converter</span></a></li>
  187. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/note-file-converter"><i b-2u57mvn44z class="bi bi-journal-text"></i><span b-2u57mvn44z>One Note Converter</span></a></li>
  188. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/outlook-file-converter"><i b-2u57mvn44z class="bi bi-envelope-open"></i><span b-2u57mvn44z>Outlook Converter</span></a></li>
  189. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/page-description-language-file-converter"><i b-2u57mvn44z class="bi bi-code-slash"></i><span b-2u57mvn44z>Page Description Language</span></a></li>
  190. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/page-layout-file-converter"><i b-2u57mvn44z class="bi bi-layout-text-window"></i><span b-2u57mvn44z>Page Layout Converter</span></a></li>
  191. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/pdf-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-pdf"></i><span b-2u57mvn44z>PDF Converter</span></a></li>
  192. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/plugin-file-converter"><i b-2u57mvn44z class="bi bi-plug"></i><span b-2u57mvn44z>Plugin Converter</span></a></li>
  193. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/presentation-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-ppt"></i><span b-2u57mvn44z>Presentation Converter</span></a></li>
  194. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/project-file-converter"><i b-2u57mvn44z class="bi bi-kanban"></i><span b-2u57mvn44z>Project Converter</span></a></li>
  195. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/project-management-file-converter"><i b-2u57mvn44z class="bi bi-kanban-fill"></i><span b-2u57mvn44z>Project Management Converter</span></a></li>
  196. </ul>
  197. </div>
  198.  
  199. <!-- Col 4 (10 items) -->
  200. <div b-2u57mvn44z class="col-12 col-md-6 col-lg-3 d-none d-lg-block">
  201. <ul b-2u57mvn44z class="list-unstyled mb-0">
  202. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/publisher-file-converter"><i b-2u57mvn44z class="bi bi-journal-richtext"></i><span b-2u57mvn44z>Publisher Files Converter</span></a></li>
  203. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/raster-image-file-converter"><i b-2u57mvn44z class="bi bi-image"></i><span b-2u57mvn44z>Raster Image Converter</span></a></li>
  204. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/settings-file-converter"><i b-2u57mvn44z class="bi bi-gear"></i><span b-2u57mvn44z>Settings File Converter</span></a></li>
  205. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/spreadsheet-file-converter"><i b-2u57mvn44z class="bi bi-table"></i><span b-2u57mvn44z>Spreadsheet Converter</span></a></li>
  206. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/system-file-converter"><i b-2u57mvn44z class="bi bi-cpu"></i><span b-2u57mvn44z>System Files Converter</span></a></li>
  207. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/text-file-converter"><i b-2u57mvn44z class="bi bi-text-paragraph"></i><span b-2u57mvn44z>Text File Converter</span></a></li>
  208. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/vector-image-file-converter"><i b-2u57mvn44z class="bi bi-bezier"></i><span b-2u57mvn44z>Vector Image Converter</span></a></li>
  209. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/video-file-converter"><i b-2u57mvn44z class="bi bi-camera-video"></i><span b-2u57mvn44z>Video Converter</span></a></li>
  210. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/web-file-converter"><i b-2u57mvn44z class="bi bi-globe"></i><span b-2u57mvn44z>Web Files Converter</span></a></li>
  211. <li b-2u57mvn44z><a b-2u57mvn44z class="dropdown-item d-flex align-items-center gap-2" href="/converters/word-processing-file-converter"><i b-2u57mvn44z class="bi bi-file-earmark-richtext"></i><span b-2u57mvn44z>Word Processing Converter</span></a></li>
  212. </ul>
  213. </div>
  214.  
  215. </div>
  216. </div>
  217. </div>
  218. </li>
  219.  
  220. <li b-2u57mvn44z class="nav-item"><a b-2u57mvn44z class="nav-link" href="/formats">Formats</a></li>
  221. <li b-2u57mvn44z class="nav-item"><a b-2u57mvn44z class="nav-link" href="/blog/">Blog</a></li>
  222. <li b-2u57mvn44z class="nav-item"><a b-2u57mvn44z class="nav-link" href="https://docpose.cloud/api-docs" target="_blank">API</a></li>
  223. <li b-2u57mvn44z class="nav-item"><a b-2u57mvn44z class="nav-link" href="/help">Help</a></li>
  224.  
  225. <li b-2u57mvn44z class="nav-item">
  226. <a b-2u57mvn44z class="nav-link" href="/download">
  227. My Files
  228. <span b-2u57mvn44z class="ui-badge text-red"><strong b-2u57mvn44z id="jobsCountLabel">0</strong></span>
  229. </a>
  230. </li>
  231.  
  232. <li b-2u57mvn44z class="nav-item auth-buttons ms-lg-3 mt-3 mt-lg-0">
  233. <a b-2u57mvn44z href="/login" class="btn btn-outline-secondary me-2">Login</a>
  234. <a b-2u57mvn44z href="/signup" class="btn btn-primary">Sign Up</a>
  235. </li>
  236. </ul>
  237. </div>
  238. </div>
  239. </nav>
  240.  
  241. <div b-2u57mvn44z class="container">
  242. <main b-2u57mvn44z role="main" class="pb-3">
  243. <!-- fallback if a view doesn’t use the layout or ViewBag is empty -->
  244.  
  245.  
  246. <!-- Include SignalR Library -->
  247. <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/7.0.5/signalr.min.js" type="5af166b0d89d5b77817c3979-text/javascript"></script>
  248.  
  249. <!-- Drop effect overlay -->
  250. <div id="dropOverlay" class="drag-over">
  251. <div class="drop-content">
  252. <svg width="80" height="80" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
  253. <line x1="12" y1="5" x2="12" y2="19"></line>
  254. <line x1="5" y1="12" x2="19" y2="12"></line>
  255. </svg>
  256. <p>Drop files here</p>
  257. </div>
  258. </div>
  259. <div class="container mt-5">
  260. <h1 class="text-center text-red">
  261. JPG to PDF Converter
  262. </h1>
  263. <h2 class="text-center">Welcome to the most advanced free online jpg to pdf converter </h2>
  264. <p class="text-center">Convert JPG to PDF online in seconds with jedok - free, secure JPG converter. Upload a .jpg file and save as TO without installing any software.</p>
  265. <form id="convertForm">
  266. <!-- Drag-and-Drop Zone -->
  267. <div id="dropZone">
  268. <button type="button" class="file-upload-btn" onclick="if (!window.__cfRLUnblockHandlers) return false; document.getElementById('fileInput').click()" data-cf-modified-5af166b0d89d5b77817c3979-="">Select Files</button>
  269. <input type="file" id="fileInput" multiple />
  270. <div class="file-source-caption"><span class="security-icon" data-placement="left" title="All your data is always protected and under your control. Learn more about technical and organizational security measures we take on the Security page."></span><span>Drop max 5 files here. 25 MB maximum file size or <a style="color:white;" href="/signup">Sign Up</a> (free).</span></div>
  271. </div>
  272. <div class="text-center mt-2"><span class="text-green">All your data is always protected and under your control. Learn more about technical and organizational security measures we take on the <a href="/security">Security</a> page.</span> </div>
  273. <div class="text-center mt-2">Powered by <a href="https://docpose.cloud" target="_blank">Docpose.Cloud</a> API's, 200+ <a href="/formats">formats</a> supported.</div>
  274.  
  275. <!-- fallback if a view doesn’t use the layout or ViewBag is empty -->
  276. <div class="adb d-md-block">
  277.  
  278. <!-- jedoktop responsive -->
  279. <ins class="adsbygoogle"
  280. style="display:block"
  281. data-ad-client="ca-pub-0313867933438659"
  282. data-ad-slot="1439225974"
  283. data-ad-format="auto"
  284. data-full-width-responsive="true"></ins>
  285. <script type="5af166b0d89d5b77817c3979-text/javascript">
  286. (adsbygoogle = window.adsbygoogle || []).push({});
  287. </script>
  288.  
  289. </div>
  290.  
  291.  
  292. <!-- File list -->
  293. <div id="file-list-container" class="mt-3 container">
  294. <ul id="file-list" class="list-group"></ul>
  295. </div>
  296.  
  297. <!-- Convert button -->
  298. <div class="mt-3 container text-center d-none" id="butonsDiv">
  299. <div class="file-source-caption" id="myFilesMessage">Files will be stored for 24 hours. Go to <a class="text-red" href="/download/">My Files</a> to delete them manually.</div>
  300. <button id="convertButton" type="submit" style="padding: 12px 24px!important; font-size: 25px!important;" class="btn btn-success w-50 mt-3">Convert</button>
  301. <!-- Clear All button (Initially Hidden) -->
  302. <button id="clearAllButton" type="button" style="padding: 12px 24px!important; font-size: 25px!important;" class="btn btn-info w-50 mt-3 d-none" onclick="if (!window.__cfRLUnblockHandlers) return false; resetForm()" data-cf-modified-5af166b0d89d5b77817c3979-="">Clear All</button>
  303. </div>
  304. </form>
  305.  
  306. <!-- Status message -->
  307. <p id="message" class="text-center mt-3"></p>
  308.  
  309.  
  310. </div>
  311.  
  312. <section class="container my-5">
  313. <div class="row">
  314. <div class="col-lg-6">
  315. <div class="card text-bg-light">
  316. <div class="card-body">
  317. <h2><span class="badge bg-warning text-dark fs-6">JPG</span> </h2>
  318. <h3 id="format-title1" class="mt-3"></h3>
  319. <p id="format-desc1" class="info-content centered-box"></p>
  320. <div style="text-align:right"><a href="/converter/jpg">Convert to JPG</a></div>
  321. </div>
  322. </div>
  323. </div>
  324. <div class="col-lg-6">
  325. <div class="card text-bg-light">
  326. <div class="card-body">
  327. <h2><span class="badge bg-warning text-dark fs-6">PDF</span> </h2>
  328. <h3 id="format-title2" class="mt-3"></h3>
  329. <p id="format-desc2" class="info-content centered-box"></p>
  330. <div style="text-align:right"><a href="/converter/pdf">PDF Converter</a></div>
  331. </div>
  332. </div>
  333. </div>
  334. </div>
  335. </section>
  336. <section class="container text-center my-5">
  337. <div class="steps text-center mt-5">
  338. <h2>How to convert JPG to TO to PDF</h2>
  339. <div class="row">
  340. <div class="col-lg-4">
  341. <div class="card text-bg-light">
  342. <div class="step-label badge bg-info text-dark fs-6">STEP 1</div>
  343. <div class="card-body">
  344. <h3>Upload jpg-file(s)</h3>
  345. <p>Select files from Computer, or by dragging it on the page.</p>
  346. </div>
  347. </div>
  348. </div>
  349. <div class="col-lg-4">
  350. <div class="card text-bg-light">
  351. <div class="step-label badge bg-warning text-dark fs-6">STEP 2</div>
  352. <div class="card-body">
  353. <h3>Choose "to pdf"</h3>
  354. <p>Choose pdf or any other format you need as a result (many formats supported)</p>
  355. </div>
  356. </div>
  357. </div>
  358. <div class="col-lg-4">
  359. <div class="card text-bg-light">
  360. <div class="step-label badge bg-success text-dark fs-6">STEP 3</div>
  361. <div class="card-body">
  362. <h3>Download your pdf</h3>
  363. <p>Let the file convert and you can download your pdf file right afterwards</p>
  364. </div>
  365. </div>
  366. </div>
  367. </div>
  368. </div>
  369. </section>
  370. <section class="my-4" aria-labelledby="top15-conversions">
  371. <h2 id="top15-conversions" class="h5 mb-3 text-center">Supported Conversions</h2>
  372. <div class="row g-4">
  373. <div class="col-md-6">
  374. <div class="table-responsive">
  375. <table class="table table-striped">
  376. <thead class="table-light">
  377. <tr>
  378. <th style="width: 3rem;">#</th>
  379. <th>Convert from JPG</th>
  380. <th class="text-end">Rating</th>
  381. </tr>
  382. </thead>
  383. <tbody id="top15-from"></tbody>
  384. </table>
  385. </div>
  386. </div>
  387. <div class="col-md-6">
  388. <div class="table-responsive">
  389. <table class="table table-striped">
  390. <thead class="table-light">
  391. <tr>
  392. <th style="width: 3rem;">#</th>
  393. <th>Convert to JPG</th>
  394. <th class="text-end">Rating</th>
  395. </tr>
  396. </thead>
  397. <tbody id="top15-to"></tbody>
  398. </table>
  399. </div>
  400. </div>
  401. </div>
  402. <div class="mt-3 container text-center">
  403. <a class="btn btn-info mt-3" href="/formats/jpg">View All JPG Supported Conversions</a>
  404. </div>
  405. </section>
  406. <style>
  407. .table thead th {
  408. white-space: nowrap;
  409. }
  410.  
  411. .table td a {
  412. text-decoration: none;
  413. font-weight: 600;
  414. }
  415. </style>
  416. <script defer type="5af166b0d89d5b77817c3979-text/javascript">
  417. (function () {
  418.  
  419. // Fetch format meta (description/shortdescription)
  420. fetch("/supported-formats/jpg")
  421.  .then(r => r.json())
  422.  .then(items => {
  423.  // Try multiple casings of property names
  424.  const meta = items.find(x => (x.formatCode ?? x.FormatCode ?? x.formatcode ?? "").toLowerCase() === "jpg");
  425.  if(meta){
  426. document.getElementById("format-title1").innerText = (meta.description ?? meta.Description ?? "") || "";
  427. document.getElementById("format-desc1").innerText = (meta.shortDescription ?? meta.ShortDescription ?? "") || "";
  428.  }
  429.  }).catch(()=>{});
  430.  
  431. // Fetch format meta (description/shortdescription)
  432. fetch("/supported-formats/pdf")
  433.  .then(r => r.json())
  434.  .then(items => {
  435.  // Try multiple casings of property names
  436.  const meta = items.find(x => (x.formatCode ?? x.FormatCode ?? x.formatcode ?? "").toLowerCase() === "pdf");
  437.  if(meta){
  438. document.getElementById("format-title2").innerText = (meta.description ?? meta.Description ?? "") || "";
  439. document.getElementById("format-desc2").innerText = (meta.shortDescription ?? meta.ShortDescription ?? "") || "";
  440.  }
  441.  }).catch(()=>{});
  442.  
  443.  // source format = the first part of "pdf-docx"
  444.  const src = "jpg".toLowerCase().replace(/^\./,'');
  445.  if (!src) return;
  446.  
  447.  const norm = s => (s||"").toString().trim().replace(/^\./,'').toLowerCase();
  448.  const up   = s => norm(s).toUpperCase();
  449.  
  450.  // Stable sort helper (keeps API order when no votes/ratings)
  451.  const rank = (arr, pickVotes, pickRating) => {
  452. return [...arr].sort((a,b) => {
  453.  const va = Number(pickVotes(a) || 0), vb = Number(pickVotes(b) || 0);
  454.  if (vb !== va) return vb - va;
  455.  const ra = Number(pickRating(a) || 0), rb = Number(pickRating(b) || 0);
  456.  if (rb !== ra) return rb - ra;
  457.  return 0; // keep original order if equal
  458. }).slice(0, 15);
  459.  };
  460.  
  461.  fetch(`/supported-conversions/${src}`)
  462. .then(r => r.json())
  463. .then(data => {
  464.  const from = data.convertFrom || data.ConvertFrom || [];
  465.  const to   = data.convertTo   || data.ConvertTo   || [];
  466.  
  467.  // rank by votes -> rating
  468.  const topFrom = rank(
  469. from,
  470. r => r.ratingCount ?? r.RatingCount,
  471. r => r.ratingValue ?? r.RatingValue
  472.  );
  473.  
  474.  const topTo = rank(
  475. to,
  476. r => r.ratingCount ?? r.RatingCount,
  477. r => r.ratingValue ?? r.RatingValue
  478.  );
  479.  
  480.  // Render rows
  481.  const renderRows = (rows, elId, linkBuilder) => {
  482. const tbody = document.getElementById(elId);
  483. tbody.innerHTML = "";
  484. rows.forEach((row, idx) => {
  485.  const f = norm(row.fromFormat ?? row.FromFormat);
  486.  const t = norm(row.toFormat   ?? row.ToFormat);
  487.  const rating = row.ratingValue ?? row.RatingValue;
  488.  const votes  = row.ratingCount ?? row.RatingCount;
  489.  const aHref  = linkBuilder(f, t);
  490.  const aText  = `${up(f)} to ${up(t)}`;
  491.  const tr = document.createElement("tr");
  492.  tr.innerHTML = `
  493. <td>${idx + 1}</td>
  494. <td><a href="/converter/${aHref}" title="${aText}">${aText}</a></td>
  495. <td class="text-end">${rating ? rating : ""} ${votes ? `(${votes} votes)` : ""}</td>
  496.  `;
  497.  tbody.appendChild(tr);
  498. });
  499.  };
  500.  
  501.  // For "Convert from SRC": rows already shaped as SRC -> X
  502.  renderRows(topFrom, "top15-from", (f,t) => `${f}-to-${t}`);
  503.  
  504.  // For "Convert to SRC": rows shaped as X -> SRC
  505.  renderRows(topTo, "top15-to", (f,t) => `${f}-to-${t}`);
  506.  
  507.  // Emit JSON-LD (two ItemLists)
  508.  const ld = [
  509. {
  510.  "@context":"https://schema.org",
  511.  "@type":"ItemList",
  512.  "name": `Convert from ${src.toUpperCase()} (Top 15)`,
  513.  "itemListElement": topFrom.map((r,i)=>({
  514. "@type":"ListItem",
  515. "position": i+1,
  516. "url": `https://jedok.com/${norm(r.fromFormat ?? r.FromFormat)}-${norm(r.toFormat ?? r.ToFormat)}`,
  517. "name": `${up(r.fromFormat ?? r.FromFormat)} to ${up(r.toFormat ?? r.ToFormat)}`
  518.  }))
  519. },
  520. {
  521.  "@context":"https://schema.org",
  522.  "@type":"ItemList",
  523.  "name": `Convert to ${src.toUpperCase()} (Top 15)`,
  524.  "itemListElement": topTo.map((r,i)=>({
  525. "@type":"ListItem",
  526. "position": i+1,
  527. "url": `https://jedok.com/${norm(r.fromFormat ?? r.FromFormat)}-${norm(r.toFormat ?? r.ToFormat)}`,
  528. "name": `${up(r.fromFormat ?? r.FromFormat)} to ${up(r.toFormat ?? r.ToFormat)}`
  529.  }))
  530. }
  531.  ];
  532.  const s = document.createElement("script");
  533.  s.type = "application/ld+json";
  534.  s.text = JSON.stringify(ld);
  535.  document.head.appendChild(s);
  536. })
  537. .catch(console.error);
  538. })();
  539. </script>
  540.  
  541. <script defer type="5af166b0d89d5b77817c3979-text/javascript">
  542. const maxFilesAllowed = 3;
  543. const maxFileSizeMB = 25;
  544. let selectedFiles = [];
  545. const convertButton = document.getElementById("convertButton");
  546.  
  547. function showWarningMessage(message) {
  548. const el = document.getElementById('message');
  549. if (!el) { console.warn('#message not found'); return; }
  550. el.innerHTML = message;
  551. el.classList.remove('d-none');       // unhide if it was hidden
  552. el.classList.add('alert', 'alert-danger'); // style as Bootstrap alert
  553. }
  554.  
  555. // Function to reset warning message
  556. function resetWarningMessage() {
  557. const msgElement = document.getElementById("message");
  558. msgElement.textContent = "";
  559. msgElement.classList.remove("text-danger");
  560. }
  561.  
  562. // File input change event
  563. document.getElementById("fileInput").addEventListener("change", (e) => {
  564.  
  565. let newFiles = Array.from(e.target.files).filter(file => file.size <= maxFileSizeMB * 1024 * 1024);
  566.  
  567. if (selectedFiles.length + newFiles.length > maxFilesAllowed) {
  568. showWarningMessage(`You can only upload a maximum of ${maxFilesAllowed} files.`);
  569. return;
  570. }
  571.  
  572. document.getElementById("butonsDiv").classList.remove("d-none");
  573. //resetWarningMessage();
  574. selectedFiles = selectedFiles.concat(newFiles);
  575. updateFileList();
  576. });
  577.  
  578. // Drag-and-drop event listeners
  579. let dropOverlay = $("#dropOverlay");
  580.  
  581. // Show overlay when dragging
  582. $(document).on("dragenter dragover", function (e) {
  583. e.preventDefault();
  584. e.stopPropagation();
  585. dropOverlay.show();
  586. });
  587.  
  588. // Hide overlay when leaving
  589. $(document).on("dragleave", function (e) {
  590. if (e.relatedTarget === null) {
  591. dropOverlay.hide();
  592. }
  593. });
  594.  
  595. // Handle file drop
  596. $(document).on("drop", function (e) {
  597. e.preventDefault();
  598. dropOverlay.hide();
  599.  
  600. let newFiles = Array.from(e.originalEvent.dataTransfer.files).filter(file => file.size <= maxFileSizeMB * 1024 * 1024);
  601.  
  602. if (selectedFiles.length + newFiles.length > maxFilesAllowed) {
  603. showWarningMessage(`You can only upload a maximum of ${maxFilesAllowed} files.`);
  604. return;
  605. }
  606. document.getElementById("butonsDiv").classList.remove("d-none"); // Hide Convert button
  607. //resetWarningMessage();
  608. selectedFiles = selectedFiles.concat(newFiles);
  609. updateFileList();
  610. });
  611.  
  612. document.getElementById("convertForm").addEventListener("submit", async function (e) {
  613. e.preventDefault();
  614.  
  615. if(document.getElementById("message").innerHTML.includes("file conversion limit"))
  616. {
  617. alert(document.getElementById("message").textContent);
  618. return;
  619. }
  620.  
  621. if (selectedFiles.length === 0) return;
  622.  
  623. var now = new Date();
  624. var batchId = now.getHours() * 100 + now.getMinutes(); // Combine hour and minute
  625. //console.log("batchId: " + batchId);
  626.  
  627. convertButton.textContent = "Converting...";
  628. convertButton.disabled = true;
  629.  
  630. selectedFiles.forEach(async (file, index) => {
  631. const badgeStatus = document.getElementById(`badgeStatus-${index}`);
  632. const progressBar = document.getElementById(`progressBar-${index}`);
  633.  
  634. if(badgeStatus.textContent === "Ready"){
  635.  
  636. const outputFormat = document.getElementById(`outputFormat-${index}`).value;
  637. if (!outputFormat) {
  638. document.getElementById("message").textContent = `Please select an output format for ${file.name}`;
  639. document.getElementById("message").classList.add("text-danger");
  640. return;
  641. }
  642.  
  643. const formData = new FormData();
  644. formData.append("file", file);
  645. formData.append("outputFormat", outputFormat);
  646. formData.append("batchId", batchId);
  647.  
  648. const fileItem = document.querySelector(`#file-list li:nth-child(${index + 1})`);
  649.  
  650. badgeStatus.textContent = "Uploading";
  651. progressBar.style.width = "10%";
  652.  
  653. try {
  654. const data = await postFormDataWithProgress("/Conversion/ConvertFile", formData, (pct) => {
  655.  progressBar.style.width = pct + "%";
  656. });
  657.  
  658. // try {
  659. // const response = await fetch("/Conversion/ConvertFile", {
  660. // method: "POST",
  661. // body: formData,
  662. // });
  663. // progressBar.style.width = "40%";
  664. // badgeStatus.textContent = "Converting";
  665. // if (!response.ok) throw new Error(`Failed to convert file: ${file.name}`);
  666.  
  667. // const data = await response.json();
  668. // const jobId = data.jobId;
  669. // fileItem.setAttribute("data-job-id", jobId);
  670. // }
  671. // catch (error) {
  672. // //console.error(error);
  673. // }
  674. // Upload finished; backend accepted the job
  675. progressBar.style.width = "40%";
  676. badgeStatus.textContent = "Converting";
  677.  
  678. // Expect JSON like { jobId: 12345 }
  679. const jobId = data.jobId ?? data.JobId ?? data.id;
  680. if (!jobId) throw new Error("No jobId returned.");
  681. fileItem.setAttribute("data-job-id", jobId);
  682. //convertButton.textContent = "Convert";
  683. convertButton.disabled = true;
  684. }
  685. catch (err) {
  686. progressBar.style.width = "100%";
  687. progressBar.classList.add("bg-danger");
  688. badgeStatus.classList.add("text-error");
  689. //retryButton.classList.remove("d-none"); // Show retry button
  690. badgeStatus.textContent = "Upload failed";
  691. convertButton.disabled = false;
  692. console.error(err);
  693.  }
  694.  }
  695. });
  696. });
  697.  
  698. // 1) POST with real-time UPLOAD progress (10% → 40%)
  699. function postFormDataWithProgress(url, formData, onProgress) {
  700.  return new Promise((resolve, reject) => {
  701. const xhr = new XMLHttpRequest();
  702. xhr.open("POST", url);
  703.  
  704. // Upload progress
  705. xhr.upload.onprogress = (e) => {
  706.  if (!e.lengthComputable) return;
  707.  const uploaded = e.loaded / e.total;           // 0..1
  708.  const pct = Math.min(40, Math.max(10, 10 + Math.round(uploaded * 30))); // map to 10..40
  709.  onProgress?.(pct);
  710. };
  711.  
  712. xhr.onload = () => {
  713.  if (xhr.status >= 200 && xhr.status < 300) {
  714. try { resolve(JSON.parse(xhr.responseText)); }
  715. catch { resolve(xhr.responseText); }
  716.  } else {
  717. reject(new Error(`HTTP ${xhr.status}: ${xhr.statusText}`));
  718.  }
  719. };
  720.  
  721. xhr.onerror = () => reject(new Error("Network error"));
  722. xhr.send(formData);
  723.  });
  724. }
  725.  
  726. function checkAllJobsFinished() {
  727.  
  728. const allJobs = document.querySelectorAll("#file-list .file-item");
  729. let allProcessed = true;
  730.  
  731. allJobs.forEach(job => {
  732. const statusMessage = job.querySelector(".ui-badge").textContent;
  733. if (!statusMessage.includes("Completed") && !statusMessage.includes("Failed")) {
  734. allProcessed = false;
  735. }
  736. });
  737.  
  738. if (allProcessed) {
  739. document.getElementById("convertButton").classList.add("d-none"); // Hide Convert button
  740. document.getElementById("clearAllButton").classList.remove("d-none"); // Show Clear All button
  741. fetchConversionsCount();
  742. }
  743. }
  744.  
  745. // Function to update file list
  746. function updateFileList() {
  747. const fileList = document.getElementById("file-list");
  748. fileList.innerHTML = "";
  749.  
  750. selectedFiles.forEach((file, index) => {
  751. const fileItem = document.createElement("li");
  752. fileItem.className = "file-item list-group-item d-flex flex-column flex-md-row align-items-center";
  753.  
  754. fileItem.innerHTML = `
  755. <div class="d-flex align-items-center w-100 mb-2 mb-md-0">
  756. <img src="/file-icon.png" alt="icon" class="file-icon me-2">
  757. <span class="file-name-inner" title="${file.name}">${truncateFileName(file.name)}</span>
  758. <small class="text-muted ms-2 file-size">${formatFileSize(file.size)}</small>
  759. </div>
  760. <div class="output-format-container w-50 w-md-25 px-2">
  761. <select class="form-control output-format w-100" id="outputFormat-${index}">
  762. <option value="">Loading formats...</option>
  763. </select>
  764. </div>
  765. <div class="w-100 w-md-50 px-2 text-center">
  766. <div class="progress w-70 my-2">
  767. <div class="progress-bar progress-bar-striped progress-bar-animated" id="progressBar-${index}" role="progressbar" style="width: 0%;" aria-valuemin="0" aria-valuemax="100"></div>
  768. </div>
  769. <div class="ui-badge text-green" id="badgeStatus-${index}">Ready</div>
  770. </div>
  771. <div class="d-flex flex-wrap justify-content-center gap-2 mt-2 mt-md-0">
  772. <button type="button" class="btn btn-outline-danger btn-sm btn-remove" onclick="removeFile(${index})"><i class="bi bi-x-lg"></i>
  773. </button>
  774. <a class="btn btn-primary btn-sm file-download d-none" href="#" target="_blank">Download</a>
  775. <button type="button" class="btn btn-warning btn-sm retry-job d-none" onclick="retryJob(${index})">Retry</button>
  776. </div>
  777. `;
  778. fileList.appendChild(fileItem);
  779. fetchConversionFormats(file, index);
  780. });
  781.  
  782. convertButton.disabled = selectedFiles.length === 0 || selectedFiles.length > maxFilesAllowed;
  783. }
  784.  
  785. function resetForm() {
  786. location.reload(); // Reload the page to reset the form
  787. }
  788.  
  789. // Remove file function
  790. function removeFile(index) {
  791. selectedFiles.splice(index, 1);
  792. updateFileList();
  793. }
  794.  
  795. // Retry Job Functionality
  796. async function retryJob(index) {
  797. const fileItem = document.querySelector(`#file-list li:nth-child(${index + 1})`);
  798. const jobId = fileItem.getAttribute("data-job-id");
  799. const progressBar = fileItem.querySelector(".progress-bar");
  800. const message = fileItem.querySelector(".ui-badge");
  801. const retryButton = fileItem.querySelector(".retry-job");
  802.  
  803. if (!jobId) {
  804. //console.error("No job ID found for retry.");
  805. return;
  806. }
  807.  
  808. retryButton.disabled = true;
  809. message.textContent = "Retrying conversion...";
  810.  
  811. try {
  812. const response = await fetch(window.APP_CONFIG?.apiBaseUrl + `/admin/jobs/${jobId}/retry`, { method: "POST" });
  813.  
  814. if (!response.ok) throw new Error("Failed to retry the job.");
  815.  
  816. message.textContent = "Retry initiated...";
  817. progressBar.style.width = "50%";
  818. retryButton.classList.add("d-none");
  819. } catch (error) {
  820. //console.error(error);
  821. message.textContent = "Retry failed.";
  822. retryButton.disabled = false;
  823. }
  824. }
  825.  
  826. // SignalR Connection
  827. const connection = new signalR.HubConnectionBuilder()
  828. .withUrl((window.APP_CONFIG?.apiBaseUrl + "/").replace("/api/","") + "/jobHub")
  829. .build();
  830.  
  831. connection.start().then().catch(err => console.error("Error connecting to SignalR:", err));
  832.  
  833. connection.on("JobStatusUpdate", (jobId, status, outputFilePath) => {
  834.  
  835. //console.log(`Received OUTSIDE update for Job ${jobId}: Status = ${status}, OutputFilePath = ${outputFilePath}`);
  836.  
  837. // Select the correct file item based on jobId
  838. const fileItem = document.querySelector(`#file-list li[data-job-id='${jobId}']`);
  839.  
  840. if (!fileItem) {
  841. //console.error(`No file item found for Job ${jobId}`);
  842. return;
  843. }
  844.  
  845. const progressBar = fileItem.querySelector(".progress-bar");
  846. const message = fileItem.querySelector(".ui-badge");
  847. const downloadButton = fileItem.querySelector(".file-download");
  848. const retryButton = fileItem.querySelector(".retry-job");
  849. const outputFormatSelect = fileItem.querySelector(".output-format");
  850.  
  851. outputFormatSelect.classList.add("disabled");
  852. message.textContent = status;
  853.  
  854. if (status === "Completed") {
  855.  
  856. progressBar.style.width = "100%";
  857. downloadButton.href = (window.APP_CONFIG?.apiBaseUrl + "/").replace("/api/","") + "" + outputFilePath;
  858. downloadButton.classList.remove("d-none");
  859. const removeButton = fileItem.querySelector(".btn-remove");
  860. removeButton.classList.add("d-none");
  861.  
  862. } else if (status === "Failed") {
  863.  
  864. progressBar.style.width = "100%";
  865. progressBar.classList.add("bg-danger");
  866. message.classList.add("text-error");
  867. retryButton.classList.remove("d-none"); // Show retry button
  868.  
  869. } else {
  870.  
  871. progressBar.style.width = "60%";
  872. }
  873. checkAllJobsFinished();
  874. });
  875.  
  876. function truncateFileName(name) {
  877. if (name.length <= 24) return name;
  878.  
  879. const extensionIndex = name.lastIndexOf(".");
  880. const extension = extensionIndex !== -1 ? name.substring(extensionIndex) : "";
  881. const nameWithoutExtension = extensionIndex !== -1 ? name.substring(0, extensionIndex) : name;
  882.  
  883. const firstPart = nameWithoutExtension.substring(0, 12);
  884. const lastPart = nameWithoutExtension.substring(nameWithoutExtension.length - 8);
  885.  
  886. return `${firstPart}...${lastPart}${extension}`;
  887. }
  888.  
  889. function formatFileSize(size) {
  890. if (size < 1024) return size + " B";
  891. else if (size < 1024 * 1024) return (size / 1024).toFixed(2) + " KB";
  892. else if (size < 1024 * 1024 * 1024) return (size / (1024 * 1024)).toFixed(2) + " MB";
  893. else return (size / (1024 * 1024 * 1024)).toFixed(2) + " GB";
  894. }
  895.  
  896. async function fetchConversionFormats(file, index) {
  897.  
  898. const fileExt = file.name.toLowerCase();
  899. const outputFormatSelect = document.getElementById(`outputFormat-${index}`);
  900.  
  901. // Clear the dropdown
  902. outputFormatSelect.innerHTML = '<option value="">Output format</option>';
  903.  
  904. const apiUrl = window.APP_CONFIG?.apiBaseUrl + `/conversion/formats/${encodeURIComponent(fileExt)}`;
  905.  
  906. try {
  907.  
  908. // Call the API to get possible conversions
  909. const response = await fetch(apiUrl);
  910.  
  911. if (!response.ok) {
  912. outputFormatSelect.innerHTML = '<option value="">Failed to fetch formats</option>';
  913. throw new Error(`Failed to fetch conversion formats. Status: ${response.status}`);
  914. }
  915.  
  916. const data = await response.json();
  917.  
  918. if (data.possibleConversions.length === 0) {
  919. outputFormatSelect.innerHTML = '<option value="">No more supported</option>';
  920. // console.log("data.possibleConversions.length: "+data.possibleConversions.length);
  921.  
  922. // var option = document.createElement("option");
  923. // option.value = "TXT";
  924. // option.textContent = "txt".toUpperCase(); // Display in uppercase
  925. // outputFormatSelect.appendChild(option);
  926.  
  927. // option = document.createElement("option");
  928. // option.value = "PDF";
  929. // option.textContent = "pdf".toUpperCase(); // Display in uppercase
  930. // outputFormatSelect.appendChild(option);
  931. }
  932.  
  933. // Sort the possible conversions alphabetically
  934. data.possibleConversions.sort((a, b) => a.localeCompare(b));
  935.  
  936. // Populate the dropdown with sorted conversions
  937. data.possibleConversions.forEach(format => {
  938. const options = document.createElement("option");
  939. options.value = format;
  940. options.textContent = format.toUpperCase(); // Display in uppercase
  941. outputFormatSelect.appendChild(options);
  942. });
  943. } catch (error) {
  944. //console.error("Error fetching formats:", error);
  945. outputFormatSelect.innerHTML = '<option value="">Error loading formats</option>';
  946. }
  947. }
  948.  
  949. </script>
  950. </main>
  951. </div>
  952.  
  953. <footer b-2u57mvn44z class="bg-dark text-light py-4">
  954. <div b-2u57mvn44z class="container">
  955. <div b-2u57mvn44z class="row">
  956. <!-- Left Column -->
  957. <div b-2u57mvn44z class="col-md-3">
  958. <h6 b-2u57mvn44z class="fw-bold">About</h6>
  959. <ul b-2u57mvn44z class="list-unstyled">
  960. <li b-2u57mvn44z><a b-2u57mvn44z href="/about" class="text-light text-decoration-none">About</a></li>
  961. <li b-2u57mvn44z><a b-2u57mvn44z href="/blog" class="text-light text-decoration-none">Blog</a></li>
  962. <li b-2u57mvn44z><a b-2u57mvn44z href="/security" class="text-light text-decoration-none">Security</a></li>
  963. <li b-2u57mvn44z><a b-2u57mvn44z href="/formats" class="text-light text-decoration-none">Formats</a></li>
  964. <li b-2u57mvn44z><a b-2u57mvn44z href="/help" class="text-light text-decoration-none">Help</a></li>
  965. <li b-2u57mvn44z><a b-2u57mvn44z href="/help" class="text-light text-decoration-none">Contact</a></li>
  966. </ul>
  967. </div>
  968. <!-- Middle Column -->
  969. <div b-2u57mvn44z class="col-md-3">
  970. <h6 b-2u57mvn44z class="fw-bold">Converters</h6>
  971. <ul b-2u57mvn44z class="list-unstyled">
  972. <li b-2u57mvn44z><a b-2u57mvn44z href="/video-file-converter" class="text-light text-decoration-none">Video Converter</a></li>
  973. <li b-2u57mvn44z><a b-2u57mvn44z href="/audio-file-converter" class="text-light text-decoration-none">Audio Converter</a></li>
  974. <li b-2u57mvn44z><a b-2u57mvn44z href="/document-file-converter" class="text-light text-decoration-none">Document Converter</a></li>
  975. <li b-2u57mvn44z><a b-2u57mvn44z href="/image-file-converter" class="text-light text-decoration-none">Image Converter</a></li>
  976. <li b-2u57mvn44z><a b-2u57mvn44z href="/youtube-file-converter" class="text-light text-decoration-none">YouTube Converter</a></li>
  977. </ul>
  978. </div>
  979. <!-- Right Column -->
  980. <div b-2u57mvn44z class="col-md-3">
  981. <h6 b-2u57mvn44z class="fw-bold">Increase Daily Limits</h6>
  982. <ul b-2u57mvn44z class="list-unstyled">
  983. <li b-2u57mvn44z><a b-2u57mvn44z href="/signup" class="text-light text-decoration-none">Go Ad Free</a></li>
  984. <li b-2u57mvn44z><a b-2u57mvn44z href="/signup" class="text-light text-decoration-none">Free Register</a></li>
  985. <li b-2u57mvn44z><a b-2u57mvn44z href="/login" class="text-light text-decoration-none">Login</a></li>
  986. </ul>
  987. </div>
  988. <!-- Right Column -->
  989. <div b-2u57mvn44z class="col-md-3">
  990. <h6 b-2u57mvn44z class="fw-bold">Developers API</h6>
  991. <ul b-2u57mvn44z class="list-unstyled">
  992. <li b-2u57mvn44z><a b-2u57mvn44z href="https://docpose.cloud/api-docs" target="_blank" class="text-light text-decoration-none">API Docs</a></li>
  993. </ul>
  994. </div>
  995. </div>
  996. <hr b-2u57mvn44z class="bg-secondary">
  997. <div b-2u57mvn44z class="row text-center">
  998. <div b-2u57mvn44z class="col-md-12">
  999. <p b-2u57mvn44z class="mb-0">© 2025 JeDok.com Ltd. All rights reserved. | <a b-2u57mvn44z href="/terms" class="text-light text-decoration-none">Terms of Use</a> | <a b-2u57mvn44z href="/privacy" class="text-light text-decoration-none">Privacy Policy</a></p>
  1000. </div>
  1001. </div>
  1002. </div>
  1003. </footer>
  1004.  
  1005. <!-- Rest can be deferred -->
  1006. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" defer crossorigin type="5af166b0d89d5b77817c3979-text/javascript"></script>
  1007. <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11" defer type="5af166b0d89d5b77817c3979-text/javascript"></script>
  1008.  
  1009. <script defer type="5af166b0d89d5b77817c3979-text/javascript">
  1010. async function fetchConversionsCount() {
  1011.  
  1012. const jobsCountLabel = document.getElementById("jobsCountLabel");
  1013. jobsCountLabel.innerHTML = "";
  1014.  
  1015. $.ajax({
  1016. url: "/Conversion/GetJobsCount",
  1017. type: "GET",
  1018. dataType: "json",
  1019. success: function (jobsCount) {
  1020. jobsCountLabel.innerHTML = jobsCount;
  1021. if (jobsCount >= 5) {
  1022. showWarningMessage('You’ve reached today’s file conversion limit (5). To increase your limit, please <a href="/signup" class="alert-link">sign up</a>, or try again tomorrow.');
  1023. }
  1024. },
  1025. error: function (xhr) {
  1026. //console.error("Error fetching jobs count:", xhr);
  1027. jobsCountLabel.innerHTML = "0";
  1028. }
  1029. });
  1030. }
  1031.  
  1032. fetchConversionsCount();
  1033. </script>
  1034. <script type="5af166b0d89d5b77817c3979-text/javascript">
  1035. function animateContinuousCounter(id, startValue, incrementPerSecond = 60, minDelay = 1000, maxDelay = 4000) {
  1036. const el = document.getElementById(id);
  1037. let currentValue = startValue;
  1038. let lastUpdate = performance.now();
  1039. let nextIncrementTime = lastUpdate + getRandomDelay();
  1040.  
  1041. function format(n) {
  1042. return n.toLocaleString(undefined, { maximumFractionDigits: 2 });
  1043. }
  1044.  
  1045. function getRandomDelay() {
  1046. return Math.random() * (maxDelay - minDelay) + minDelay; // ms
  1047. }
  1048.  
  1049. function update(currentTime) {
  1050. if (currentTime >= nextIncrementTime) {
  1051. // Time to increment
  1052. currentValue += incrementPerSecond * 2; // Double tick effect
  1053. el.textContent = format(currentValue);
  1054.  
  1055. // Schedule next increment
  1056. nextIncrementTime = currentTime + getRandomDelay();
  1057. }
  1058.  
  1059. requestAnimationFrame(update);
  1060. }
  1061.  
  1062. requestAnimationFrame(update);
  1063. }
  1064. </script>
  1065. <script src="https://protagcdn.com/d/jedok.com.js" async type="5af166b0d89d5b77817c3979-text/javascript"></script>
  1066. <!-- Why Register Popup -->
  1067. <div b-2u57mvn44z class="modal fade" id="whyRegisterModal" tabindex="-1" aria-labelledby="whyRegisterLabel" aria-hidden="true">
  1068. <div b-2u57mvn44z class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
  1069. <div b-2u57mvn44z class="modal-content rounded-3 shadow">
  1070. <div b-2u57mvn44z class="modal-header border-0">
  1071. <h2 b-2u57mvn44z class="h4 modal-title mx-auto" id="whyRegisterLabel">Why Register on Jedok?</h2>
  1072. <button b-2u57mvn44z type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
  1073. </div>
  1074. <div b-2u57mvn44z class="modal-body">
  1075.  
  1076. <div b-2u57mvn44z class="row g-4">
  1077. <div b-2u57mvn44z class="col-12 col-md-6">
  1078. <h3 b-2u57mvn44z class="h5 text-center mb-3">Free</h3>
  1079. <ul b-2u57mvn44z class="list-unstyled fs-6">
  1080. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Free Conversions</strong> – Enjoy <strong b-2u57mvn44z>15 per day</strong>.</li>
  1081. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Bigger Files</strong> – Upload up to <strong b-2u57mvn44z>250 MB</strong>.</li>
  1082. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Parallel Conversions</strong> – Run up to <strong b-2u57mvn44z>10</strong> at once.</li>
  1083. <li b-2u57mvn44z>✅ Conversion priority <strong b-2u57mvn44z>High</strong></li>
  1084. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>File Management</strong> – Files kept for <strong b-2u57mvn44z>24 hours</strong> (auto-delete) or delete anytime.</li>
  1085. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>All Formats Supported</strong> – 200+ formats (docs, images, audio, video, archives, and more).</li>
  1086. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Email Verification</strong> – A valid email is required; we’ll send a quick verification link.</li>
  1087. </ul>
  1088. <div b-2u57mvn44z class="text-center">
  1089. <a b-2u57mvn44z class="btn btn-primary btn-sm" href="/signup">Register Now</a>
  1090. </div>
  1091. </div>
  1092.  
  1093. <div b-2u57mvn44z class="col-12 col-md-6">
  1094. <h3 b-2u57mvn44z class="h5 text-center mb-3">
  1095. Subscribed<br b-2u57mvn44z /><small b-2u57mvn44z>(USD $3.99 / month)</small>
  1096. </h3>
  1097. <ul b-2u57mvn44z class="list-unstyled fs-6">
  1098. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Free Conversions</strong> – Enjoy <strong b-2u57mvn44z>60 per day</strong>.</li>
  1099. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Bigger Files</strong> – Upload up to <strong b-2u57mvn44z>500 MB</strong>.</li>
  1100. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Parallel Conversions</strong> – Run up to <strong b-2u57mvn44z>25</strong> at once.</li>
  1101. <li b-2u57mvn44z>✅ Conversion priority <strong b-2u57mvn44z>Highest</strong></li>
  1102. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>Ad-Free</strong> – 100% ad-free experience.</li>
  1103. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>File Management</strong> – Files kept for <strong b-2u57mvn44z>24 hours</strong> (auto-delete) or delete anytime.</li>
  1104. <li b-2u57mvn44z>✅ <strong b-2u57mvn44z>All Formats Supported</strong> – 200+ formats.</li>
  1105. </ul>
  1106. <div b-2u57mvn44z class="text-center">
  1107. <a b-2u57mvn44z class="btn btn-primary btn-sm" href="/contact">Contact Us for Subscription</a>
  1108. </div>
  1109. </div>
  1110. </div>
  1111.  
  1112. <p b-2u57mvn44z class="text-center mt-4 mb-0">
  1113. <strong b-2u57mvn44z>Sign up now</strong> to unlock these features and enjoy a faster, more powerful conversion experience!
  1114. </p>
  1115. </div>
  1116. </div>
  1117. </div>
  1118. </div>
  1119. <script type="5af166b0d89d5b77817c3979-text/javascript">
  1120. document.addEventListener("DOMContentLoaded", function () {
  1121.  const modalEl = document.getElementById('whyRegisterModal');
  1122.  const modal = new bootstrap.Modal(modalEl);
  1123.  const key = "whyRegisterShownCount";
  1124.  
  1125.  // Check how many times shown in this session
  1126.  let shownCount = parseInt(sessionStorage.getItem(key) || "0");
  1127.  
  1128.  if (shownCount < 2) {
  1129. setTimeout(() => {
  1130.  modal.show();
  1131.  shownCount++;
  1132.  sessionStorage.setItem(key, shownCount);
  1133. }, 15000); // 15 seconds
  1134.  }
  1135. });
  1136. </script>
  1137. <script src="/cdn-cgi/scripts/7d0fa10a/cloudflare-static/rocket-loader.min.js" data-cf-settings="5af166b0d89d5b77817c3979-|49" defer></script><script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"version":"2024.11.0","token":"b675e68b422a4d21b07fefa11bd3a716","r":1,"server_timing":{"name":{"cfCacheStatus":true,"cfEdge":true,"cfExtPri":true,"cfL4":true,"cfOrigin":true,"cfSpeedBrain":true},"location_startswith":null}}' crossorigin="anonymous"></script>
  1138. </body>
  1139. </html>
  1140.  
Copyright © 2002-9 Sam Ruby, Mark Pilgrim, Joseph Walton, and Phil Ringnalda