From 56aef196f70f2949706ac865e1e19395e7549b7e Mon Sep 17 00:00:00 2001 From: Kai Moritz Date: Tue, 26 Feb 2013 13:58:33 +0100 Subject: [PATCH] The script overwrites document.write in order to serialize all rendering The first version of openx.js had sometimes freezed the IE 8. The cause of this probably was a race-condition while moving the nodes with the banner to their final destination. Because of that, the script serializes all modifications of the DOM strictly now. Implementation-Details: * The HTML delivered by OpenX is parsed, in order to detect included script-tags. * HTML-code is written to the destination-node directly. * script-tags, that load additional code are loaded via a script-node, that is appended to the end of the page. The script waits, until the additional code is loaded, by adding an onload-event to the appended script-node. * script-tags with inline-code are executed directly via eval(). * Calls to document.write() in the additional scripts are catched. To achieve that, openx.js overwrites document.write with its own implementation, that simply adds the code to an execution-queue, that is processed, when the onload-event fires or when the eval()-call returns. TODO: * Not tested with IE! --- openx.js | 145 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 30 deletions(-) diff --git a/openx.js b/openx.js index 68cc431..b916e78 100644 --- a/openx.js +++ b/openx.js @@ -4,18 +4,31 @@ (function( openx, $, undefined ) { + var body = document.getElementsByTagName('body')[0]; + + var id; + var node; + var count = 0; var slots = {}; - var ads = new Array(); + var ads = []; + + + openx.show_ads = function(server, zones) { + document.write = render; + document.writeln = render; - openx.fetch_ads = function(server, zones) { + var domain = document.location.protocol == 'https:' ? 'https://' + server + ':8443':'http://' + server; - var spc; + var spc = document.createElement('script'); - spc = ""); - } + var fl = document.createElement('script'); - openx.render_ads = function() { + fl.type = 'text/javascript'; + fl.async = false; + fl.defer = false; + + fl.src = domain + '/www/delivery/fl.js'; + + body.appendChild(fl); + + } + + function init_ads() { - /** Render the fetched ad-banners... */ for (var id in slots) { - // alert(id + ": " + OA_output[id]); - if (typeof(OA_output[id]) != 'undefined' && OA_output[id] != '') { - document.write("
"); - document.write(OA_output[id]); - document.write("
"); + if (typeof(OA_output[id]) != 'undefined' && OA_output[id] != '') ads.push(id); - // alert('Banner ' + id + ': ' + OA_output[id]); - } } + render_ad(); + } - openx.show_ads = function() { + function render_ad() { - /** Show the rendered banners */ - for (var i=0; i]*)>([\s\S]*?)<\\?\/script>/i.exec(OA_output[id]); + if (result == null) { + /** Invalid syntax in delivered banner-code: ignoring the rest of this banner-code! */ + // alert(OA_output[id]); + OA_output[id] = ""; + render_ad(); + return; + } + /** Remember iinline-code, if present */ + src = result[1] + inline = result[2]; + /** Strip all text up to and including "" from OA_output[id] */ + OA_output[id] = OA_output[id].slice(result[0].length,OA_output[id].length); + result = /src\s*=\s*['"]([^'"]*)['"]/i.exec(src); + if (result == null) { + /** script-tag with inline-code: execute inline-code! */ + eval(inline); + } + else { + /** script-tag with src-URL! */ + script = document.createElement('script'); + script.type = 'text/javascript'; + script.async = false; + script.defer = false; + script.src = result[1]; + script.onload = render_ad; + /** The banner might not be rendered fully, or include more calls to document.write(). */ + ads.push(id); + /** Load the script and halt all work until the script is loaded and executed... */ + body.appendChild(script); // << The onload-event is only fired when appendChild is used! + return; + } + } + node.append(OA_output[id]); + OA_output[id] = ""; + + /** This statement will only reached, when no script-element was rendered! */ + render_ad(); + + } + + function render() { + + if (id == undefined) + return; + + var str = ""; + for (var i=0; i < arguments.length; i++) + str += arguments[i]; + + OA_output[id] = str + OA_output[id]; + } } ( window.openx = window.openx || {}, jQuery )); -- 2.20.1