Skip to content

Commit ed23d55

Browse files
authored
Merge pull request #45 from conversant/release/2.5.0
Release/2.5.0
2 parents da7017c + fb38003 commit ed23d55

5 files changed

Lines changed: 8671 additions & 43 deletions

File tree

karma.conf.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ module.exports = function(config) {
4040

4141
// Number of browsers to run in parallel [set to 1 to avoid timing-based tests from failing]
4242
concurrency: 1,
43-
44-
browsers: ['Firefox', 'Chrome', 'Safari']
43+
// Using SafariNative launcher to due changes in Mojave: https://github.com/karma-runner/karma-safari-launcher/issues/29
44+
browsers: ['Firefox', 'Chrome', 'SafariNative']
4545

4646
});
4747

lib/dom/embedHtml.js

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

3-
var lastParent,
4-
insContainer,
3+
var insContainer,
54
insId,
65
insCounter = 0,
76
cloneDataAttrib = 'data-adlibs-clone';
@@ -46,11 +45,12 @@ var addToDom = function (elem, target) {
4645
* nor can it be used inside this function
4746
*
4847
* @param inputScriptElem {Element} Input Script Element
48+
* @param win {Object}
4949
* @returns {Element}
5050
*/
51-
var customCloneScript = function (inputScriptElem) {
51+
var customCloneScript = function (inputScriptElem, win) {
5252
var inputScriptAttrib,
53-
outputScriptElem = document.createElement('script'),
53+
outputScriptElem = win.document.createElement('script'),
5454
inputScriptAttribs = inputScriptElem.attributes,
5555
i = 0;
5656

@@ -75,10 +75,11 @@ var customCloneScript = function (inputScriptElem) {
7575
* Scripts have to be handled differently because the script code will not execute unless they are processed this way
7676
*
7777
* @param elemToClone
78+
* @param win {Object}
7879
* @returns {Node | Element}
7980
*/
80-
var cloneElem = function (elemToClone) {
81-
var clonedElem = (isAScript(elemToClone)) ? customCloneScript(elemToClone) : elemToClone.cloneNode(true);
81+
var cloneElem = function (elemToClone, win) {
82+
var clonedElem = (isAScript(elemToClone)) ? customCloneScript(elemToClone, win) : elemToClone.cloneNode(true);
8283
clonedElem.setAttribute && clonedElem.setAttribute(cloneDataAttrib, '1'); //Mark element as being a clone
8384
return clonedElem;
8485
};
@@ -89,10 +90,11 @@ var cloneElem = function (elemToClone) {
8990
*
9091
* @param inputElem {Node | Element}
9192
* @param targetElem {Node | Element}
93+
* @param win {Object}
9294
*
9395
* @returns {Node | Element}
9496
*/
95-
var recursiveCloneAndAddToDom = function (inputElem, targetElem) {
97+
var recursiveCloneAndAddToDom = function (inputElem, targetElem, win) {
9698
var childClone,
9799
childElem,
98100
clonedElem = inputElem.cloneNode(false), //Shallow clone
@@ -102,9 +104,9 @@ var recursiveCloneAndAddToDom = function (inputElem, targetElem) {
102104
for (; i < inputElem.childNodes.length; i++) {
103105
childElem = inputElem.childNodes[i];
104106
if (childElem.hasChildNodes() && !isAScript(childElem)) {
105-
childClone = recursiveCloneAndAddToDom(childElem, clonedElem);
107+
childClone = recursiveCloneAndAddToDom(childElem, clonedElem, win);
106108
} else {
107-
childClone = cloneElem(childElem);
109+
childClone = cloneElem(childElem, win);
108110
addToDom(childClone, clonedElem);
109111
}
110112
}
@@ -118,27 +120,27 @@ var recursiveCloneAndAddToDom = function (inputElem, targetElem) {
118120
*
119121
* @param htmlString {String} HTML String to Add to the page
120122
* @param [parentElem] {Node | Element} Parent element to attach 'htmlString' as a child to; defaults to document.body
123+
* @param win {Object}
121124
* @returns {boolean}
122125
*/
123-
var insertInlineHtmlString = function (htmlString, parentElem) {
124-
parentElem = parentElem || lastParent || document.body;
125-
lastParent = parentElem;
126+
var insertInlineHtmlString = function (htmlString, parentElem, win) {
127+
parentElem = parentElem || win.document.body;
126128

127129
//Create an 'ins' tag to be a container to hold htmlString
128-
(insContainer = createInsContainer()).innerHTML = htmlString;
130+
(insContainer = createInsContainer(win)).innerHTML = htmlString;
129131

130132
//Add the HTML to 'parentElem' by recursively creating clones
131-
recursiveCloneAndAddToDom(insContainer, parentElem);
133+
recursiveCloneAndAddToDom(insContainer, parentElem, win);
132134
return true;
133135
};
134136

135137
/**
136138
* Returns an 'ins' element with a unique ID and class 'adlibs-ins'
137-
*
139+
* @param win {Object}
138140
* @returns {HTMLModElement}
139141
*/
140-
var createInsContainer = function () {
141-
var ins = document.createElement('ins');
142+
var createInsContainer = function (win) {
143+
var ins = win.document.createElement('ins');
142144
insId = 'adlibs-ins-' + (++insCounter);
143145
ins.setAttribute('id', insId);
144146
ins.setAttribute('class', 'adlibs-ins');
@@ -149,10 +151,11 @@ var createInsContainer = function () {
149151
* Uses document.writeln to add an HTML string to the page
150152
*
151153
* @param htmlString {string} HTML String to Add to the page
154+
* @param win {Object}
152155
* @returns {boolean}
153156
*/
154-
var docWriteHtmlString = function (htmlString) {
155-
document.writeln(htmlString); //jshint ignore: line
157+
var docWriteHtmlString = function (htmlString, win) {
158+
win.document.writeln(htmlString); //jshint ignore: line
156159
return true;
157160
};
158161

@@ -180,28 +183,36 @@ var isNativeFunction = function (value) {
180183
* @param htmlString {string}
181184
* @param [parentElem] {HTMLElement} Parent element to attach 'htmlString' as a child to (this is only used if the document readyState is complete or interactive)
182185
* @param [callback] {function} Callback function
186+
* @param [win] {Object} Optional window reference to write into
183187
*
184188
*/
185-
var embedHtml = function (htmlString, parentElem, callback) {
186-
if (document.readyState === 'complete' || document.readyState === 'interactive') {
189+
var embedHtml = function (htmlString, parentElem, callback, win) {
190+
var originalDocWrite,
191+
originalDocWriteln;
192+
193+
win = win || window;
194+
originalDocWrite = win.document.write;
195+
originalDocWriteln = win.document.writeln;
196+
197+
if (win.document.readyState === 'complete' || win.document.readyState === 'interactive') {
187198
//Overwrite document.write and document.writeln (so we can handle nested document.writes)
188-
if (isNativeFunction(document.write)) {
189-
document.write = embedHtml.bind(this);
199+
if (isNativeFunction(win.document.write)) {
200+
win.document.write = embedHtml.bind(this);
190201
}
191202

192-
if (isNativeFunction(document.writeln)) {
193-
document.writeln = embedHtml.bind(this);
203+
if (isNativeFunction(win.document.writeln)) {
204+
win.document.writeln = embedHtml.bind(this);
194205
}
195206

196-
//Keep track of our parent element because document.write calls wont pass that in
197-
parentElem = parentElem || lastParent;
198-
insertInlineHtmlString(htmlString, parentElem);
207+
insertInlineHtmlString(htmlString, parentElem, win);
199208
} else {
200-
//Restore document.write and document.writeln to their native implementations
201-
delete document.write;
202-
delete document.writeln;
203-
docWriteHtmlString(htmlString);
209+
delete win.document.write; //Restore native implementation
210+
delete win.document.writeln; //Restore native implementation
211+
docWriteHtmlString(htmlString, win); //Write contents to DOM using native implementation
204212
}
213+
//Restore document.write and document.writeln
214+
win.document.write = originalDocWrite;
215+
win.document.writeln = originalDocWriteln;
205216

206217
//Pass the container element to the callback
207218
if (typeof callback === 'function') {
@@ -211,7 +222,5 @@ var embedHtml = function (htmlString, parentElem, callback) {
211222

212223
/**
213224
* Handles adding HTML elements to the DOM, in whatever state the document is in
214-
*
215-
* @returns {boolean}
216225
*/
217226
module.exports = embedHtml;

0 commit comments

Comments
 (0)