Loading External JavaScript and CSS Resources

var jCanvas = false;  // Global to test if jCanvas has loaded, jQuery and AngularJS don't need this, and
                      // the others have not been examined yet.

/** This includes one or more JavaScript and/or CSS libraries, which may be CDNs (Content Delivery
* Networks), into the head of an HTML file with code such as:
*
* <script src='js/include-URLs.js'></script>
* <script>includeURLs("J-J---", true);</script>
*
* where the invocation of includeURLs() must follow where it is included in the HTML file.
*
* The first argument is a string of switches determining which URLs will be included from the array url[]
* containing a list of CND URLs counting from url[0], and each character in the switch string has the
* following meanings:
* "-" - The URL of the corresponding entry in url[] will not be included.
* "J" - The URL of the corresponding entry in url[] will be included as a JavaScript file.
* "C" - The URL of the corresponding entry in url[] will be included as a CSS file.
* Anything else other than "-" - The URL of the corresponding entry in url[] will be included as a
*       JavaScript file if it ends with ".js", as a CSS file if it ends with ".css", or an error for
*       anything else.
* The number of URL entries in url[] and name[] must match each other and the length of the switch string.
*
* The second argument, debug, is a boolean true or false used for testing and debugging.  If true alerts
* are displayed on loading showing which URLs have been loaded, otherwise nothing is displayed, provided
* there are no other errors.  In production mode this should be set to false.  The following errors are
* shown whatever the debug status:
* 1) The lengths of the url and name arrays are not the same.
* 2) An input file was not recognised as a JavaScript or CSS file.
* 3) A selected input file depends on another file which has not been included.  This is currently the
*    case when jCanvas is included which depends on jQuery, which has not been selected.
*
* This solves the problem of having to put in a specific reference to libraries on several pages, with the
* reference having to be changed on each page when a new version is used.  This is put in a folder
* accessible from the whole application, then included in the head section of each HTML page that needs it,
* so it is only necessary to change the URLs in this file.  More sophisticated methods using AJAX or the
* DOM were found not to work in this context.  The code is derived from:
* http://www.webdeveloper.com/forum/showthread.php?93461-RESOLVED-How-to-include-js-files-inside-a-js-file */
function includeURLs(switches, debug){

  var url  = [
              "http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js",
              "http://ajax.googleapis.com/ajax/libs/angularjs/1.2.13/angular.js",
              "https://raw.githubusercontent.com/caleb531/jcanvas/master/jcanvas.min.js",
              "https://cdnjs.cloudflare.com/ajax/libs/three.js/r73/three.min.js",
              "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js",
              "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"
             ];
  var name = [ // Holds the names of the corresponding libraries which are shown when debug is set to true.
              "jQuery",       // J 0 
              "AngularJS",    // J 1
              "jCanvas",      // J 2	- This depends on jQuery which must be loaded.
              "Three.js",     // J 3
              "BootstrapJS",  // J 4
              "BootstrapCSS"  // C 5
             ];
  var selected = []; // If a URL is selected the corresponding element is set to true, otherwise false.
						 
  if (url.length !== switches.length || url.length !== name.length) {
    alert("ERROR: Arrays and the switch string should all be of the same length.");
    return;
  }
  var code;
  for (var i=0; i< url.length; i++) {
    selected.push(false);
    if (switches.charAt(i) !== '-') {
      if (endsWith(url[i], ".js") || switches.charAt(i) === 'J') {
        selected[i] = true;
        if (i === 2) {
          if (!selected[0]) {
            alert("ERROR: " + name[i] + " depends on " + name[0] + " which is not included");
            return;
          }
          jCanvas = true;
        }
        code = "";
        document.write(code);
      } else if (endsWith(url[i], ".css") || switches.charAt(i) === 'C') {
        selected[i] = true;
        code = ""
        document.write(code);
      } else {
        alert("ERROR - " + url[i] + " is an unknown file type.");
        return;
      }
      if (debug) {
        alert("Index " + i + "  code " + switches.charAt(i) + " - " + name[i] + " loaded from link: " + url[i]);
        alert("Code: " + code);
      }
    }
  }
}

/** There is as yet no standard JavaScript endWith() function or method, so this was taken from the
* link: http://stackoverflow.com/questions/280634/endswith-in-javascript, where s is the string and
* t is the suffix, which is a substring of 1 or more characters.  If s ends with t this returns true,
* otherwise this returns false. */
function endsWith(s, t) {
  return s.indexOf(t, s.length - t.length) !== -1;
}
Return to Technical Details.