Link to home
Start Free TrialLog in
Avatar of MJ
MJFlag for United States of America

asked on

How To Create A Pollyfill that converts document.write in Async Loading

I have a JavaScript file that uses document.writes. This file needs to be loaded asynchronously on a new web app. The issue is that this file is used on a bunch of other web apps. synchronously. I was told I could write a pollyfill to make the document.writes into asynchronous loading. I have never written a polyfill, so I'm looking for advice and examples on how to do this? I have looked at a few videos and web sites but still not sure how to approach this? Appreciate any help or guidance.

Thanks!
Avatar of leakim971
leakim971
Flag of Guadeloupe image

create a pollyfil that convert document.write (an existing function) in Async Loading
I believe this is not the description of a polyfill something cconverting extsing function
It is something you create to add functionality/ies to existing object

so I believe the issue here, the recommendation you receive :)

Anyway from what I understood here my two cents :

var oldDocumentWrite = document.write;
document.write = function(what) {
       // some ajax or script download here
       // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests#Example_creating_a_standard_function_to_read_external_files
}
Just to clarify - the script does this

document.write('some output');

Which is fine when your page is loading but if run after loading wipes out your page correct?

What you want to do is convert these document.write in to something else that can achieve the same thing but work after the script is loaded - which may be after document.load.

My first question - why can't you amend the original script to take out the document.write and rather uses something more portable?

My second question is can you give us some examples of what the script currently does and how it will be used in the new implementation?
Avatar of MJ

ASKER

Hi Julian,
First of all, thank you for the response and all the help you always provide, To answer your questions, the scripts are always regenerated each time I need to make updates etc.  This is due to the scripts being generated by Adobe's Dynamic Tag Manager. For testing purposes (which I can currently work -around) the files are pushed to the Akamai CDN. Once we test the changes, we generate the new files and download them to be hosted on our web servers for a production release. One issue is this code is shared by most of our web apps (approx. 11) and these all run fine the way the synchronous code is already structured without any changes. I have a new web app that can't load the JS script explicitly so we are trying to figure out how to get it to work>? Here is the URL of the script:   https://www.bankofthewest.com/js/DTM/botw/52526302225396ab63a2d854ed0c3ac8d6b71e8e/satelliteLib-8b0957229e4e0b480ac27c82c946e106ec00b3ce.js

You can search for ".write" and it will be your 1st match.

Thanks!
That seems to write out <script> tags

using Leak's suggestion if you add this to your page before including that JS
document.write = function(x) {
 console.log(x)x;
}

Open in new window

you should see the output from the write's to the console.

I tried this and it seems to do something but I don't know what the use case is here - I had to define some functions to make the script work so this is just a guess
<!doctype html>
<html>
<head>
<script src="http://code.jquery.com/jquery.js"></script>
<script>
/**
 * Start of polyfills
 * The following functions I added to make the code work - these should not be included in the final solution
 */

function _dtmNonHostedDomain()
{
  return true;
}
function _dtmSpecialChar(x)
{
  console.log(x);
}
var __ = {
  map: function(o, fn) {
    for(var x in o) {
      fn(x, o[x]);
    }
  }
}
/** 
 * End of polyfills
 */

// Redirect .write to your own code as per Leak's suggestion

document.write = function(a) {
  // Create a <Script> tag
  var s = document.createElement('script');
  
  // Get the src	  
  var result = a.match(/src="(.*?)"/);

  // Set the src
  s.src = result[1];

  // Add to <head> or <body> as required
  $('body').append(s);
}
</script>
</head>
<body>
<script>
// load source on document ready
$(function() {
  var s = document.createElement('script');
  s.src = 'https://www.bankofthewest.com/js/DTM/botw/52526302225396ab63a2d854ed0c3ac8d6b71e8e/satelliteLib-8b0957229e4e0b480ac27c82c946e106ec00b3ce.js';
  $('body').append(s);
});
</script>
</body>
</html>

Open in new window

Avatar of MJ

ASKER

Thank you both very much. You both are priceless resources! Truly! I will test the above code and get back to you. I may have somefollow-up questions so stay tuned! :0)
Avatar of MJ

ASKER

Hi Julian,
I looked at your code but I'm confused.  I have a few questions:
1) Why did you have to add those functions to get it to work? ==> "The following functions I added to make the code work..."

2) I'm not sure how this whole thing actually works?  Will it take every document.write in the file https://www.bankofthewest.com/js/DTM/botw/52526302225396ab63a2d854ed0c3ac8d6b71e8e/satelliteLib-8b0957229e4e0b480ac27c82c946e106ec00b3ce.js and convert to an asynchronous call?

3) Is there any way to limit which files pollyfill is applied to?

4) The code is always obfuscated and document.write in the files I'm targeting becomes something like n.write etc. Does it matter?
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of MJ

ASKER

Thanks for the response. Much appreciated! As far as limiting the Pollyfill to specific files. Is it possible to only apply to a specific directory and its children on a specific host name?
Avatar of MJ

ASKER

Thank you both!
You are welcome