1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013, 2014, 2015, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2013, 2014, 2015, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 
 25 /**
 26  * Utility function (NOT object!) that loads external files in a specified
 27  * order (thus it'll work fine if scripts have dependencies, you just need to
 28  * pass them all in the includes array).  If a callback is given, it will be
 29  * called when all the scripts in the includes array (and possibly dependencies
 30  * generated by them using document.write) are loaded.
 31  *
 32  * Note that scripts are loaded asynchronously -- this function returns
 33  * immediately, but there's no guarantee that scripts have finished loading by
 34  * that time.  DO pass a callback if you want to execute code that rely on
 35  * those scripts.
 36  *
 37  * @param {array}	includes 	An array of strings or object; each is the URL to
 38  *                              some script OR an object with a required src property
 39  *                              and an optional id property. The id, if specified,
 40  *                              will be attached to the SCRIPT tag so that the caller
 41  *                              can access the element later.
 42  * @param {string}	baseurl 	the URL that will be prepended to scripts with a
 43  *                            relative address (not starting with http://, ftp:// or /)
 44  * @param {AjxCallback}	callback the callback will be called when all scripts were processed
 45  *
 46  * @author Mihai Bazon
 47  * 
 48  * @private
 49  */
 50 AjxInclude = function(includes, baseurl, callback, proxy) {
 51 	var head = document.getElementsByTagName("head")[0];
 52 
 53 	function loadNextScript(script) {
 54 		if (AjxEnv.isIE && script && !/loaded|complete/.test(script.readyState))
 55 			return;
 56 		if (script) {
 57 			// Clear the event handler so IE won't leak.  (Did you know
 58 			// that Microsoft knew about the mem. leak bug in 1998
 59 			// and by the end of 2005 it's still not fixed? :-p
 60 			// http://www.bazon.net/mishoo/home.epl?NEWS_ID=1281 )
 61 			script[AjxInclude.eventName] = null;
 62 		}
 63 		window.status = "";
 64 		if (includes.length > 0) {
 65             var object = includes.shift();
 66 			var fullurl = typeof object == "string" ? object : object.src;
 67 			var orig = fullurl;
 68 			if (!/^((https?|ftps?):\x2f\x2f|\x2f)/.test(fullurl)) {
 69 				if (baseurl)
 70 					fullurl = baseurl + fullurl;
 71 				if (cacheKillerVersion)
 72 					fullurl += "?v=" + cacheKillerVersion;
 73 			} else if (proxy && fullurl.indexOf('/') != 0) {
 74  				// fully qualified URL-s will go through our proxy
 75  				fullurl = proxy + AjxStringUtil.urlEncode(fullurl);
 76 			}
 77 			var script = document.createElement("script");
 78 			var handler = AjxCallback.simpleClosure(loadNextScript, null, script);
 79 			if (script.attachEvent) {
 80 				script.attachEvent("onreadystatechange", handler);
 81 				script.attachEvent("onerror", handler);
 82 			}
 83             else if (script.addEventListener) {
 84 				script.addEventListener("load", handler, true);
 85 				script.addEventListener("error", handler, true);
 86 			}
 87 			script.type = "text/javascript";
 88 			script.src = fullurl;
 89 			window.status = "Loading script: " + orig;
 90 
 91             var oscript = null;
 92             if (object.id) {
 93                 script.id = object.id;
 94                 oscript = document.getElementById(object.id);
 95             }
 96             if (oscript) {
 97                 oscript.parentNode.replaceChild(script, oscript);
 98             }
 99             else {
100                 head.appendChild(script);
101             }
102 		} else if (includes.length == 0) {
103 			script = null;
104 			head = null;
105 			if (callback)
106 				callback.run();
107 		}
108 	};
109 
110 	loadNextScript(null);
111 };
112