Attempting to load API and JS file dynamically

I am trying to load the Skyscanner API dynamically, but it does not work. I tried all possible ways that I could think of, and everything that happens, the content disappears.

I tried console.log, which did not give any results; I tried the elements from the chrome tools for developers, and all the css content remains the same, but the content disappears (I thought this could add a display: none in html / body). I tried all of the Google tricks asynchronous, but again a blank page. I tried all js plugins for asynchronous loading with the same results.

The Skyscanner API documentation is bad, and although they offer a callback, it doesn’t work the way the Google API callback does.

Example: http://jsfiddle.net/7TWYC/

An example with loading the API in the main section: http://jsfiddle.net/s2HkR/

So how can I load api on click or async button? Without the file located in the HEAD section. If there is a way to prevent document.write to make the page blank or in any other way. I would not mind using simple js, jQuery or PHP.

EDIT:

I set the bounty to 250 50% earlier.

Orlando Leite answered a very close idea on how to make this download asynch api, although some functions do not work, such as date picker, and I cannot set the style.

I am looking for an answer from which I can use all the functions so that it works as if it loaded at boot time.

Here is the updated Orlando fiddle: http://jsfiddle.net/cxysA/12/

-

EDIT 2 ON Gijs ANSWER:

Gijs mentioned two rewriting links for document.write. That sounds awesome, but I think it's impossible to accomplish what I'm trying.

I used John Resig's method to prevent which document.write can be found here: http://ejohn.org/blog/xhtml-documentwrite-and-adsense/

When I used this method, I successfully load the API, but the snippets.js file does not load at all.

Fiddle: http://jsfiddle.net/9HX7N/

+8
javascript jquery api
source share
3 answers

For problem cases like this, you can simply overwrite document.write . Hacker, damn it, but it works, and you decide where all the content is. See for example. This blogpost is from John Rezig . This ignores IE, but with a bit of work, the trick also works in IE, see, for example. this blogpost .

So, I suggest overwriting document.write your own function, if necessary, deliver the output file and put it where you like (for example, in the div at the bottom of your <body> '). This should prevent the script from disabling the content of your page.

Edit: Ok, so I had / it took a while to learn this script. For future reference, use http://jsbeautifier.org/ to explore third-party scripts. It is much easier to read this way. Fortunately, there is practically no obfuscation / minimization, and therefore you have an addition to their API documentation (which I could not find, by the way, I found only “code masters” that I was not interested in).

Here is an almost working example: http://jsfiddle.net/a8q2s/1/

Here are the steps I took:

  • override document.write . This should happen before you load the initial script. Your replacement function should add your line of code to the DOM. Do not call the old document.write , which will simply lead to errors and in any case will not do what you want. In this case, you are lucky because all the content is in one call to document.write (check the source of the initial script). If this were not so, you would have to get everything until the HTML that they gave you was valid and / or you were sure that there would be nothing more.
  • load the initial script when the button is clicked using jQuery $.getScript or equivalent. Pass a callback function (I use a link to a named function for clarity, but you can enable it if you want).
  • Download Skyscanner to download the module.

Edit # 2: Hah, they have an API ( skyscanner.loadAndWait ) to receive a callback after loading their script. Using this works:

http://jsfiddle.net/a8q2s/3/

(note: it still seems to use a timeout inside)

+3
source share

I believe you want:

 function loadSkyscanner() { function loaded() { t.skyscanner.load('snippets', '1', {'nocss' : true}); var snippet = new t.skyscanner.snippets.SearchPanelControl(); snippet.setCurrency('GBP'); snippet.setDeparture('uk'); snippet.draw(document.getElementById('snippet_searchpanel')); } var t = document.getElementById('sky_loader').contentWindow; var head = t.document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.onreadystatechange= function() { if(this.readyState == 'complete') loaded(); } script.onload= loaded; script.src= 'http://api.skyscanner.net/api.ashx?key=PUT_HERE_YOUR_SKYSCANNER_API_KEY'; head.appendChild(script); } $("button").click(function(e) { loadSkyscanner(); }); 

Loads skyscanner into iframe # sky_loader, after calling the load function to create SearchPanelControl. But, in the end, the fragment is drawn in the main document. This is a really weird workaround, but it works.

The only limitation is you need an iframe. But you can hide it with display:none .

Working example

EDIT

Sorry, man, I have not seen this. Now we see how terrible the skyscanner API is. It places two divs for autocomplete, but does not apply to the element that you call to draw, but to the document. When a script is loaded in an iframe, the document is an iframe document.

There is a solution, but I do not recommend, this is really a workaround:

  function loadSkyscanner() { var t; this.skyscanner; var iframe = $("<iframe id=\"sky_loader\" src=\"http://fiddle.jshell.net/orlleite/2TqDu/6/show/\"></iframe>"); function realWorkaround() { var tbody = t.document.getElementsByTagName("body")[0]; var body = document.getElementsByTagName("body")[0]; while( tbody.children.length != 0 ) { var temp = tbody.children[0]; tbody.removeChild( temp ); body.appendChild( temp ); } } function snippetLoaded() { skyscanner = t.skyscanner; var snippet = new skyscanner.snippets.SearchPanelControl(); snippet.setCurrency('GBP'); snippet.setDeparture('uk'); snippet.draw(document.getElementById('snippet_searchpanel')); setTimeout( realWorkaround, 2000 ); } var loaded = function() { console.log( "loaded" ); t = document.getElementById('sky_loader').contentWindow; t.onLoadSnippets( snippetLoaded ); } $("body").append(iframe); iframe.load(loaded); } $("button").click(function(e) { loadSkyscanner(); }); 

Load the iframe with another html that loads and calls the callback when the fragment loads. After loading, create the fragment you want and after setting the timeout, because we cannot know when SearchPanelControl is loading. This realWorkaround moves the autocomplete div into the main document.

Here you can see an example of work

Loaded iframe

EDIT

The detected error was fixed and the link was updated.

the for loop went through and added some time, now it works better.

  while( tbody.children.length != 0 ) { var temp = tbody.children[0]; tbody.removeChild( temp ); body.appendChild( temp ); } 
+5
source share

In the skyrunner.js file, they use document.write to make the page blank when loading the callback ... So these are some of the consequences in your script.

  • This makes the page blank when you click the button.
  • Thus, it removes everything from the page even “jQuery.js”, so the callback does not work. ie the main function cannot be called because it is written using jQuery.
  • And you missed the target 'div' tag with id = map (according to the code). This is actually the target where the map is loaded.
  • Another thing I've observed is that it is not really a div in the current context, i.e. api maps to load.

Here you should go with the old school approach, that is .. You should include your skyrunner.js file at the top of the contents of the chapter.

So, try downloading this file and including it in the main tag.

thanks

+3
source share

All Articles