1/* eslint-disable camelcase */ 2/* eslint-disable no-undef */ 3jQuery( function( $ ) { 4 // Let's initiate the XHR. 5 new DLM_XHR_Download(); 6} ); 7 8class DLM_XHR_Download { 9 responsHeaders = {}; 10 11 constructor() { 12 // dlmXHRinstance defined in inline script 13 dlmXHRinstance = this; 14 this.init(); 15 } 16 17 init() { 18 dlmXHRinstance.attachButtonEvent(); 19 } 20 21 // Function to attach events for the download buttons 22 attachButtonEvent() { 23 // Stop propagation on child elements 24 jQuery( 'html,body' ).on( 'click', '.dlm-no-access-modal-window > div', function( e ) { 25 e.stopPropagation(); 26 } ); 27 // Close modal on these clicks 28 jQuery( 'html, body' ).on( 'click', '.dlm-no-access-modal-overlay, .dlm-no-access-modal-close, .dlm-no-access-modal-window', function( e ) { 29 e.stopPropagation(); 30 jQuery( '#dlm-no-access-modal' ).remove(); 31 } ); 32 // Close modal on ESC key press 33 jQuery( document ).on( 'keydown', function( e ) { 34 if ( e.key === 'Escape' ) { 35 jQuery( '#dlm-no-access-modal' ).remove(); 36 } 37 } ); 38 39 jQuery( 'html, body' ).on( 'click', 'a', function( e ) { 40 let url = jQuery( this ).attr( 'href' ); 41 // Let's see if we need to do XHR download on this link. 42 let noXHR = false; 43 if ( jQuery( this ).hasClass( 'dlm-no-xhr-download' ) ) { 44 noXHR = true; 45 } 46 47 if ( 'undefined' !== typeof dlmNonXHRGlobalLinks && dlmNonXHRGlobalLinks.length > 0 ) { 48 if ( 'undefined' !== typeof url ) { 49 dlmNonXHRGlobalLinks.forEach( ( element ) => { 50 if ( url.indexOf( element ) >= 0 ) { 51 noXHR = true; 52 } 53 } ); 54 } 55 } 56 57 if ( noXHR ) { // No XHR so return; 58 jQuery( '#dlm-no-access-modal' ).remove(); // Close the modal also in case we opened it before. 59 return; 60 } 61 62 if ( typeof url === 'string' ) { 63 try { 64 url = new URL( url, window.location.origin ).href; 65 } catch ( e ) {} 66 } 67 68 jQuery( document ).trigger( 'dlm-xhr-download-button-click', [ url, this, dlmXHRGlobalLinks ] ); 69 if ( 'undefined' !== typeof url && url.indexOf( dlmXHRGlobalLinks ) >= 0 ) { 70 const redirect_link = jQuery( this ).data( 'redirect' ), 71 target = jQuery( this ).attr( 'target' ); 72 // Check if the link has a target attribute, and if it does, we need to open it in a new window. 73 if ( 'undefined' !== typeof redirect_link && true === redirect_link && '_blank' === target ) { 74 // If we need to redirect/open in a new tab, then we do not need to do XHR, so return. 75 return; 76 } 77 dlmXHRinstance.handleDownloadClick( this, e ); 78 } 79 } ); 80 } 81 82 handleDownloadClick( obj, e ) { 83 e.stopPropagation(); 84 const href = obj.getAttribute( 'href' ); 85 86 const triggerObject = { 87 button: obj, 88 href, 89 buttonObj: jQuery( obj ), 90 }; 91 92 // Show the progress bar after complete download also 93 if ( triggerObject.href.indexOf( 'blob:http' ) !== -1 ) { 94 /*triggerObject.buttonObj.addClass('download-100'); 95 setTimeout(function () { 96 triggerObject.buttonObj.removeClass('download-100'); 97 }, 1500);*/ 98 99 return; 100 } 101 102 if ( '#' === triggerObject.href ) { 103 return; 104 } 105 106 e.preventDefault(); 107 dlmXHRinstance.retrieveBlob( triggerObject ); 108 } 109 110 retrieveBlob( triggerObject ) { 111 const instance = this; 112 const { 113 button, 114 href, 115 buttonObj, 116 } = triggerObject; 117 118 // This will hold the file as a local object URL 119 let _OBJECT_URL; 120 const request = new XMLHttpRequest(); 121 const $setCookie = dlmXHR.prevent_duplicates, 122 buttonTarget = buttonObj.attr( 'target' ); 123 let buttonClass = buttonObj.attr( 'class' ); 124 buttonClass = ( 'undefined' !== typeof buttonClass && '' !== buttonClass ) ? buttonClass.replace( 'dlm-download-started', '' ).replace( 'dlm-download-completed', '' ) : ''; 125 126 buttonObj.addClass( 'dlm-download-started' ); 127 button.setAttribute( 'href', '#' ); 128 button.removeAttribute( 'download' ); 129 button.setAttribute( 'disabled', 'disabled' ); 130 if ( dlmXHRProgress ) { 131 const loading_gif = '<img src="' + dlmXHRgif + '" class="dlm-xhr-loading-gif">'; 132 button.innerHTML += loading_gif; 133 } 134 135 // Trigger the `dlm_download_triggered` action 136 jQuery( document ).trigger( 'dlm_download_triggered', [ this, button, buttonObj, _OBJECT_URL, request ] ); 137 let check_headers = false;
138 request.responseType = 'blob'; 139 request.onreadystatechange = function() { 140 const { 141 status, 142 readyState, 143 statusText, 144 } = request; 145 const headers = request 146 .getAllResponseHeaders() 147 .split( '\r\n' ) 148 .reduce( ( result, current ) => { 149 const [ name, value ] = current.split( ': ' ); 150 result[ name ] = value; 151 return result; 152 }, {} ); 153 154 if ( Object.keys( headers ).length > 1 ) { 155 check_headers = true; 156 // Set the response headers to the instance so that we can use it later. 157 instance.responseHeaders = headers; 158 } 159 160 let file_name = 'download'; 161 let dlmFilenameHeader = false, 162 dlmNoWaypoints = false, 163 dlmRedirectHeader = false, 164 dlmExternalDownloadHeader = false, 165 dlmNoAccessHeader = null, 166 dlmNoAccessModalHeader = false, 167 dlmErrorHeader = false, 168 dlmDownloadIdHeader = false, 169 dlmDownloadVersionHeader = false, 170 dlmNoAccessModalTextHeader = false; 171 172 /** 173 * Old headers check 174 */ 175 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-file-name' ] ) { 176 dlmFilenameHeader = instance.responseHeaders[ 'dlm-file-name' ]; 177 } 178 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-no-waypoints' ] ) { 179 dlmNoWaypoints = true; 180 } 181 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-redirect' ] ) { 182 dlmRedirectHeader = instance.responseHeaders[ 'dlm-redirect' ]; 183 } 184 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-external-download' ] ) { 185 dlmExternalDownloadHeader = true; 186 } 187 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-no-access' ] ) { 188 dlmNoAccessHeader = instance.responseHeaders[ 'dlm-no-access' ]; 189 } 190 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-no-access-modal' ] ) { 191 dlmNoAccessModalHeader = instance.responseHeaders[ 'dlm-no-access-modal' ]; 192 } 193 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-error' ] ) { 194 dlmErrorHeader = instance.responseHeaders[ 'dlm-error' ]; 195 } 196 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-download-id' ] ) { 197 dlmDownloadIdHeader = instance.responseHeaders[ 'dlm-download-id' ]; 198 } 199 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-version-id' ] ) { 200 dlmDownloadVersionHeader = instance.responseHeaders[ 'dlm-version-id' ]; 201 } 202 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'dlm-no-access-modal-text' ] ) { 203 dlmNoAccessModalTextHeader = instance.responseHeaders[ 'dlm-no-access-modal-text' ]; 204 } 205 // End old headers check 206 207 /** 208 * New headers check 209 */ 210 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-file-name' ] ) { 211 dlmFilenameHeader = instance.responseHeaders[ 'x-dlm-file-name' ]; 212 } 213 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-no-waypoints' ] ) { 214 dlmNoWaypoints = true; 215 } 216 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-redirect' ] ) { 217 dlmRedirectHeader = instance.responseHeaders[ 'x-dlm-redirect' ]; 218 } 219 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-external-download' ] ) { 220 dlmExternalDownloadHeader = true; 221 } 222 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-no-access' ] ) { 223 dlmNoAccessHeader = instance.responseHeaders[ 'x-dlm-no-access' ]; 224 } 225 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-no-access-modal' ] ) { 226 dlmNoAccessModalHeader = instance.responseHeaders[ 'x-dlm-no-access-modal' ]; 227 } 228 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-error' ] ) { 229 dlmErrorHeader = instance.responseHeaders[ 'x-dlm-error' ]; 230 } 231 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-download-id' ] ) { 232 dlmDownloadIdHeader = instance.responseHeaders[ 'x-dlm-download-id' ]; 233 } 234 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-version-id' ] ) { 235 dlmDownloadVersionHeader = instance.responseHeaders[ 'x-dlm-version-id' ]; 236 } 237 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-no-access-modal-text' ] ) { 238 dlmNoAccessModalTextHeader = instance.responseHeaders[ 'x-dlm-no-access-modal-text' ]; 239 } 240 241 // End new headers check 242 243 if ( dlmFilenameHeader ) { 244 file_name = dlmFilenameHeader.replace( /\"/g, '' ).replace( ';', '' ); 245 file_name = decodeURI( file_name ); 246 } else if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'content-disposition' ] ) { 247 file_name = instance.responseHeaders[ 'content-disposition' ].split( /(?:filename\*=UTF-8'')|(?:filename=)/ )[ 1 ]; 248 file_name = file_name.replace( /\"/g, '' ).replace( ';', '' ); 249 // We use this method because we urlencoded it on the server so that characters like chinese or persian are not broken 250 file_name = decodeURI( file_name ); 251 } 252 253 // Error translations 254 if ( dlmErrorHeader ) { 255 //var obj = { key: undefined };
256 if ( dlmErrorHeader in dlmXHRtranslations ) { 257 dlmErrorHeader = dlmXHRtranslations[ dlmErrorHeader ]; 258 } else { 259 dlmErrorHeader = dlmXHRtranslations.error; 260 } 261 } 262 263 // Let's check for DLM request headers 264 if ( request.readyState === 2 ) { 265 // Add other checks for responseHeaders that can be taken care of from extensions. 266 if ( check_headers && 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-force-abort' ] && '' !== instance.responseHeaders[ 'x-dlm-force-abort' ] ) { 267 button.removeAttribute( 'download' ); 268 button.setAttribute( 'href', href ); 269 buttonObj.removeClass().addClass( buttonClass ).find( 'span.dlm-xhr-progress' ).remove(); 270 buttonObj.find( '.dlm-xhr-loading-gif' ).remove(); 271 request.abort(); 272 jQuery( '#dlm-no-access-modal' ).remove(); 273 return; 274 } 275 276 // If the dlm-no-waypoints header is set we need to redirect. 277 if ( dlmNoWaypoints ) { 278 request.abort(); 279 if ( dlmRedirectHeader ) { 280 window.location.href = dlmRedirectHeader; 281 return; 282 } 283 window.location.href = href; 284 return; 285 } 286 287 // If it's an external link we need to redirect. 288 if ( dlmExternalDownloadHeader ) { 289 request.abort(); 290 dlmXHRinstance.dlmExternalDownload( instance.responseHeaders, button, buttonObj, file_name, href ); 291 return; 292 } 293 294 // If there are no specific DLM headers then we need to abort and redirect. 295 const responseDLM = Object.keys( instance.responseHeaders ).filter( ( element ) => { 296 return element.indexOf( 'dlm-' ) !== -1; 297 } ).length; 298 299 if ( 0 === responseDLM ) { 300 request.abort(); 301 window.location.href = href; 302 return; 303 } 304 305 if ( dlmNoAccessHeader && 'true' === dlmNoAccessHeader ) { 306 if ( dlmNoAccessModalHeader && 0 != dlmNoAccessModalHeader ) { 307 dlmXHRinstance.dlmNoAccessModal( instance.responseHeaders ); 308 button.removeAttribute( 'download' ); 309 button.setAttribute( 'href', href ); 310 buttonObj.removeClass().addClass( buttonClass ).find( 'span.dlm-xhr-progress' ).remove(); 311 buttonObj.find( '.dlm-xhr-loading-gif' ).remove(); 312 request.abort(); 313 return; 314 } 315 } 316 317 // If there is a dlm-error headers means we have an error. Display the error and abort. 318 if ( dlmErrorHeader && '' !== dlmErrorHeader && null !== dlmErrorHeader ) { 319 dlmXHRinstance.dlmLogDownload( instance.responseHeaders, 'failed', false ); 320 button.removeAttribute( 'download' ); 321 button.setAttribute( 'href', href ); 322 buttonObj.removeClass().addClass( buttonClass ).find( 'span.dlm-xhr-progress' ).remove(); 323 buttonObj.find( '.dlm-xhr-loading-gif' ).remove(); 324 request.abort(); 325 326 if ( dlmNoAccessModalHeader && 0 != dlmNoAccessModalHeader ) { 327 dlmXHRinstance.dlmNoAccessModal( instance.responseHeaders ); 328 } else { 329 buttonObj.find( '.dlm-xhr-error' ).remove(); 330 buttonObj.append( '<span class="dlm-xhr-error">' + dlmErrorHeader + '</span>' ); 331 } 332 333 return; 334 } 335 336 // If we have a x-dlm-redirect header means this is a redirect. Let's do that. 337 if ( dlmRedirectHeader && '' !== dlmRedirectHeader && null !== dlmRedirectHeader ) { 338 dlmXHRinstance.dlmLogDownload( instance.responseHeaders, 'redirected', false, dlmRedirectHeader, dlmNoAccessHeader, buttonTarget ); 339 button.removeAttribute( 'download' ); 340 button.setAttribute( 'href', href ); 341 buttonObj.removeClass().addClass( buttonClass ).find( 'span.dlm-xhr-progress' ).remove(); 342 buttonObj.find( '.dlm-xhr-loading-gif' ).remove(); 343 request.abort(); 344 345 return; 346 } 347 } 348 349 if ( status == 404 && readyState == 2 ) { 350 const p = document.createElement( 'p' ); 351 p.innerHTML = statusText; 352 button.parentNode.appendChild( p ); 353 } 354 355 if ( status == 401 && readyState == 2 ) { 356 window.location.href = statusText; 357 return; 358 } 359 360 if ( status == 403 && readyState == 2 ) { 361 const p = document.createElement( 'p' ); 362 p.innerHTML = statusText; 363 button.parentNode.appendChild( p ); 364 } 365 366 if ( status == 200 && readyState == 4 ) { 367 const blob = request.response; 368 _OBJECT_URL = URL.createObjectURL( blob ); 369 // Remove event listener 370 button.removeEventListener( 'click', dlmXHRinstance.handleDownloadClick ); 371 // Set the download attribute of the a.download-complete to the file name 372 button.setAttribute( 'download', `${ file_name }` ); 373 // Set the href of the a.download-complete to the object URL 374 button.setAttribute( 'href', _OBJECT_URL ); 375 // Trigger click on a.download-complete 376 button.click(); 377 buttonObj.removeClass().addClass( buttonClass + ' dlm-download-complete' ); 378 379 dlmXHRinstance.attachButtonEvent(); 380 381 // Append the paragraph to the download-contaner 382 // Trigger the `dlm_download_complete` action 383 jQuery( document ).trigger( 'dlm_download_complete', [ this, button, buttonObj, _OBJECT_URL ] ); 384 dlmXHRinstance.dlmLogDownload( instance.responseHeaders, 'completed', $setCookie ); 385 // Recommended : Revoke the object URL after some time to free up resources
386 window.URL.revokeObjectURL( _OBJECT_URL ); 387 button.removeAttribute( 'download' ); 388 button.setAttribute( 'href', href ); 389 buttonObj.find( '.dlm-xhr-loading-gif' ).remove(); 390 // There is no way to find out whether user finished downloading 391 setTimeout( function() { 392 buttonObj.removeClass().addClass( buttonClass ).find( 'span.dlm-xhr-progress' ).remove(); 393 }, 4000 ); 394 } 395 }; 396 397 if ( dlmXHRProgress ) { 398 request.addEventListener( 'progress', function( e ) { 399 let total = e.total; 400 // Set the total file size from the custom response header 401 if ( 'undefined' === typeof e.total || e.total === 'undefined' || 0 === e.total ) { 402 if ( 'undefined' !== typeof instance.responseHeaders[ 'x-dlm-filesize' ] ) { 403 total = instance.responseHeaders[ 'x-dlm-filesize' ]; 404 } 405 } 406 let percent_complete = ( e.loaded / total ) * 100; 407 // Force perfect complete to have 2 digits 408 percent_complete = percent_complete.toFixed(); 409 let $class = 'dlm-download-started'; 410 buttonObj.find( 'span.dlm-xhr-progress' ).remove(); 411 // Comment below lines for the new XHR loader so that we know
411where to rever 412 $class = $class + ' dlm-download-' + Math.ceil( percent_complete / 10 ) * 10; 413 414 if ( Infinity != percent_complete ) { 415 buttonObj.append( '<span class="dlm-xhr-progress"> ' + percent_complete + '%</span>' ); 416 } 417 418 // Show spinner 419 buttonObj.removeClass().addClass( buttonClass + ' ' + $class ); 420 // Trigger the `dlm_download_progress` action 421 jQuery( document ).trigger( 'dlm_download_progress', [ this, button, buttonObj, _OBJECT_URL, e, percent_complete ] ); 422 } ); 423 } 424 425 request.onerror = function() { 426 button.removeAttribute( 'download' ); 427 button.setAttribute( 'href', href ); 428 buttonObj.removeClass().addClass( buttonClass + ' dlm-no-xhr-download' ).find( 'span.dlm-xhr-progress' ).remove(); 429 buttonObj.find( '.dlm-xhr-error' ).remove(); 430 buttonObj.append( '<span class="dlm-xhr-error">' + dlmXHRtranslations.error + '</span>' ); 431 console.log( '** An error occurred during the transaction' ); 432 }; 433 434 request.open( 'GET', href, true ); 435 request.setRequestHeader( 'Cache-Control', 'no-store, no-cache, no-transform, max-age=0' ); 436 request.setRequestHeader( 'dlm-xhr-request', 'dlm_XMLHttpRequest' ); 437 request.send(); 438 } 439 440 dlmLogDownload( headers, status, cookie, redirect_path = null, no_access = null, target = '_self' ) { 441 const currentURL = window.location.href; 442 const download_id = headers[ 'x-dlm-download-id' ] ?? headers[ 'dlm-download-id' ]; 443 const version_id = headers[ 'x-dlm-version-id' ] ?? headers[ 'dlm-version-id' ]; 444 445 const ua = navigator.userAgent || ''; 446 const isSafari = /^((?!chrome|android|crios|fxios|edgios).)*safari/i.test( ua ); 447 const isAppleSafari = isSafari && ! /CriOS|FxiOS|EdgiOS/i.test( ua ); 448 // Early redirect â skip logging if no_access = true 449 if ( no_access && redirect_path ) { 450 if ( isAppleSafari ) { 451 window.location.href = redirect_path; 452 } else { 453 const tgt = target || '_self'; 454 const downloadTab = window.open( redirect_path, tgt, 'noopener' ); 455 if ( downloadTab ) { 456 downloadTab.location.href = redirect_path; 457 } 458 } 459 return; 460 } 461 462 const params = new URLSearchParams( { 463 action: 'log_dlm_xhr_download', 464 download_id, 465 version_id, 466 status, 467 cookie, 468 currentURL, 469 nonce: headers[ 'x-dlm-nonce' ], 470 log_token: headers[ 'x-dlm-log-token' ], 471 } ); 472 473 for ( const [ key, value ] of Object.entries( headers ) ) { 474 params.append( `responseHeaders[${ key }]`, value ); 475 } 476 477 try { 478 navigator.sendBeacon( 479 dlmXHR.ajaxUrl, 480 new Blob( [ params.toString() ], { type: 'application/x-www-form-urlencoded;charset=UTF-8' } ), 481 ); 482 } catch ( e ) { 483 try { 484 fetch( dlmXHR.ajaxUrl, { method: 'POST', body: params, keepalive: true } ); 485 } catch ( _ ) {} 486 } 487 488 if ( ! redirect_path ) { 489 return; 490 } 491 492 if ( isAppleSafari ) { 493 window.location.href = redirect_path; 494 return; 495 } 496 497 const tgt = target || '_self'; 498 const downloadTab = window.open( redirect_path, tgt, 'noopener' ); 499 if ( no_access && downloadTab ) { 500 downloadTab.location.href = redirect_path; 501 } 502 } 503 504 dlmNoAccessModal( headers ) { 505 const instance = this; 506 let download = 'empty-download', 507 version = 'empty-version', 508 restriction = 'empty-restriction', 509 text = ''; 510 511 /** 512 * Old headers, will be removed in a future release. DLM Amazon S3 adds these headers. 513 */ 514 if ( 'undefined' !== typeof headers[ 'dlm-download-id' ] ) { 515 download = headers[ 'dlm-download-id' ]; 516 } 517 if ( 'undefined' !== typeof headers[ 'dlm-version-id' ] ) { 518 version = headers[ 'dlm-version-id' ]; 519 } 520 if ( 'undefined' !== typeof headers[ 'dlm-no-access-modal-text' ] ) { 521 text = headers[ 'dlm-no-access-modal-text' ]; 522 } 523 if ( 'undefined' !== typeof headers[ 'dlm-no-access-restriction' ] ) { 524 restriction = headers[ 'dlm-no-access-restriction' ]; 525 } 526 // End of old headers. 527 528 /** 529 * New headers. 530 */ 531 if ( 'undefined' !== typeof headers[ 'x-dlm-download-id' ] ) { 532 download = headers[ 'x-dlm-download-id' ]; 533 } 534 if ( 'undefined' !== typeof headers[ 'x-dlm-version-id' ] ) { 535 version = headers[ 'x-dlm-version-id' ]; 536 } 537 if ( 'undefined' !== typeof headers[ 'x-dlm-no-access-modal-text' ] ) { 538 text = headers[ 'x-dlm-no-access-modal-text' ]; 539 } 540 if ( 'undefined' !== typeof headers[ 'x-dlm-no-access-restriction' ] ) { 541 restriction = headers[ 'x-dlm-no-access-restriction' ]; 542 } 543 // End of new headers. 544 545 const data = { 546 download_id: download, 547 version_id: version, 548 modal_text: text, 549 restriction, 550 action: 'no_access_dlm_xhr_download', 551 nonce: headers[ 'x-dlm-nonce' ], 552 }; 553 554 jQuery( document ).trigger( 'dlm-xhr-modal-data', [ data, headers ] ); 555 document.dispatchEvent( 556 new CustomEvent( 'dlm-xhr-modal-data', { detail: { data, headers } } ), 557 ); 558 559 jQuery.post( dlmXHR.ajaxUrl, data, function( response ) { 560 jQuery( '#dlm-no-access-modal' ).remove(); 561 //document.body.insertAdjacentHTML('beforeend', response); 562 const tempDiv = document.createElement( 'div' ); 563 tempDiv.innerHTML = response; 564 // Extract and execute scripts from the response using a regular expression 565 const scriptRegex = /<script\b[^>]*>([\s\S]*?)<\/script>/gm; 566 // Remove script tags from tempDiv.innerHTML 567 tempDiv.innerHTML = tempDiv.innerHTML.replace( scriptRegex, '' ); 568 let match; 569 while ( ( match = scriptRegex.exec( response ) ) !== null ) { 570 const scriptTag = match[ 0 ]; 571 const scriptContent = match[ 1 ]; 572 const newScript = document.createElement( 'script' ); 573 // Check if the script has a src attribute 574 const srcMatch = scriptTag.match( /src=["']([^"']+)["']/ ); 575 if ( srcMatch ) { 576 newScript.src = srcMatch[ 1 ]; 577 } else { 578 newScript.textContent = scriptContent; 579 } 580 // Append the new script to the modal if exists 581 const modal = tempDiv.querySelector( '#dlm-no-access-modal' ); 582 if ( modal ) { 583 modal.appendChild( newScript ); 584 } else { 585 document.body.appendChild( newScript ); 586 } 587 } 588 // Append the parsed HTML elements to the body 589 while ( tempDiv.firstChild ) { 590 document.body.appendChild( tempDiv.firstChild ); 591 } 592 593 //jQuery('body').append(response); 594 jQuery( document ).trigger( data.action, [ response, data ] ); 595 596 document.dispatchEvent( 597 new CustomEvent( data.action, { detail: [ response, data ] } ), 598 ); 599 } ); 600 } 601 602 dlmExternalDownload( headers, button, buttonObj, file_name, href ) { 603 const request = new XMLHttpRequest(), 604 buttonTarget = buttonObj.attr( 'target' ); 605 let buttonClass = buttonObj.attr( 'class' ), 606 _OBJECT_URL, 607 uri = ''; 608 609 if ( 'undefined' !== typeof headers[ 'dlm-external-download' ] ) { 610 uri = headers[ 'dlm-external-download' ]; 611 } 612 if ( 'undefined' !== typeof headers[ 'x-dlm-external-download' ] ) { 613 uri = headers[ 'x-dlm-external-download' ]; 614 } 615 buttonClass = ( 'undefined' !== typeof buttonClass && '' !== buttonClass ) ? buttonClass.replace( 'dlm-download-started', '' ).replace( 'dlm-download-completed', '' ) : ''; 616 617 buttonObj.addClass( 'dlm-download-started' ); 618 button.setAttribute( 'href', '#' ); 619 button.removeAttribute( 'download' ); 620 button.setAttribute( 'disabled', 'disabled' ); 621 622 // Trigger the `dlm_download_triggered` action 623 jQuery( document ).trigger( 'dlm_download_triggered', [ this, button, buttonObj, _OBJECT_URL, request ] ); 624 625 request.responseType = 'blob'; 626 request.onreadystatechange = function() { 627 const { 628 status, 629 readyState, 630 statusText, 631 } = request; 632 633 if ( 403 === status ) { 634 dlmXHRinstance.dlmLogDownload( headers, 'failed', false ); 635 request.abort(); 636 buttonObj.find( '.dlm-xhr-error' ).remove(); 637 buttonObj.append( '<span class="dlm-xhr-error">Acces Denied to file.</span>' ); 638 return; 639 } 640 if ( status == 200 && readyState == 4 ) { 641 const blob = request.response; 642 643 _OBJECT_URL = URL.createObjectURL( blob ); 644 // Remove event listener 645 button.removeEventListener( 'click', dlmXHRinstance.handleDownloadClick ); 646 // Set the download attribute of the a.download-complete to the file name 647 button.setAttribute( 'download', `${ file_name }` ); 648 // Set the href of the a.download-complete to the object URL 649 button.setAttribute( 'href', _OBJECT_URL ); 650 // Trigger click on a.download-complete 651 button.click(); 652 buttonObj.removeClass().addClass( buttonClass + ' dlm-download-complete' ); 653 654 dlmXHRinstance.attachButtonEvent(); 655 656 // Append the paragraph to the download-contaner 657 // Trigger the `dlm_download_complete` action 658 jQuery( document ).trigger( 'dlm_download_complete', [ this, button, buttonObj, _OBJECT_URL ] ); 659 dlmXHRinstance.dlmLogDownload( headers, 'completed', false ); 660 661 // Recommended : Revoke the object URL after some time to free up resources
662 window.URL.revokeObjectURL( _OBJECT_URL ); 663 button.removeAttribute( 'download' ); 664 button.setAttribute( 'href', href ); 665 // There is no way to find out whether user finished downloading 666 buttonObj.find( '.dlm-xhr-loading-gif' ).remove(); 667 setTimeout( function() { 668 buttonObj.removeClass().addClass( buttonClass ).find( 'span.dlm-xhr-progress' ).remove(); 669 }, 1000 ); 670 } 671 }; 672 673 if ( dlmXHRProgress ) { 674 request.addEventListener( 'progress', function( e ) { 675 let total = e.total; 676 677 if ( 'undefined' === typeof e.total || e.total === 'undefined' ) { 678 total = request.getResponseHeader( 'X-DLM-Filesize' ); 679 } 680 let percent_complete = ( e.loaded / total ) * 100; 681 // Force perfect complete to have 2 digits 682 percent_complete = percent_complete.toFixed(); 683 let $class = 'dlm-download-started'; 684 buttonObj.find( 'span.dlm-xhr-progress' ).remove(); 685 // Comment below lines for the new XHR loader so that we know where to rever 686 $class = $class + ' dlm-download-' + Math.ceil( percent_complete / 10 ) * 10; 687 688 if ( Infinity != percent_complete ) { 689 buttonObj.append( '<span class="dlm-xhr-progress"> ' + percent_complete + '%</span>' ); 690 } 691 692 // Show spinner 693 buttonObj.removeClass().addClass( buttonClass + ' ' + $class ); 694 // Trigger the `dlm_download_progress` action 695 jQuery( document ).trigger( 'dlm_download_progress', [ this, button, buttonObj, _OBJECT_URL, e, percent_complete ] ); 696 } ); 697 } 698 699 request.onerror = function() { 700 button.removeAttribute( 'download' ); 701 button.setAttribute( 'href', href ); 702 buttonObj.removeClass().addClass( buttonClass + ' .dlm-no-xhr-download' ).find( 'span.dlm-xhr-progress' ).remove(); 703 buttonObj.find( '.dlm-xhr-error' ).remove(); 704 buttonObj.append( '<span class="dlm-xhr-error">' + dlmXHRtranslations.error + '</span>' ); 705 console.log( '** An error occurred during the transaction' ); 706 }; 707 708 request.open( 'GET', uri, true ); 709 request.setRequestHeader( 'Cache-Control', 'no-store, no-cache, no-transform, max-age=0' ); 710 request.setRequestHeader( 'dlm-xhr-request', 'dlm_XMLHttpRequest' ); 711 request.send(); 712 } 713}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.