Newer
Older
reroad-test / 2020-ryusei / aframe-master / src / utils / src-loader.js
@ryusei ryusei on 22 Oct 2020 4 KB パノラマ表示
/* global Image, XMLHttpRequest */
var debug = require('./debug');

var warn = debug('utils:src-loader:warn');

/**
 * Validate a texture, either as a selector or as a URL.
 * Detects whether `src` is pointing to an image or video and invokes the appropriate
 * callback.
 *
 * `src` will be passed into the callback
 *
 * @params {string|Element} src - URL or media element.
 * @params {function} isImageCb - callback if texture is an image.
 * @params {function} isVideoCb - callback if texture is a video.
 */
function validateSrc (src, isImageCb, isVideoCb) {
  checkIsImage(src, function isAnImageUrl (isImage) {
    if (isImage) {
      isImageCb(src);
      return;
    }
    isVideoCb(src);
  });
}

/**
 * Validates six images as a cubemap, either as selector or comma-separated
 * URLs.
 *
 * @param {string} src - A selector or comma-separated image URLs. Image URLs
          must be wrapped by `url()`.
 * @param {string} src - A selector or comma-separated image URLs. Image URLs
          must be wrapped by `url()`.
 */
function validateCubemapSrc (src, cb) {
  var aCubemap;
  var cubemapSrcRegex = '';
  var i;
  var urls;
  var validatedUrls = [];

  for (i = 0; i < 5; i++) {
    cubemapSrcRegex += '(url\\((?:[^\\)]+)\\),\\s*)';
  }
  cubemapSrcRegex += '(url\\((?:[^\\)]+)\\)\\s*)';
  urls = src.match(new RegExp(cubemapSrcRegex));

  // `src` is a comma-separated list of URLs.
  // In this case, re-use validateSrc for each side of the cube.
  function isImageCb (url) {
    validatedUrls.push(url);
    if (validatedUrls.length === 6) {
      cb(validatedUrls);
    }
  }
  if (urls) {
    for (i = 1; i < 7; i++) {
      validateSrc(parseUrl(urls[i]), isImageCb);
    }
    return;
  }

  // `src` is a query selector to <a-cubemap> containing six $([src])s.
  aCubemap = validateAndGetQuerySelector(src);
  if (!aCubemap) { return; }
  if (aCubemap.tagName === 'A-CUBEMAP' && aCubemap.srcs) {
    return cb(aCubemap.srcs);
  }
  // Else if aCubeMap is not a <a-cubemap>.
  warn('Selector "%s" does not point to <a-cubemap>', src);
}

/**
 * Parses src from `url(src)`.
 * @param  {string} src - String to parse.
 * @return {string} The parsed src, if parseable.
 */
function parseUrl (src) {
  var parsedSrc = src.match(/\url\((.+)\)/);
  if (!parsedSrc) { return; }
  return parsedSrc[1];
}

/**
 * Call back whether `src` is an image.
 *
 * @param {string|Element} src - URL or element that will be tested.
 * @param {function} onResult - Callback with whether `src` is an image.
 */
function checkIsImage (src, onResult) {
  var request;

  if (src.tagName) {
    onResult(src.tagName === 'IMG');
    return;
  }
  request = new XMLHttpRequest();

  // Try to send HEAD request to check if image first.
  request.open('HEAD', src);
  request.addEventListener('load', function (event) {
    var contentType;
    if (request.status >= 200 && request.status < 300) {
      contentType = request.getResponseHeader('Content-Type');
      if (contentType == null) {
        checkIsImageFallback(src, onResult);
      } else {
        if (contentType.startsWith('image')) {
          onResult(true);
        } else {
          onResult(false);
        }
      }
    } else {
      checkIsImageFallback(src, onResult);
    }
    request.abort();
  });
  request.send();
}

function checkIsImageFallback (src, onResult) {
  var tester = new Image();
  tester.addEventListener('load', onLoad);
  function onLoad () { onResult(true); }
  tester.addEventListener('error', onError);
  function onError () { onResult(false); }
  tester.src = src;
}

/**
 * Query and validate a query selector,
 *
 * @param  {string} selector - DOM selector.
 * @return {object|null|undefined} Selected DOM element if exists.
           null if query yields no results.
           undefined if `selector` is not a valid selector.
 */
function validateAndGetQuerySelector (selector) {
  try {
    var el = document.querySelector(selector);
    if (!el) {
      warn('No element was found matching the selector: "%s"', selector);
    }
    return el;
  } catch (e) {  // Capture exception if it's not a valid selector.
    warn('"%s" is not a valid selector', selector);
    return undefined;
  }
}

module.exports = {
  parseUrl: parseUrl,
  validateSrc: validateSrc,
  validateCubemapSrc: validateCubemapSrc
};