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 */
217226module . exports = embedHtml ;
0 commit comments