b916e78934b3807904f775b27b66cb58c0d0dd56
[openx] / openx.js
1 /** Optimized methods for fetching ad-banners via OpenX */
2
3 /** see: http://enterprisejquery.com/2010/10/how-good-c-habits-can-encourage-bad-javascript-habits-part-1/ */
4
5 (function( openx, $, undefined ) {
6
7   var body = document.getElementsByTagName('body')[0];
8
9   var id;
10   var node;
11
12   var count = 0;
13   var slots = {};
14   var ads = [];
15
16
17   openx.show_ads = function(server, zones) {
18
19     document.write = render;
20     document.writeln = render;
21
22     var domain = document.location.protocol == 'https:' ? 'https://' + server + ':8443':'http://' + server;
23
24     var spc = document.createElement('script');
25
26     spc.type = 'text/javascript';
27     spc.async = false;
28     spc.defer = false;
29
30     spc.src = domain;
31     spc.src += "/www/delivery/spc.php?zones=";
32
33     /** Only fetch banners, that are really included in this page */
34     $('.oa').each(function() {
35       var node = $(this);
36       for(var name in zones) {
37         if (node.hasClass(name)) {
38           var id = 'oa_' + ++count;
39           slots[id] = node;
40           spc.src += escape(id + '=' + zones[name] + "|");
41         }
42       }
43     });
44
45     spc.src += "&nz=1&source=" + escape(OA_source);
46     spc.src += "&r=" + Math.floor(Math.random()*99999999);
47     spc.src += "&block=1&charset=UTF-8";
48
49     if (window.location)   spc.src += "&loc=" + escape(window.location);
50     if (document.referrer) spc.src += "&referer=" + escape(document.referrer);
51
52     spc.onload = init_ads;
53
54     body.appendChild(spc);
55
56
57     var fl = document.createElement('script');
58
59     fl.type = 'text/javascript';
60     fl.async = false;
61     fl.defer = false;
62
63     fl.src = domain + '/www/delivery/fl.js';
64
65     body.appendChild(fl);
66
67   }
68
69   function init_ads() {
70
71     for (var id in slots) {
72       if (typeof(OA_output[id]) != 'undefined' && OA_output[id] != '')
73         ads.push(id);
74     }
75
76     render_ad();
77
78   }
79
80   function render_ad() {
81
82     if (ads.length == 0) {
83       id = undefined;
84       node = undefined;
85       return;
86     }
87
88     id = ads.pop();
89     node = slots[id];
90
91     // node.append(id + ": " + node.attr('class'));
92
93     var result;
94     var script;
95     var src;
96     var inline;
97
98     while ((result = /<script/i.exec(OA_output[id])) != null) {
99       node.append(OA_output[id].slice(0,result.index));
100       /** Strip all text before "<script" from OA_output[id] */
101       OA_output[id] = OA_output[id].slice(result.index,OA_output[id].length);
102       result = /^([^>]*)>([\s\S]*?)<\\?\/script>/i.exec(OA_output[id]);
103       if (result == null) {
104         /** Invalid syntax in delivered banner-code: ignoring the rest of this banner-code! */
105         // alert(OA_output[id]);
106         OA_output[id] = "";
107         render_ad();
108         return;
109       }
110       /** Remember iinline-code, if present */
111       src = result[1]
112       inline = result[2];
113       /** Strip all text up to and including "</script>" from OA_output[id] */
114       OA_output[id] = OA_output[id].slice(result[0].length,OA_output[id].length);
115       result = /src\s*=\s*['"]([^'"]*)['"]/i.exec(src);
116       if (result == null) {
117         /** script-tag with inline-code: execute inline-code! */
118         eval(inline);
119       }
120       else {
121         /** script-tag with src-URL! */
122         script = document.createElement('script');
123         script.type = 'text/javascript';
124         script.async = false;
125         script.defer = false;
126         script.src = result[1];
127         script.onload = render_ad;
128         /** The banner might not be rendered fully, or include more calls to document.write(). */
129         ads.push(id);
130         /** Load the script and halt all work until the script is loaded and executed... */
131         body.appendChild(script); // << The onload-event is only fired when appendChild is used!
132         return;
133       }
134     }
135     node.append(OA_output[id]);
136     OA_output[id] = "";
137
138     /** This statement will only reached, when no script-element was rendered! */
139     render_ad();
140
141   }
142
143   function render() {
144
145     if (id == undefined)
146       return;
147
148     var str = "";
149     for (var i=0; i < arguments.length; i++)
150       str += arguments[i];
151
152     OA_output[id] = str + OA_output[id];
153
154   }
155
156 } ( window.openx = window.openx || {}, jQuery ));