<commit_before>import { createCreativeLinear } from '../creative/creative_linear';
import { createClosedCaptionFile } from '../closed_caption_file';
import { createIcon } from '../icon';
import { createInteractiveCreativeFile } from '../interactive_creative_file';
import { createMediaFile } from '../media_file';
import { createMezzanine } from '../mezzanine';
import { parserUtils } from './parser_utils';

/**
 * This module provides methods to parse a VAST Linear Element.
 */

/**
 * Parses a Linear element.
 * @param  {Object} creativeElement - The VAST Linear element to parse.
 * @param  {any} creativeAttributes - The attributes of the Linear (optional).
 * @return {Object} creative - The creativeLinear object.
 */
export function parseCreativeLinear(creativeElement, creativeAttributes) {
  let offset;
  const creative = createCreativeLinear(creativeAttributes);

  creative.duration = parserUtils.parseDuration(
    parserUtils.parseNodeText(
      parserUtils.childByName(creativeElement, 'Duration')
    )
  );
  const skipOffset = creativeElement.getAttribute('skipoffset');

  if (typeof skipOffset === 'undefined' || skipOffset === null) {
    creative.skipDelay = null;
  } else if (
    skipOffset.charAt(skipOffset.length - 1) === '%' &&
    creative.duration !== -1
  ) {
    const percent = parseInt(skipOffset, 10);
    creative.skipDelay = creative.duration * (percent / 100);
  } else {
    creative.skipDelay = parserUtils.parseDuration(skipOffset);
  }

  const videoClicksElement = parserUtils.childByName(
    creativeElement,
    'VideoClicks'
  );
  if (videoClicksElement) {
    const videoClickThroughElement = parserUtils.childByName(
      videoClicksElement,
      'ClickThrough'
    );
    if (videoClickThroughElement) {
      creative.videoClickThroughURLTemplate = {
        id: videoClickThroughElement.getAttribute('id') || null,
        url: parserUtils.parseNodeText(videoClickThroughElement)
      };
    } else {
      creative.videoClickThroughURLTemplate = null;
    }

    parserUtils
      .childrenByName(videoClicksElement, 'ClickTracking')
      .forEach(clickTrackingElement => {
        creative.videoClickTrackingURLTemplates.push({
          id: clickTrackingElement.getAttribute('id') || null,
          url: parserUtils.parseNodeText(clickTrackingElement)
        });
      });

    parserUtils
      .childrenByName(videoClicksElement, 'CustomClick')
      .forEach(customClickElement => {
        creative.videoCustomClickURLTemplates.push({
          id: customClickElement.getAttribute('id') || null,
          url: parserUtils.parseNodeText(customClickElement)
        });
      });
  }

  const adParamsElement = parserUtils.childByName(
    creativeElement,
    'AdParameters'
  );
  if (adParamsElement) {
    creative.adParameters = parserUtils.parseNodeText(adParamsElement);
  }

  parserUtils
    .childrenByName(creativeElement, 'TrackingEvents')
    .forEach(trackingEventsElement => {
      parserUtils
        .childrenByName(trackingEventsElement, 'Tracking')
        .forEach(trackingElement => {
          let eventName = trackingElement.getAttribute('event');
          const trackingURLTemplate = parserUtils.parseNodeText(
            trackingElement
          );
          if (eventName && trackingURLTemplate) {
            if (eventName === 'progress') {
              offset = trackingElement.getAttribute('offset');
              if (!offset) {
                return;
              }
              if (offset.charAt(offset.length - 1) === '%') {
                eventName = `progress-${offset}`;
              } else {
                eventName = `progress-${Math.round(
                  parserUtils.parseDuration(offset)
                )}`;
              }
            }

            if (!Array.isArray(creative.trackingEvents[eventName])) {
              creative.trackingEvents[eventName] = [];
            }
            creative.trackingEvents[eventName].push(trackingURLTemplate);
          }
        });
    });

  parserUtils
    .childrenByName(creativeElement, 'MediaFiles')
    .forEach(mediaFilesElement => {
      parserUtils
        .childrenByName(mediaFilesElement, 'MediaFile')
        .forEach(mediaFileElement => {
          creative.mediaFiles.push(parseMediaFile(mediaFileElement));
        });

      const interactiveCreativeElement = parserUtils.childByName(
        mediaFilesElement,
        'InteractiveCreativeFile'
      );
      if (interactiveCreativeElement) {
        creative.interactiveCreativeFile = parseInteractiveCreativeFile(
          interactiveCreativeElement
        );
      }

      const closedCaptionElements = parserUtils.childByName(
        mediaFilesElement,
        'ClosedCaptionFiles'
      );
      if (closedCaptionElements) {
        parserUtils
          .childrenByName(closedCaptionElements, 'ClosedCaptionFile')
          .forEach(closedCaptionElement => {
            const closedCaptionFile = createClosedCaptionFile(
              parserUtils.parseAttributes(closedCaptionElement)
            );
            closedCaptionFile.fileURL = parserUtils.parseNodeText(
              closedCaptionElement
            );

            creative.closedCaptionFiles.push(closedCaptionFile);
          });
      }

      const mezzanineElement = parserUtils.childByName(
        mediaFilesElement,
        'Mezzanine'
      );
      const requiredAttributes = getRequiredAttributes(mezzanineElement, [
        'delivery',
        'type',
        'width',
        'height'
      ]);

      if (requiredAttributes) {
        const mezzanine = createMezzanine();

        mezzanine.id = mezzanineElement.getAttribute('id');
        mezzanine.fileURL = parserUtils.parseNodeText(mezzanineElement);
        mezzanine.delivery = requiredAttributes.delivery;
        mezzanine.codec = mezzanineElement.getAttribute('codec');
        mezzanine.type = requiredAttributes.type;
        mezzanine.width = parseInt(requiredAttributes.width, 10);
        mezzanine.height = parseInt(requiredAttributes.height, 10);
        mezzanine.fileSize = parseInt(
          mezzanineElement.getAttribute('fileSize'),
          10
        );
        mezzanine.mediaType =
          mezzanineElement.getAttribute('mediaType') || '2D';

        creative.mezzanine = mezzanine;
      }
    });

  const iconsElement = parserUtils.childByName(creativeElement, 'Icons');
  if (iconsElement) {
    parserUtils.childrenByName(iconsElement, 'Icon').forEach(iconElement => {
      creative.icons.push(parseIcon(iconElement));
    });
  }

  return creative;
}

/**
 * Parses the MediaFile element from VAST.
 * @param  {Object} mediaFileElement - The VAST MediaFile element.
 * @return {Object} - Parsed mediaFile object.
 */
function parseMediaFile(mediaFileElement) {
  const mediaFile = createMediaFile();
  mediaFile.id = mediaFileElement.getAttribute('id');
  mediaFile.fileURL = parserUtils.parseNodeText(mediaFileElement);
  mediaFile.deliveryType = mediaFileElement.getAttribute('delivery');
  mediaFile.codec = mediaFileElement.getAttribute('codec');
  mediaFile.mimeType = mediaFileElement.getAttribute('type');
  mediaFile.mediaType = mediaFileElement.getAttribute('mediaType') || '2D';
  mediaFile.apiFramework = mediaFileElement.getAttribute('apiFramework');
  mediaFile.fileSize = parseInt(mediaFileElement.getAttribute('fileSize') || 0);
  mediaFile.bitrate = parseInt(mediaFileElement.getAttribute('bitrate') || 0);
  mediaFile.minBitrate = parseInt(
    mediaFileElement.getAttribute('minBitrate') || 0
  );
  mediaFile.maxBitrate = parseInt(
    mediaFileElement.getAttribute('maxBitrate') || 0
  );
  mediaFile.width = parseInt(mediaFileElement.getAttribute('width') || 0);
  mediaFile.height = parseInt(mediaFileElement.getAttribute('height') || 0);

  const scalable = mediaFileElement.getAttribute('scalable');
  if (scalable && typeof scalable === 'string') {
    mediaFile.scalable = parserUtils.parseBoolean(scalable);
  }

  const maintainAspectRatio = mediaFileElement.getAttribute(
    'maintainAspectRatio'
  );
  if (maintainAspectRatio && typeof maintainAspectRatio === 'string') {
    mediaFile.maintainAspectRatio = parserUtils.parseBoolean(
      maintainAspectRatio
    );
  }
  return mediaFile;
}

/**
 * Parses the InteractiveCreativeFile element from VAST MediaFiles node.
 * @param  {Object} interactiveCreativeElement - The VAST InteractiveCreativeFile element.
 * @return {Object} - Parsed interactiveCreativeFile object.
 */
function parseInteractiveCreativeFile(interactiveCreativeElement) {
  const interactiveCreativeFile = createInteractiveCreativeFile(
    parserUtils.parseAttributes(interactiveCreativeElement)
  );
  interactiveCreativeFile.fileURL = parserUtils.parseNodeText(
    interactiveCreativeElement
  );
  return interactiveCreativeFile;
}

/**
 * Parses the Icon element from VAST.
 * @param  {Object} iconElement - The VAST Icon element.
 * @return {Object} - Parsed icon object.
 */
function parseIcon(iconElement) {
  const icon = createIcon(iconElement);
  icon.program = iconElement.getAttribute('program');
  icon.height = parseInt(iconElement.getAttribute('height') || 0);
  icon.width = parseInt(iconElement.getAttribute('width') || 0);
  icon.xPosition = parseXPosition(iconElement.getAttribute('xPosition'));
  icon.yPosition = parseYPosition(iconElement.getAttribute('yPosition'));
  icon.apiFramework = iconElement.getAttribute('apiFramework');
  icon.pxratio = iconElement.getAttribute('pxratio') || '1';
  icon.offset = parserUtils.parseDuration(iconElement.getAttribute('offset'));
  icon.duration = parserUtils.parseDuration(
    iconElement.getAttribute('duration')
  );

  parserUtils
    .childrenByName(iconElement, 'HTMLResource')
    .forEach(htmlElement => {
      icon.type = htmlElement.getAttribute('creativeType') || 'text/html';
      icon.htmlResource = parserUtils.parseNodeText(htmlElement);
    });

  parserUtils
    .childrenByName(iconElement, 'IFrameResource')
    .forEach(iframeElement => {
      icon.type = iframeElement.getAttribute('creativeType') || 0;
      icon.iframeResource = parserUtils.parseNodeText(iframeElement);
    });

  parserUtils
    .childrenByName(iconElement, 'StaticResource')
    .forEach(staticElement => {
      icon.type = staticElement.getAttribute('creativeType') || 0;
      icon.staticResource = parserUtils.parseNodeText(staticElement);
    });

  const iconClicksElement = parserUtils.childByName(iconElement, 'IconClicks');
  if (iconClicksElement) {
    icon.iconClickThroughURLTemplate = parserUtils.parseNodeText(
      parserUtils.childByName(iconClicksElement, 'IconClickThrough')
    );
    parserUtils
      .childrenByName(iconClicksElement, 'IconClickTracking')
      .forEach(iconClickTrackingElement => {
        icon.iconClickTrackingURLTemplates.push({
          id: iconClickTrackingElement.getAttribute('id') || null,
          url: parserUtils.parseNodeText(iconClickTrackingElement)
        });
      });
  }

  icon.iconViewTrackingURLTemplate = parserUtils.parseNodeText(
    parserUtils.childByName(iconElement, 'IconViewTracking')
  );
  return icon;
}

/**
 * Parses the MediaFile element from VAST.
 * @param  {Object} mediaFileElement - The VAST MediaFile element.
 * @return {Object} - Parsed mediaFile object.
 */
function parseMediaFile(mediaFileElement) {
  const mediaFile = createMediaFile();
  mediaFile.id = mediaFileElement.getAttribute('id');
  mediaFile.fileURL = parserUtils.parseNodeText(mediaFileElement);
  mediaFile.deliveryType = mediaFileElement.getAttribute('delivery');
  mediaFile.codec = mediaFileElement.getAttribute('codec');
  mediaFile.mimeType = mediaFileElement.getAttribute('type');
  mediaFile.mediaType = mediaFileElement.getAttribute('mediaType') || '2D';
  mediaFile.apiFramework = mediaFileElement.getAttribute('apiFramework');
  mediaFile.fileSize = parseInt(mediaFileElement.getAttribute('fileSize') || 0);
  mediaFile.bitrate = parseInt(mediaFileElement.getAttribute('bitrate') || 0);
  mediaFile.minBitrate = parseInt(
    mediaFileElement.getAttribute('minBitrate') || 0
  );
  mediaFile.maxBitrate = parseInt(
    mediaFileElement.getAttribute('maxBitrate') || 0
  );
  mediaFile.width = parseInt(mediaFileElement.getAttribute('width') || 0);
  mediaFile.height = parseInt(mediaFileElement.getAttribute('height') || 0);

  let scalable = mediaFileElement.getAttribute('scalable');
  if (scalable && typeof scalable === 'string') {
    scalable = scalable.toLowerCase();
    if (scalable === 'true') {
      mediaFile.scalable = true;
    } else if (scalable === 'false') {
      mediaFile.scalable = false;
    }
  }

  let maintainAspectRatio = mediaFileElement.getAttribute(
    'maintainAspectRatio'
  );
  if (maintainAspectRatio && typeof maintainAspectRatio === 'string') {
    maintainAspectRatio = maintainAspectRatio.toLowerCase();
    if (maintainAspectRatio === 'true') {
      mediaFile.maintainAspectRatio = true;
    } else if (maintainAspectRatio === 'false') {
      mediaFile.maintainAspectRatio = false;
    }
  }
  return mediaFile;
}

/**
 * Parses the InteractiveCreativeFile element from VAST.
 * @param  {Object} interactiveCreativeElement - The VAST InteractiveCreativeFile element.
 * @return {Object} - Parsed interactiveCreativeFile object.
 */
function parseInteractiveCreativeFile(interactiveCreativeElement) {
  const interactiveCreativeFile = createInteractiveCreativeFile();
  interactiveCreativeFile.type = interactiveCreativeElement.getAttribute(
    'type'
  );
  interactiveCreativeFile.apiFramework = interactiveCreativeElement.getAttribute(
    'apiFramework'
  );
  let variableDuration = interactiveCreativeElement.getAttribute(
    'variableDuration'
  );
  if (variableDuration && typeof variableDuration === 'string') {
    variableDuration = variableDuration.toLowerCase();
    if (variableDuration === 'true') {
      interactiveCreativeFile.variableDuration = true;
    } else if (variableDuration === 'false') {
      interactiveCreativeFile.variableDuration = false;
    }
  }
  interactiveCreativeFile.fileURL = parserUtils.parseNodeText(
    interactiveCreativeElement
  );
  return interactiveCreativeFile;
}

/**
 * Parses an horizontal position into a String ('left' or 'right') or into a Number.
 * @param  {String} xPosition - The x position to parse.
 * @return {String|Number}
 */
function parseXPosition(xPosition) {
  if (['left', 'right'].indexOf(xPosition) !== -1) {
    return xPosition;
  }

  return parseInt(xPosition || 0);
}

/**
 * Parses an vertical position into a String ('top' or 'bottom') or into a Number.
 * @param  {String} yPosition - The x position to parse.
 * @return {String|Number}
 */
function parseYPosition(yPosition) {
  if (['top', 'bottom'].indexOf(yPosition) !== -1) {
    return yPosition;
  }

  return parseInt(yPosition || 0);
}

/**
 * Getting required attributes from element
 * @param  {Object} element - DOM element
 * @param  {Array} attributes - list of attributes
 * @return {Object|null} null if a least one element not present
 */
function getRequiredAttributes(element, attributes) {
  const values = {};
  let error = false;

  attributes.forEach(name => {
    if (!element || !element.getAttribute(name)) {
      error = true;
    } else {
      values[name] = element.getAttribute(name);
    }
  });

  return error ? null : values;
}
<commit_msg>[parser] Refactored the icon parsing to a separate method<commit_after>import { createCreativeLinear } from '../creative/creative_linear';
import { createClosedCaptionFile } from '../closed_caption_file';
import { createIcon } from '../icon';
import { createInteractiveCreativeFile } from '../interactive_creative_file';
import { createMediaFile } from '../media_file';
import { createMezzanine } from '../mezzanine';
import { parserUtils } from './parser_utils';

/**
 * This module provides methods to parse a VAST Linear Element.
 */

/**
 * Parses a Linear element.
 * @param  {Object} creativeElement - The VAST Linear element to parse.
 * @param  {any} creativeAttributes - The attributes of the Linear (optional).
 * @return {Object} creative - The creativeLinear object.
 */
export function parseCreativeLinear(creativeElement, creativeAttributes) {
  let offset;
  const creative = createCreativeLinear(creativeAttributes);

  creative.duration = parserUtils.parseDuration(
    parserUtils.parseNodeText(
      parserUtils.childByName(creativeElement, 'Duration')
    )
  );
  const skipOffset = creativeElement.getAttribute('skipoffset');

  if (typeof skipOffset === 'undefined' || skipOffset === null) {
    creative.skipDelay = null;
  } else if (
    skipOffset.charAt(skipOffset.length - 1) === '%' &&
    creative.duration !== -1
  ) {
    const percent = parseInt(skipOffset, 10);
    creative.skipDelay = creative.duration * (percent / 100);
  } else {
    creative.skipDelay = parserUtils.parseDuration(skipOffset);
  }

  const videoClicksElement = parserUtils.childByName(
    creativeElement,
    'VideoClicks'
  );
  if (videoClicksElement) {
    const videoClickThroughElement = parserUtils.childByName(
      videoClicksElement,
      'ClickThrough'
    );
    if (videoClickThroughElement) {
      creative.videoClickThroughURLTemplate = {
        id: videoClickThroughElement.getAttribute('id') || null,
        url: parserUtils.parseNodeText(videoClickThroughElement)
      };
    } else {
      creative.videoClickThroughURLTemplate = null;
    }

    parserUtils
      .childrenByName(videoClicksElement, 'ClickTracking')
      .forEach(clickTrackingElement => {
        creative.videoClickTrackingURLTemplates.push({
          id: clickTrackingElement.getAttribute('id') || null,
          url: parserUtils.parseNodeText(clickTrackingElement)
        });
      });

    parserUtils
      .childrenByName(videoClicksElement, 'CustomClick')
      .forEach(customClickElement => {
        creative.videoCustomClickURLTemplates.push({
          id: customClickElement.getAttribute('id') || null,
          url: parserUtils.parseNodeText(customClickElement)
        });
      });
  }

  const adParamsElement = parserUtils.childByName(
    creativeElement,
    'AdParameters'
  );
  if (adParamsElement) {
    creative.adParameters = parserUtils.parseNodeText(adParamsElement);
  }

  parserUtils
    .childrenByName(creativeElement, 'TrackingEvents')
    .forEach(trackingEventsElement => {
      parserUtils
        .childrenByName(trackingEventsElement, 'Tracking')
        .forEach(trackingElement => {
          let eventName = trackingElement.getAttribute('event');
          const trackingURLTemplate = parserUtils.parseNodeText(
            trackingElement
          );
          if (eventName && trackingURLTemplate) {
            if (eventName === 'progress') {
              offset = trackingElement.getAttribute('offset');
              if (!offset) {
                return;
              }
              if (offset.charAt(offset.length - 1) === '%') {
                eventName = `progress-${offset}`;
              } else {
                eventName = `progress-${Math.round(
                  parserUtils.parseDuration(offset)
                )}`;
              }
            }

            if (!Array.isArray(creative.trackingEvents[eventName])) {
              creative.trackingEvents[eventName] = [];
            }
            creative.trackingEvents[eventName].push(trackingURLTemplate);
          }
        });
    });

  parserUtils
    .childrenByName(creativeElement, 'MediaFiles')
    .forEach(mediaFilesElement => {
      parserUtils
        .childrenByName(mediaFilesElement, 'MediaFile')
        .forEach(mediaFileElement => {
          creative.mediaFiles.push(parseMediaFile(mediaFileElement));
        });

      const interactiveCreativeElement = parserUtils.childByName(
        mediaFilesElement,
        'InteractiveCreativeFile'
      );
      if (interactiveCreativeElement) {
        creative.interactiveCreativeFile = parseInteractiveCreativeFile(
          interactiveCreativeElement
        );
      }

      const closedCaptionElements = parserUtils.childByName(
        mediaFilesElement,
        'ClosedCaptionFiles'
      );
      if (closedCaptionElements) {
        parserUtils
          .childrenByName(closedCaptionElements, 'ClosedCaptionFile')
          .forEach(closedCaptionElement => {
            const closedCaptionFile = createClosedCaptionFile(
              parserUtils.parseAttributes(closedCaptionElement)
            );
            closedCaptionFile.fileURL = parserUtils.parseNodeText(
              closedCaptionElement
            );

            creative.closedCaptionFiles.push(closedCaptionFile);
          });
      }

      const mezzanineElement = parserUtils.childByName(
        mediaFilesElement,
        'Mezzanine'
      );
      const requiredAttributes = getRequiredAttributes(mezzanineElement, [
        'delivery',
        'type',
        'width',
        'height'
      ]);

      if (requiredAttributes) {
        const mezzanine = createMezzanine();

        mezzanine.id = mezzanineElement.getAttribute('id');
        mezzanine.fileURL = parserUtils.parseNodeText(mezzanineElement);
        mezzanine.delivery = requiredAttributes.delivery;
        mezzanine.codec = mezzanineElement.getAttribute('codec');
        mezzanine.type = requiredAttributes.type;
        mezzanine.width = parseInt(requiredAttributes.width, 10);
        mezzanine.height = parseInt(requiredAttributes.height, 10);
        mezzanine.fileSize = parseInt(
          mezzanineElement.getAttribute('fileSize'),
          10
        );
        mezzanine.mediaType =
          mezzanineElement.getAttribute('mediaType') || '2D';

        creative.mezzanine = mezzanine;
      }
    });

  const iconsElement = parserUtils.childByName(creativeElement, 'Icons');
  if (iconsElement) {
    parserUtils.childrenByName(iconsElement, 'Icon').forEach(iconElement => {
      creative.icons.push(parseIcon(iconElement));
    });
  }

  return creative;
}

/**
 * Parses the MediaFile element from VAST.
 * @param  {Object} mediaFileElement - The VAST MediaFile element.
 * @return {Object} - Parsed mediaFile object.
 */
function parseMediaFile(mediaFileElement) {
  const mediaFile = createMediaFile();
  mediaFile.id = mediaFileElement.getAttribute('id');
  mediaFile.fileURL = parserUtils.parseNodeText(mediaFileElement);
  mediaFile.deliveryType = mediaFileElement.getAttribute('delivery');
  mediaFile.codec = mediaFileElement.getAttribute('codec');
  mediaFile.mimeType = mediaFileElement.getAttribute('type');
  mediaFile.mediaType = mediaFileElement.getAttribute('mediaType') || '2D';
  mediaFile.apiFramework = mediaFileElement.getAttribute('apiFramework');
  mediaFile.fileSize = parseInt(mediaFileElement.getAttribute('fileSize') || 0);
  mediaFile.bitrate = parseInt(mediaFileElement.getAttribute('bitrate') || 0);
  mediaFile.minBitrate = parseInt(
    mediaFileElement.getAttribute('minBitrate') || 0
  );
  mediaFile.maxBitrate = parseInt(
    mediaFileElement.getAttribute('maxBitrate') || 0
  );
  mediaFile.width = parseInt(mediaFileElement.getAttribute('width') || 0);
  mediaFile.height = parseInt(mediaFileElement.getAttribute('height') || 0);

  const scalable = mediaFileElement.getAttribute('scalable');
  if (scalable && typeof scalable === 'string') {
    mediaFile.scalable = parserUtils.parseBoolean(scalable);
  }

  const maintainAspectRatio = mediaFileElement.getAttribute(
    'maintainAspectRatio'
  );
  if (maintainAspectRatio && typeof maintainAspectRatio === 'string') {
    mediaFile.maintainAspectRatio = parserUtils.parseBoolean(
      maintainAspectRatio
    );
  }
  return mediaFile;
}

/**
 * Parses the InteractiveCreativeFile element from VAST MediaFiles node.
 * @param  {Object} interactiveCreativeElement - The VAST InteractiveCreativeFile element.
 * @return {Object} - Parsed interactiveCreativeFile object.
 */
function parseInteractiveCreativeFile(interactiveCreativeElement) {
  const interactiveCreativeFile = createInteractiveCreativeFile(
    parserUtils.parseAttributes(interactiveCreativeElement)
  );
  interactiveCreativeFile.fileURL = parserUtils.parseNodeText(
    interactiveCreativeElement
  );
  return interactiveCreativeFile;
}

/**
 * Parses the Icon element from VAST.
 * @param  {Object} iconElement - The VAST Icon element.
 * @return {Object} - Parsed icon object.
 */
function parseIcon(iconElement) {
  const icon = createIcon(iconElement);
  icon.program = iconElement.getAttribute('program');
  icon.height = parseInt(iconElement.getAttribute('height') || 0);
  icon.width = parseInt(iconElement.getAttribute('width') || 0);
  icon.xPosition = parseXPosition(iconElement.getAttribute('xPosition'));
  icon.yPosition = parseYPosition(iconElement.getAttribute('yPosition'));
  icon.apiFramework = iconElement.getAttribute('apiFramework');
  icon.pxratio = iconElement.getAttribute('pxratio') || '1';
  icon.offset = parserUtils.parseDuration(iconElement.getAttribute('offset'));
  icon.duration = parserUtils.parseDuration(
    iconElement.getAttribute('duration')
  );

  parserUtils
    .childrenByName(iconElement, 'HTMLResource')
    .forEach(htmlElement => {
      icon.type = htmlElement.getAttribute('creativeType') || 'text/html';
      icon.htmlResource = parserUtils.parseNodeText(htmlElement);
    });

  parserUtils
    .childrenByName(iconElement, 'IFrameResource')
    .forEach(iframeElement => {
      icon.type = iframeElement.getAttribute('creativeType') || 0;
      icon.iframeResource = parserUtils.parseNodeText(iframeElement);
    });

  parserUtils
    .childrenByName(iconElement, 'StaticResource')
    .forEach(staticElement => {
      icon.type = staticElement.getAttribute('creativeType') || 0;
      icon.staticResource = parserUtils.parseNodeText(staticElement);
    });

  const iconClicksElement = parserUtils.childByName(iconElement, 'IconClicks');
  if (iconClicksElement) {
    icon.iconClickThroughURLTemplate = parserUtils.parseNodeText(
      parserUtils.childByName(iconClicksElement, 'IconClickThrough')
    );
    parserUtils
      .childrenByName(iconClicksElement, 'IconClickTracking')
      .forEach(iconClickTrackingElement => {
        icon.iconClickTrackingURLTemplates.push({
          id: iconClickTrackingElement.getAttribute('id') || null,
          url: parserUtils.parseNodeText(iconClickTrackingElement)
        });
      });
  }

  icon.iconViewTrackingURLTemplate = parserUtils.parseNodeText(
    parserUtils.childByName(iconElement, 'IconViewTracking')
  );
  return icon;
}

/**
 * Parses an horizontal position into a String ('left' or 'right') or into a Number.
 * @param  {String} xPosition - The x position to parse.
 * @return {String|Number}
 */
function parseXPosition(xPosition) {
  if (['left', 'right'].indexOf(xPosition) !== -1) {
    return xPosition;
  }

  return parseInt(xPosition || 0);
}

/**
 * Parses an vertical position into a String ('top' or 'bottom') or into a Number.
 * @param  {String} yPosition - The x position to parse.
 * @return {String|Number}
 */
function parseYPosition(yPosition) {
  if (['top', 'bottom'].indexOf(yPosition) !== -1) {
    return yPosition;
  }

  return parseInt(yPosition || 0);
}

/**
 * Getting required attributes from element
 * @param  {Object} element - DOM element
 * @param  {Array} attributes - list of attributes
 * @return {Object|null} null if a least one element not present
 */
function getRequiredAttributes(element, attributes) {
  const values = {};
  let error = false;

  attributes.forEach(name => {
    if (!element || !element.getAttribute(name)) {
      error = true;
    } else {
      values[name] = element.getAttribute(name);
    }
  });

  return error ? null : values;
}
<|endoftext|>


<commit_before>var Middleware = require('../middleware/middleware');
var Parameters = require('./parameters');
var Need       = require('./need');
var Socket     = require('./socket');

module.exports = function(router, route, io) {

	router[route.method](route.path, route.middlewares, function(req, res, next) {

		if(!Parameters.check(req, route)) {
			res.json({satus: 400, message: 'Bad request : missing parameters'});
			return false;
		}

		if(!Need.check(req, res)) {
			res.status(400).send({status: 400, message: "You don't have permissions."});
			return false;
		}

		// Add route infos in the request
		req.routeInfos = route;

		// Launch the right method from the right controller
		if(route.controller) {
			route.controller[route.action](req, res, function(req, res) {
				// After route
				Middleware.afterRoute(req, res);
				// Emit socket
				Socket.emit(req, io);
			});
		}else {
			route.action(req, res, function(req, res) {
				// After route
				Middleware.afterRoute(req, res);
				// Emit socket
				Socket.emit(req, io);
			});
		}

	});
}

<commit_msg>update socket in routing<commit_after>var Middleware = require('../middleware/middleware');
var Parameters = require('./parameters');
var Need       = require('./need');
var Socket     = require('./socket');

module.exports = function(router, route, io) {

	router[route.method](route.path, route.middlewares, function(req, res, next) {

		if(!Parameters.check(req, route)) {
			res.json({satus: 400, message: 'Bad request : missing parameters'});
			return false;
		}

		if(!Need.check(req, res)) {
			res.status(400).send({status: 400, message: "You don't have permissions."});
			return false;
		}

		// Add route infos in the request
		req.routeInfos = route;

		// Launch the right method from the right controller
		if(route.controller) {
			route.controller[route.action](req, res, function(req, res) {
				// After route
				Middleware.afterRoute(req, res);
				// Emit socket
				if(route.socket)
					Socket.emit(req, io);
			});
		}else {
			route.action(req, res, function(req, res) {
				// After route
				Middleware.afterRoute(req, res);
				// Emit socket
				if(route.socket)
					Socket.emit(req, io);
			});
		}

	});
}

<|endoftext|>


<commit_before>'use strict';
import db from './';
import config from '../config';

const DEBUG = config.debug;

export function dropProjects () {
  DEBUG && console.log('Dropping table: projects');
  return db.schema.dropTableIfExists('projects');
}

export function dropProjectsFiles () {
  DEBUG && console.log('Dropping table: projects_files');
  return db.schema.dropTableIfExists('projects_files');
}

export function dropProjectsAA () {
  DEBUG && console.log('Dropping table: projects_aa');
  return db.schema.dropTableIfExists('projects_aa');
}

export function dropScenarios () {
  DEBUG && console.log('Dropping table: scenarios');
  return db.schema.dropTableIfExists('scenarios');
}

export function dropScenariosFiles () {
  DEBUG && console.log('Dropping table: scenarios_files');
  return db.schema.dropTableIfExists('scenarios_files');
}

export function dropScenariosSettings () {
  DEBUG && console.log('Dropping table: scenarios_settings');
  return db.schema.dropTableIfExists('scenarios_settings');
}

export function dropOperations () {
  DEBUG && console.log('Dropping table: operations');
  return db.schema.dropTableIfExists('operations');
}

export function dropOperationsLogs () {
  DEBUG && console.log('Dropping table: operations_logs');
  return db.schema.dropTableIfExists('operations_logs');
}

export function dropResults () {
  DEBUG && console.log('Dropping table: results');
  return db.schema.dropTableIfExists('results');
}

export function dropResultsPoi () {
  DEBUG && console.log('Dropping table: results_poi');
  return db.schema.dropTableIfExists('results_poi');
}

export function dropProjectsOrigins () {
  DEBUG && console.log('Dropping table: projects_origins');
  return db.schema.dropTableIfExists('projects_origins');
}

export function dropProjectsOriginsIndicators () {
  DEBUG && console.log('Dropping table: projects_origins_indicators');
  return db.schema.dropTableIfExists('projects_origins_indicators');
}

export function createProjectsTable () {
  DEBUG && console.log('Creating table: projects');
  return db.schema.createTable('projects', table => {
    table.increments('id').primary();
    table.string('name');
    table.text('description');
    table.string('status');
    table.json('bbox');
    table.timestamps();

    table.unique('name');
  });
}

export function createProjectsFilesTable () {
  DEBUG && console.log('Creating table: projects_files');
  return db.schema.createTable('projects_files', table => {
    table.increments('id').primary();
    table.string('name');
    table.string('type');
    table.string('path');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.json('data');
    table.timestamps();
  });
}

export function createProjectsAATable () {
  DEBUG && console.log('Creating table: projects_aa');
  return db.schema.createTable('projects_aa', table => {
    table.increments('id').primary();
    table.string('name');
    table.string('type');
    table.json('geometry');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
  });
}

export function createScenariosTable () {
  DEBUG && console.log('Creating table: scenarios');
  return db.schema.createTable('scenarios', table => {
    table.increments('id').primary();
    table.string('name');
    table.text('description');
    table.string('status');
    table.boolean('master').defaultTo(false);
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.json('admin_areas');
    table.timestamps();

    table.unique(['project_id', 'name']);
  });
}

export function createScenariosFilesTable () {
  DEBUG && console.log('Creating table: scenarios_files');
  return db.schema.createTable('scenarios_files', table => {
    table.increments('id').primary();
    table.string('name');
    table.string('type');
    table.string('subtype');
    table.string('path');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.timestamps();
  });
}

export function createScenariosSettingsTable () {
  DEBUG && console.log('Creating table: scenarios_settings');
  return db.schema.createTable('scenarios_settings', table => {
    table.string('key');
    table.string('value');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.timestamps();
    table.primary(['scenario_id', 'key']);
  });
}

export function createOperationsTable () {
  DEBUG && console.log('Creating table: operations');
  return db.schema.createTable('operations', table => {
    table.increments('id').primary();
    table.string('name');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.string('status');
    table.timestamps();
  });
}

export function createOperationsLogsTable () {
  DEBUG && console.log('Creating table: operations_logs');
  return db.schema.createTable('operations_logs', table => {
    table.increments('id').primary();
    table.integer('operation_id').unsigned();
    table.foreign('operation_id')
      .references('operations.id')
      .onDelete('CASCADE');
    table.string('code');
    table.json('data');
    table.timestamp('created_at').defaultTo(db.fn.now());
  });
}

export function createResultsTable () {
  DEBUG && console.log('Creating table: results');
  return db.schema.createTable('results', table => {
    table.increments('id').primary();
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.integer('origin_id').unsigned();
    table.foreign('origin_id')
      .references('projects_origins.id')
      .onDelete('CASCADE');
    table.integer('project_aa_id').unsigned();
    table.foreign('project_aa_id')
      .references('projects_aa.id')
      .onDelete('CASCADE');
  });
}

export function createResultsPoiTable () {
  DEBUG && console.log('Creating table: results_poi');
  return db.schema.createTable('results_poi', table => {
    table.increments('id').primary();
    table.integer('result_id').unsigned();
    table.foreign('result_id')
      .references('results.id')
      .onDelete('CASCADE');
    table.string('type');
    table.integer('time');
  });
}

export function createProjectsOriginsTable () {
  DEBUG && console.log('Creating table: projects_origins');
  return db.schema.createTable('projects_origins', table => {
    table.increments('id').primary();
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.string('name');
    table.json('coordinates');
  });
}

export function createProjectsOriginsIndicatorsTable () {
  DEBUG && console.log('Creating table: projects_origins_indicators');
  return db.schema.createTable('projects_origins_indicators', table => {
    table.increments('id').primary();
    table.integer('origin_id').unsigned();
    table.foreign('origin_id')
      .references('projects_origins.id')
      .onDelete('CASCADE');
    table.string('key');
    table.string('label');
    table.integer('value');
  });
}

export function setupStructure () {
  return dropScenariosFiles()
  .then(() => dropProjectsFiles())
  .then(() => dropResultsPoi())
  .then(() => dropResults())
  .then(() => dropProjectsAA())
  .then(() => dropOperationsLogs())
  .then(() => dropOperations())
  .then(() => dropScenariosSettings())
  .then(() => dropScenarios())
  .then(() => dropProjectsOriginsIndicators())
  .then(() => dropProjectsOrigins())
  .then(() => dropProjects())
  .then(() => createProjectsTable())
  .then(() => createProjectsAATable())
  .then(() => createScenariosTable())
  .then(() => createScenariosSettingsTable())
  .then(() => createOperationsTable())
  .then(() => createOperationsLogsTable())
  .then(() => createProjectsFilesTable())
  .then(() => createScenariosFilesTable())
  .then(() => createProjectsOriginsTable())
  .then(() => createProjectsOriginsIndicatorsTable())
  .then(() => createResultsTable())
  .then(() => createResultsPoiTable());
}
<commit_msg>Change settings value field to text<commit_after>'use strict';
import db from './';
import config from '../config';

const DEBUG = config.debug;

export function dropProjects () {
  DEBUG && console.log('Dropping table: projects');
  return db.schema.dropTableIfExists('projects');
}

export function dropProjectsFiles () {
  DEBUG && console.log('Dropping table: projects_files');
  return db.schema.dropTableIfExists('projects_files');
}

export function dropProjectsAA () {
  DEBUG && console.log('Dropping table: projects_aa');
  return db.schema.dropTableIfExists('projects_aa');
}

export function dropScenarios () {
  DEBUG && console.log('Dropping table: scenarios');
  return db.schema.dropTableIfExists('scenarios');
}

export function dropScenariosFiles () {
  DEBUG && console.log('Dropping table: scenarios_files');
  return db.schema.dropTableIfExists('scenarios_files');
}

export function dropScenariosSettings () {
  DEBUG && console.log('Dropping table: scenarios_settings');
  return db.schema.dropTableIfExists('scenarios_settings');
}

export function dropOperations () {
  DEBUG && console.log('Dropping table: operations');
  return db.schema.dropTableIfExists('operations');
}

export function dropOperationsLogs () {
  DEBUG && console.log('Dropping table: operations_logs');
  return db.schema.dropTableIfExists('operations_logs');
}

export function dropResults () {
  DEBUG && console.log('Dropping table: results');
  return db.schema.dropTableIfExists('results');
}

export function dropResultsPoi () {
  DEBUG && console.log('Dropping table: results_poi');
  return db.schema.dropTableIfExists('results_poi');
}

export function dropProjectsOrigins () {
  DEBUG && console.log('Dropping table: projects_origins');
  return db.schema.dropTableIfExists('projects_origins');
}

export function dropProjectsOriginsIndicators () {
  DEBUG && console.log('Dropping table: projects_origins_indicators');
  return db.schema.dropTableIfExists('projects_origins_indicators');
}

export function createProjectsTable () {
  DEBUG && console.log('Creating table: projects');
  return db.schema.createTable('projects', table => {
    table.increments('id').primary();
    table.string('name');
    table.text('description');
    table.string('status');
    table.json('bbox');
    table.timestamps();

    table.unique('name');
  });
}

export function createProjectsFilesTable () {
  DEBUG && console.log('Creating table: projects_files');
  return db.schema.createTable('projects_files', table => {
    table.increments('id').primary();
    table.string('name');
    table.string('type');
    table.string('path');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.json('data');
    table.timestamps();
  });
}

export function createProjectsAATable () {
  DEBUG && console.log('Creating table: projects_aa');
  return db.schema.createTable('projects_aa', table => {
    table.increments('id').primary();
    table.string('name');
    table.string('type');
    table.json('geometry');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
  });
}

export function createScenariosTable () {
  DEBUG && console.log('Creating table: scenarios');
  return db.schema.createTable('scenarios', table => {
    table.increments('id').primary();
    table.string('name');
    table.text('description');
    table.string('status');
    table.boolean('master').defaultTo(false);
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.json('admin_areas');
    table.timestamps();

    table.unique(['project_id', 'name']);
  });
}

export function createScenariosFilesTable () {
  DEBUG && console.log('Creating table: scenarios_files');
  return db.schema.createTable('scenarios_files', table => {
    table.increments('id').primary();
    table.string('name');
    table.string('type');
    table.string('subtype');
    table.string('path');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.timestamps();
  });
}

export function createScenariosSettingsTable () {
  DEBUG && console.log('Creating table: scenarios_settings');
  return db.schema.createTable('scenarios_settings', table => {
    table.string('key');
    table.text('value');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.timestamps();
    table.primary(['scenario_id', 'key']);
  });
}

export function createOperationsTable () {
  DEBUG && console.log('Creating table: operations');
  return db.schema.createTable('operations', table => {
    table.increments('id').primary();
    table.string('name');
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.string('status');
    table.timestamps();
  });
}

export function createOperationsLogsTable () {
  DEBUG && console.log('Creating table: operations_logs');
  return db.schema.createTable('operations_logs', table => {
    table.increments('id').primary();
    table.integer('operation_id').unsigned();
    table.foreign('operation_id')
      .references('operations.id')
      .onDelete('CASCADE');
    table.string('code');
    table.json('data');
    table.timestamp('created_at').defaultTo(db.fn.now());
  });
}

export function createResultsTable () {
  DEBUG && console.log('Creating table: results');
  return db.schema.createTable('results', table => {
    table.increments('id').primary();
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.integer('scenario_id').unsigned();
    table.foreign('scenario_id')
      .references('scenarios.id')
      .onDelete('CASCADE');
    table.integer('origin_id').unsigned();
    table.foreign('origin_id')
      .references('projects_origins.id')
      .onDelete('CASCADE');
    table.integer('project_aa_id').unsigned();
    table.foreign('project_aa_id')
      .references('projects_aa.id')
      .onDelete('CASCADE');
  });
}

export function createResultsPoiTable () {
  DEBUG && console.log('Creating table: results_poi');
  return db.schema.createTable('results_poi', table => {
    table.increments('id').primary();
    table.integer('result_id').unsigned();
    table.foreign('result_id')
      .references('results.id')
      .onDelete('CASCADE');
    table.string('type');
    table.integer('time');
  });
}

export function createProjectsOriginsTable () {
  DEBUG && console.log('Creating table: projects_origins');
  return db.schema.createTable('projects_origins', table => {
    table.increments('id').primary();
    table.integer('project_id').unsigned();
    table.foreign('project_id')
      .references('projects.id')
      .onDelete('CASCADE');
    table.string('name');
    table.json('coordinates');
  });
}

export function createProjectsOriginsIndicatorsTable () {
  DEBUG && console.log('Creating table: projects_origins_indicators');
  return db.schema.createTable('projects_origins_indicators', table => {
    table.increments('id').primary();
    table.integer('origin_id').unsigned();
    table.foreign('origin_id')
      .references('projects_origins.id')
      .onDelete('CASCADE');
    table.string('key');
    table.string('label');
    table.integer('value');
  });
}

export function setupStructure () {
  return dropScenariosFiles()
  .then(() => dropProjectsFiles())
  .then(() => dropResultsPoi())
  .then(() => dropResults())
  .then(() => dropProjectsAA())
  .then(() => dropOperationsLogs())
  .then(() => dropOperations())
  .then(() => dropScenariosSettings())
  .then(() => dropScenarios())
  .then(() => dropProjectsOriginsIndicators())
  .then(() => dropProjectsOrigins())
  .then(() => dropProjects())
  .then(() => createProjectsTable())
  .then(() => createProjectsAATable())
  .then(() => createScenariosTable())
  .then(() => createScenariosSettingsTable())
  .then(() => createOperationsTable())
  .then(() => createOperationsLogsTable())
  .then(() => createProjectsFilesTable())
  .then(() => createScenariosFilesTable())
  .then(() => createProjectsOriginsTable())
  .then(() => createProjectsOriginsIndicatorsTable())
  .then(() => createResultsTable())
  .then(() => createResultsPoiTable());
}
<|endoftext|>


<commit_before>// LaVue
// Web server relaying serial data and exposing it on a web page
// JRY
// 04.12.2015

//generic vars
var COMPort='COM14';
var PORT=80;
var MAINFILE='index.html';
var BTLoggerName='LaVue Logger';

//os
var os=require('os');
var LinuxOS=true;
LinuxOS=(os.platform()==='win32')?false:true;

//file system
var fs=require('fs');

//express
var express=require("express");
var app=express();

//websocket and server
var wsConnected=false;
var http = require('http');
var io=require('socket.io');
io=io.listen(app.listen(PORT,function(){
	console.log("WebServer: ON ("+PORT+")")
}));

app.get('/',function(req,res){
	console.log(' Received request for '+req.url );
    fs.readFile(MAINFILE,function (err, data){
		if(err)throw err;
        res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
        res.write(data);
        res.end();
    });
});

function CS_AckHandler(data){
	//console.log('client WS message: '+data);
}

io.on('connection',function(socket){
	console.log("WebSocket: ON");
	wsConnected=true;
	socket.on('Ack', CS_AckHandler);
	socket.on('disconnect', function() {
		console.log("Websocket disconnected");
		socket.removeAllListeners('Ack');
		wsConnected=false;
  });
});
io.set('transports',  ['websocket', 'polling']);

//Serial port
var SPBT=require('./mod/SPBT');

function BTCOMcb(d){
	var data="";
	d.forEach(function(elem){data+=String.fromCharCode(elem)});
	console.log("data from COM :"+data);
	if(wsConnected)
		io.emit('FakeData',data);
	else
		console.log('no websocket to send to');
}

function Start(x){
	if(x==='OK')
	{

	}
	else{
		console.log("Error : "+x);
	}
}

SPBT.SPBT(COMPort,115200,function(x){console.log("User callback , data received :"+x);},Start);
console.log("Bluetooth: ON");

process.on('SIGINT', function () {
  console.log('CTRL-C: exiting...');
  SPBT.Terminate(function(){console.log("OK. bye bye");process.exit(0);});
});<commit_msg>- Server ready to receive application data through SPP connection :-)<commit_after>// LaVue
// Web server relaying serial data and exposing it on a web page
// JRY
// 04.12.2015

//generic vars
var COMPort='COM14';
var PORT=80;
var MAINFILE='index.html';
var BTLoggerName='LaVue Logger';

//os
var os=require('os');
var LinuxOS=true;
LinuxOS=(os.platform()==='win32')?false:true;

//file system
var fs=require('fs');

//express
var express=require("express");
var app=express();

//websocket and server
var wsConnected=false;
var http = require('http');
var io=require('socket.io');
io=io.listen(app.listen(PORT,function(){
	console.log("WebServer: ON ("+PORT+")")
}));

app.get('/',function(req,res){
	console.log(' Received request for '+req.url );
    fs.readFile(MAINFILE,function (err, data){
		if(err)throw err;
        res.writeHead(200, {'Content-Type': 'text/html','Content-Length':data.length});
        res.write(data);
        res.end();
    });
});

function CS_AckHandler(data){
	//console.log('client WS message: '+data);
}

io.on('connection',function(socket){
	console.log("WebSocket: ON");
	wsConnected=true;
	socket.on('Ack', CS_AckHandler);
	socket.on('disconnect', function() {
		console.log("Websocket disconnected");
		socket.removeAllListeners('Ack');
		wsConnected=false;
  });
});
io.set('transports',  ['websocket', 'polling']);

//Serial port
var SPBT=require('./mod/SPBT');

function BTCOMcb(d){
	var data="";
	d.forEach(function(elem){data+=String.fromCharCode(elem)});
	console.log("data from COM :"+data);
	if(wsConnected)
		io.emit('FakeData',data);
	else
		console.log('no websocket to send to');
}

function Start(x){
	if(x==='OK')
	{
		if(wsConnected)
			io.emit('FakeData',"Bluetooth SPP Connection UP and running !! :-)");
		else
			console.log('no websocket to send to');
	}
	else{
		console.log("Error : "+x);
	}
}

SPBT.SPBT(COMPort,115200,BTCOMcb,Start);
console.log("Bluetooth: ON");

process.on('SIGINT', function () {
  console.log('CTRL-C: exiting...');
  SPBT.Terminate(function(){console.log("OK. bye bye");process.exit(0);});
});<|endoftext|>


<commit_before>var cities = {
    "vancouver" : {
        "lat" : 49.25,
        "lng" : -123.13,
    },
};

// Map location
var LAT = cities["vancouver"]["lat"];
var LNG = cities["vancouver"]["lng"];

// Global variables
var mapEvents  = [];
var mapVenues  = [];
var mapMarkers = [];

$(document).ready(function() {

    // Enable tooltips.
    $("[data-toggle='tooltip']").tooltip();

    // -------------------------------------------------------------------------
    // SEARCH FORM
    // -------------------------------------------------------------------------

    // Convert the dropdown menu into a select element.
    $("#by-menu-dropdown li a").click(function() {
        $("#by-menu-label").html($(this).html());
        $("#by-menu-select option").prop("selected", false)
                                   .filter("[value=" + $(this).attr("value") + "]")
                                   .prop("selected", true);
    });

    // Animate the search field.
    $("#search-field").focus(function() {
        $(this).attr("default-width", $(this).css("width"));
        $(this).animate({ width : 150 }, "fast");
    }).blur(function() {
        var defaultWidth = $(this).attr("default-width");
        $(this).animate({ width : defaultWidth }, "fast");
    });

    // Submit the search form on enter.
    $("#search-field").keydown(function(e) {
        if (e.keyCode == 13) {
            e.preventDefault();
            $("#search-form").submit();
        }
    });

    // -------------------------------------------------------------------------
    // MAP
    // -------------------------------------------------------------------------

    // Check to prevent error message.
    if ($("#map").is(":visible")) {

        // Adjust zoom levels here.
        var INITIAL_ZOOM = 12;
        var CLICKED_ZOOM = 14;

        // Initialize the map.
        var map;
        var infoWindow = new google.maps.InfoWindow({
            pixelOffset : new google.maps.Size(0, -25),
        });
        google.maps.event.addDomListener(window, "load", initMap(LAT, LNG));

        /**
         * Plots the map every time the page is loaded.
         */
        function initMap(lat, lng) {
            var mapSettings = {
                zoom      : INITIAL_ZOOM,
                center    : new google.maps.LatLng(lat, lng),
                mapTypeId : google.maps.MapTypeId.ROADMAP,
            };
            map = new google.maps.Map(document.getElementById("map"), mapSettings);

            getEvents();
            getVenues();
            createMarkers();

            mapEvents  = [];
            mapVenues  = [];
            mapMarkers = [];
        }

        /**
         * Puts markers on the map.
         */
        function createMarkers() {
            for (var i = 0; i < mapEvents.length; ++i) {
                var lat = mapVenues[i][1];
                var lng = mapVenues[i][2];

                var content = "
" + mapEvents[i]["date"];
                if (mapEvents[i]["time"]) {
                    content += " " + mapEvents[i]["time"];
                }
                if (mapEvents[i]["venue"]) {
                    content += " at " + mapEvents[i]["venue"];
                }
                content += "
";
                if (mapEvents[i]["type"] === "Festival") {
                    content += "
";
                } else {
                    content += "
";
                }
                content += mapEvents[i]["lineup"][0] + "
";
                for (var j = 1; j < mapEvents[i]["lineup"].length; ++j) {
                    content += "
" + mapEvents[i]["lineup"][j] + "
";
                }

                var thisMarker = new google.maps.Marker({
                    map       : map,
                    content   : content,
                    position  : new google.maps.LatLng(lat, lng),
                    animation : google.maps.Animation.DROP,
                    eventId   : mapEvents[i]["id"],
                });
                mapMarkers.push(thisMarker);
                setClickEvent(thisMarker);
            }
        }

        /**
         * Sets what happens when a marker is clicked on.
         */
        function setClickEvent(marker) {
            google.maps.event.addListener(marker, "click", function() {
                var markerContent = marker.content.replace("'", "'");
                var markerPosition = marker.getPosition();

                // Zoom the map in to the marker.
                map.setCenter(markerPosition);
                map.setZoom(CLICKED_ZOOM);
                initInfoWindow(markerContent, markerPosition);

                // Scroll to and highlight corresponding row on the table.
                var eventRow = "#" + marker["eventId"];
                $("tbody").scrollTo(eventRow, { duration : 500 });
                $(eventRow).effect("highlight", { color : "#ff467a" }, 2000);

                // document.getElementById("id_lat").value = markerPosition.lat();
                // document.getElementById("id_lng").value = markerPosition.lng();
                // document.getElementById("id_event_name").value = markerTitle;
            });
        }

        /**
         * Checks whether or not infoWindow is enabled.
         */
        function isInfoWindowOpen(infoWindow) {
            var map = infoWindow.getMap();
            return (map !== null && typeof map !== "undefined");
        }

        /**
         * Enables infoWindow when a marker is clicked on and closes any
         * currently open ones.
         */
        function initInfoWindow(markerContent, markerPosition) {
            if (isInfoWindowOpen(infoWindow)) {
                infoWindow.close();
            }
            infoWindow.setContent(markerContent);
            infoWindow.setPosition(markerPosition);
            infoWindow.open(map);
        }
    }
});
<commit_msg>Trigger marker click when table row is clicked<commit_after>var cities = {
    "vancouver" : {
        "lat" : 49.25,
        "lng" : -123.13,
    },
};

// Map location
var LAT = cities["vancouver"]["lat"];
var LNG = cities["vancouver"]["lng"];

// Global variables
var mapEvents  = [];
var mapVenues  = [];
var mapMarkers = [];

$(document).ready(function() {

    // Enable tooltips.
    $("[data-toggle='tooltip']").tooltip();

    $("tr").click(function() {
        var eventId = $(this).attr("id");
        var marker = mapMarkers.reduce(function(a, b) {
            return (a["eventId"] === eventId && a) || (b["eventId"] === eventId && b);
        });
        new google.maps.event.trigger(marker, "click");
    });

    // -------------------------------------------------------------------------
    // SEARCH FORM
    // -------------------------------------------------------------------------

    // Convert the dropdown menu into a select element.
    $("#by-menu-dropdown li a").click(function() {
        $("#by-menu-label").html($(this).html());
        $("#by-menu-select option").prop("selected", false)
                                   .filter("[value=" + $(this).attr("value") + "]")
                                   .prop("selected", true);
    });

    // Animate the search field.
    $("#search-field").focus(function() {
        $(this).attr("default-width", $(this).css("width"));
        $(this).animate({ width : 150 }, "fast");
    }).blur(function() {
        var defaultWidth = $(this).attr("default-width");
        $(this).animate({ width : defaultWidth }, "fast");
    });

    // Submit the search form on enter.
    $("#search-field").keydown(function(e) {
        if (e.keyCode == 13) {
            e.preventDefault();
            $("#search-form").submit();
        }
    });

    // -------------------------------------------------------------------------
    // MAP
    // -------------------------------------------------------------------------

    // Check to prevent error message.
    if ($("#map").is(":visible")) {

        // Adjust zoom levels here.
        var INITIAL_ZOOM = 12;
        var CLICKED_ZOOM = 14;

        // Initialize the map.
        var map;
        var infoWindow = new google.maps.InfoWindow({
            pixelOffset : new google.maps.Size(0, -25),
        });
        google.maps.event.addDomListener(window, "load", initMap(LAT, LNG));

        /**
         * Plots the map every time the page is loaded.
         */
        function initMap(lat, lng) {
            var mapSettings = {
                zoom      : INITIAL_ZOOM,
                center    : new google.maps.LatLng(lat, lng),
                mapTypeId : google.maps.MapTypeId.ROADMAP,
            };
            map = new google.maps.Map(document.getElementById("map"), mapSettings);

            mapEvents  = [];
            mapVenues  = [];
            mapMarkers = [];

            getEvents();
            getVenues();
            createMarkers();
        }

        /**
         * Puts markers on the map.
         */
        function createMarkers() {
            for (var i = 0; i < mapEvents.length; ++i) {
                var lat = mapVenues[i][1];
                var lng = mapVenues[i][2];

                var content = "
" + mapEvents[i]["date"];
                if (mapEvents[i]["time"]) {
                    content += " " + mapEvents[i]["time"];
                }
                if (mapEvents[i]["venue"]) {
                    content += " at " + mapEvents[i]["venue"];
                }
                content += "
";
                if (mapEvents[i]["type"] === "Festival") {
                    content += "
";
                } else {
                    content += "
";
                }
                content += mapEvents[i]["lineup"][0] + "
";
                for (var j = 1; j < mapEvents[i]["lineup"].length; ++j) {
                    content += "
" + mapEvents[i]["lineup"][j] + "
";
                }

                var thisMarker = new google.maps.Marker({
                    map       : map,
                    content   : content,
                    position  : new google.maps.LatLng(lat, lng),
                    animation : google.maps.Animation.DROP,
                    eventId   : mapEvents[i]["id"],
                });
                mapMarkers.push(thisMarker);
                setClickEvent(thisMarker);
            }
        }

        /**
         * Sets what happens when a marker is clicked on.
         */
        function setClickEvent(marker) {
            google.maps.event.addListener(marker, "click", function() {
                var markerContent = marker.content.replace("'", "'");
                var markerPosition = marker.getPosition();

                // Zoom the map in to the marker.
                map.setCenter(markerPosition);
                map.setZoom(CLICKED_ZOOM);
                initInfoWindow(markerContent, markerPosition);

                // Scroll to and highlight corresponding row on the table.
                var eventRow = "#" + marker["eventId"];
                $("tbody").scrollTo(eventRow, { duration : 500 });
                $(eventRow).effect("highlight", { color : "#ff467a" }, 2000);

                // document.getElementById("id_lat").value = markerPosition.lat();
                // document.getElementById("id_lng").value = markerPosition.lng();
                // document.getElementById("id_event_name").value = markerTitle;
            });
        }

        /**
         * Checks whether or not infoWindow is enabled.
         */
        function isInfoWindowOpen(infoWindow) {
            var map = infoWindow.getMap();
            return (map !== null && typeof map !== "undefined");
        }

        /**
         * Enables infoWindow when a marker is clicked on and closes any
         * currently open ones.
         */
        function initInfoWindow(markerContent, markerPosition) {
            if (isInfoWindowOpen(infoWindow)) {
                infoWindow.close();
            }
            infoWindow.setContent(markerContent);
            infoWindow.setPosition(markerPosition);
            infoWindow.open(map);
        }
    }
});
<|endoftext|>


<commit_before><commit_msg>fix applab tests<commit_after><|endoftext|>


<commit_before>const setLocal = (k,v) =>
  localStorage.setItem(`__flint.state.${k}`, JSON.stringify(v))
const getLocal = (k,d) =>
  JSON.parse(localStorage.getItem(`__flint.state.${k}`)) || d

const round = Math.round

let highlighter

function positionHighlight(node) {
  const bounds = node.getBoundingClientRect()
  highlighter.setAttribute('style', `
    top: ${round(bounds.top)}px;
    left: ${round(bounds.left)}px;
    width: ${round(bounds.right - bounds.left)}px;
    height: ${round(bounds.bottom - bounds.top)}px;
  `)
}

function hideHighlight() {
  highlighter.setAttribute('style', '')
}

function findPath(node) {
  if (!node || !node.getAttribute) return null
  const flintid = node.__flintID
  if (!flintid) return findPath(node.parentNode)
  positionHighlight(node)
  return flintid
}

view Inspector {
  view.pause()

  let hudActive = false
  let showTemp = false
  let temp = null
  let views = []
  let clickOff
  let keys = {}
  let lastTarget = null
  let hoverOff

  on.mount(() => {
    if (highlighter) return
    highlighter = document.createElement('div')
    highlighter.className = "_flintHighlighter"
    document.body.appendChild(highlighter)
  })

  function inspect(path) {
    if (!path || path === temp) return
    _Flint.isInspecting = true
    temp = path
    view.update()
  }

  function mouseMove({ target }) {
    lastTarget = target
    if (hudActive) inspect(findPath(lastTarget))
  }

  function removeTemp() {
    temp = null
    view.update()
  }

  function close(path, e) {
    if (e) { e.stopPropagation() }

    views = views.filter(_id => _id != path)
    setTimeout(view.update, 100)
  }

  function hideHudTemporarily() {
    hideInspect()
    const offAgain = on.mousemove(() => {
      offAgain()
      if (hudActive)
        showInspect()
    })
  }

  function glue(e) {
    const path = findPath(e.target)

    hideHudTemporarily()

    /* toggle whether views has path */
    if (views.indexOf(path) > -1) {
      close(path)
    }
    else {
      views.push(path)
      view.update()
    }
    return false
  }

  const hover = () => {
    hoverOff = on.mousemove(window, mouseMove)
  }

  function showInspect() {
    inspect(findPath(lastTarget))
    hudActive = true
    hover()
    clickOff = on.click(window, glue)
  }

  function hideInspect(turnOffHud) {
    _Flint.isInspecting = false
    hideHighlight()
    hoverOff()
    clickOff()
    removeTemp()

    if (turnOffHud)
      hudActive = false
  }

  function writeBack(path, data) {
    const name  = data[1][0]
    const current = _Flint.getCache[path][name]
    let value = data[1][1]

    if (typeof current == 'number') {
      value = +value
    }

    _Flint.setCache(path, name, value)
    _Flint.inspectorRefreshing = path
    _Flint.getInitialStates[path]()
    _Flint.viewsAtPath[path].forceUpdate()
    _Flint.inspectorRefreshing = null
    view.update()
  }

  hover()

  const isAlt = cb => e => e.keyIdentifier === 'Alt' && cb()

  on.keydown(window, isAlt(showInspect))
  on.keyup(window, isAlt(hideInspect.bind(null, true)))

  <views>
    <Inspector.View
      repeat={views}
      path={_}
      writeBack={writeBack}
      onClose={e => close(_, e)}
    />
    <Inspector.View
      if={temp}
      path={temp}
      animate={true}
      writeBack={writeBack}
      onClose={removeTemp}
    />
  </views>

  $ = {
    position: 'fixed',
    top: 0, right: 0,
    padding: 2
  }
}<commit_msg>esc to close inspector<commit_after>const setLocal = (k,v) =>
  localStorage.setItem(`__flint.state.${k}`, JSON.stringify(v))
const getLocal = (k,d) =>
  JSON.parse(localStorage.getItem(`__flint.state.${k}`)) || d

const round = Math.round

let highlighter

function positionHighlight(node) {
  const bounds = node.getBoundingClientRect()
  highlighter.setAttribute('style', `
    top: ${round(bounds.top)}px;
    left: ${round(bounds.left)}px;
    width: ${round(bounds.right - bounds.left)}px;
    height: ${round(bounds.bottom - bounds.top)}px;
  `)
}

function hideHighlight() {
  highlighter.setAttribute('style', '')
}

function findPath(node) {
  if (!node || !node.getAttribute) return null
  const flintid = node.__flintID
  if (!flintid) return findPath(node.parentNode)
  positionHighlight(node)
  return flintid
}

view Inspector {
  view.pause()

  let hudActive = false
  let showTemp = false
  let temp = null
  let views = []
  let clickOff
  let keys = {}
  let lastTarget = null
  let hoverOff

  on.mount(() => {
    if (highlighter) return
    highlighter = document.createElement('div')
    highlighter.className = "_flintHighlighter"
    document.body.appendChild(highlighter)
  })

  function inspect(path) {
    if (!path || path === temp) return
    _Flint.isInspecting = true
    temp = path
    view.update()
  }

  function hideLast() {
    if (!views.length) return
    views.pop()
    view.update()
  }

  function mouseMove({ target }) {
    lastTarget = target
    if (hudActive) inspect(findPath(lastTarget))
  }

  function removeTemp() {
    temp = null
    view.update()
  }

  function close(path, e) {
    if (e) { e.stopPropagation() }

    views = views.filter(_id => _id != path)
    setTimeout(view.update, 100)
  }

  function hideHudTemporarily() {
    hideInspect()
    const offAgain = on.mousemove(() => {
      offAgain()
      if (hudActive)
        showInspect()
    })
  }

  function glue(e) {
    const path = findPath(e.target)

    hideHudTemporarily()

    /* toggle whether views has path */
    if (views.indexOf(path) > -1) {
      close(path)
    }
    else {
      views.push(path)
      view.update()
    }
    return false
  }

  const hover = () => {
    hoverOff = on.mousemove(window, mouseMove)
  }

  function showInspect() {
    inspect(findPath(lastTarget))
    hudActive = true
    hover()
    clickOff = on.click(window, glue)
  }

  function hideInspect(turnOffHud) {
    _Flint.isInspecting = false
    hideHighlight()
    hoverOff()
    clickOff()
    removeTemp()

    if (turnOffHud)
      hudActive = false
  }

  function writeBack(path, data) {
    const name  = data[1][0]
    const current = _Flint.getCache[path][name]
    let value = data[1][1]

    if (typeof current == 'number') {
      value = +value
    }

    _Flint.setCache(path, name, value)
    _Flint.inspectorRefreshing = path
    _Flint.getInitialStates[path]()
    _Flint.viewsAtPath[path].forceUpdate()
    _Flint.inspectorRefreshing = null
    view.update()
  }

  hover()

  const isAlt = cb => e => e.keyIdentifier === 'Alt' && cb()
  const isEsc = cb => e => e.keyCode === 27 && cb()

  on.keydown(window, isAlt(showInspect))
  on.keyup(window, isAlt(hideInspect.bind(null, true)))
  on.keyup(window, isEsc(hideLast))

  <views>
    <Inspector.View
      repeat={views}
      path={_}
      writeBack={writeBack}
      onClose={e => close(_, e)}
    />
    <Inspector.View
      if={temp}
      path={temp}
      animate={true}
      writeBack={writeBack}
      onClose={removeTemp}
    />
  </views>

  $ = {
    position: 'fixed',
    top: 0, right: 0,
    padding: 2
  }
}<|endoftext|>


<commit_before>/* Copyright (C) 2013 Hans Larsen */
'use strict';

/**
 * AngularJS Loader.
 * Automatically load scripts based on angular.module() calls (ala AMD).
 *******************************************************************************
 * In my experience this is faster than RequireJS in our case (around 60 scripts
 * both including utility functions and angular modules).
 *******************************************************************************
 * Documentation: see http://github.com/hansl/angularjs-loader
 */
(function() {

// Get our script tag.
var allScriptTags = document.getElementsByTagName('script');
var angularJsLoaderScriptTag = allScriptTags[allScriptTags.length - 1];

var mainModulePathArg = getAttribute('app');
var rootPathArg = getAttribute('root', '');
var timeoutArg = getAttribute('timeout', 30000);

var angularModuleOriginalFn = angular.module;

var config = {};

var defaultTransformPathList = [
    function isAbsoluteUrl(path) {
        return path.search(/^(https?:)?\/\/.+/) == 0 ? null : path;
    },
    function prependRootPath(path) {
        return (rootPathArg ? rootPathArg + '/' : '') + path;
    },
    function appendJsExtension(path) {
        return path.search(/\.js$/) == -1 ? path + '.js' : path;
    }
];

function getConfig(name, defaultValue) {
    if (name in config) {
        return config[name];
    }
    else {
        return defaultValue;
    }
}

/**
 * A really simple promise object.
 */
function deferred() {
    var success = [];
    var error = [];
    var pending = true;
    var value;
    var reason;

    var deferred = {
        pending: function() {
            return pending;
        },
        resolve: function(val) {
            if (!pending) {
                throw new Error('Deferred resolved twice.');
            }
            value = val;
            for (var i = 0; i < success.length; i++) {
                success[i](val);
            }
            pending = false;
        },
        reject: function(val) {
            reason = val;
            for (var i = 0; i < error.length; i++) {
                error[i](val);
            }
            pending = false;
        },
        promise: {
            then: function(fn, errFn) {
                if (!pending) {
                    if (value) {
                        fn && fn(value);
                    }
                    else {
                        errFn && errFn(reason);
                    }
                }
                else {
                    if (fn) {
                        success.push(fn);
                    }
                    if (errFn) {
                        error.push(errFn);
                    }
                }
                return deferred.promise;
            },
            error: function(fn) {
                return deferred.then(null, fn);
            }
        }
    };

    return deferred;
}

function transformPath(path, transformList) {
    var original = path;
    for (var i = 0, fn; fn = transformList[i]; i++) {
        var old = path;
        path = fn(path, original);
        if (path === null) {
            return old;
        }
    }
    return path;
}

function pathFromModuleName(name) {
    var map = getConfig('path', {});
    if (map[name] === null) return null;

    var transformList = getConfig('pathTransform', [])
                                .concat(defaultTransformPathList);
    var path = transformPath(name in map ? map[name] : name, transformList);

    return path;
}

var lockCount = 0;
var isBootstrapped = false;
var locks = {};

function locked(name) {
    return name in locks;
}

function lock(name) {
    if (name in locks) {
        throw new Error('Path "' + name + '" is being loaded twice.')
        return false;
    }
    locks[name] = false;
    lockCount++;
}

function unlock(name) {
    if (!(name in locks)) {
        throw new Error('Path "' + name + '" was not loaded.');
    }
    if (locks[name]) {
        throw new Error('Path "' + name + '" was loaded twice.');
    }
    locks[name] = true;

    if (--lockCount == 0) {
        if (isBootstrapped) {
            throw new Error('App already bootstrapped.');
        }

        isBootstrapped = true;

        window.setTimeout(function() {
            // We check again in case the file introduced new dependencies.
            angular.bootstrap(document, [mainModulePathArg]);
        }, 0);
    }
}

function insertScript(path) {
    var d = deferred();

    var newScriptTag = document.createElement('script');
    newScriptTag.type = "text/javascript";
    newScriptTag.src = path;

    newScriptTag.addEventListener('load', function(ev) { d.resolve(ev); });
    newScriptTag.addEventListener('error', function(ev) { d.reject(ev); });
    window.setTimeout(function() {
        if (d.pending()) {
            d.reject(new Error('Script did not load in time.'));
        }
    }, timeoutArg);
    document.head.appendChild(newScriptTag);

    return d.promise;
}

function getAttribute(name, defaultValue) {
    if (angularJsLoaderScriptTag.attributes[name]) {
        return angularJsLoaderScriptTag.attributes[name].value;
    }
    else if (typeof defaultValue == 'undefined') {
        throw new Error('Need to specify an "' + name
                      + '" attribute to angularjs-loader.');
    }
    return defaultValue;
}

function loaderFn(path, options) {
    if (options === undefined) {
        options = {};
    }
    if (typeof path == 'string') {
        path = [path];
    }

    var isSequence = options.sequence || false;
    var returnDefer = deferred();
    if (path.length == 0) {
        returnDefer.resolve();
        return returnDefer;
    }

    var checkerFn = options.checker || function() { return true; };
    var checkerMap = {};

    if (typeof checkerFn == 'object') {
        checkerMap = checkerFn;
    }
    else {
        for (var i = 0; i < path.length; i++) {
            checkerMap[path[i]] = checkerFn;
        }
    }

    angular.extend(checkerMap, getConfig('checker', {}));

    // Replace all the values in checkerMap by a function. If it's already
    // do nothing. If it's a string or an array adhere to the documentation.
    for (var script in checkerMap) {
        var fn = checkerMap[script];
        if (typeof fn == 'function') {
            continue;
        }

        if (typeof fn == 'string') {
            fn = [fn];
        }

        checkerMap[script] = function() {
            for (var i = 0; i < fn.length; i++) {
                if (typeof window[fn[i]] == 'undefined') {
                    return false;
                }
            }
            return true;
        };
    }

    var timeout = options.timeout || timeoutArg;

    function unlockOnChecker(name, lock) {
        if (!(name in checkerMap)) {
            unlock(lock);
            return;
        }
        else {
            if (checkerMap[name](name)) {
                unlock(lock);
                return;
            }

            var start = +new Date();
            var interval = window.setInterval(function() {
                if (checkerMap[name](name)) {
                    // For every interval created we will clear it by design.
                    window.clearInterval(interval);
                    unlock(lock);
                }
                else if (new Date() - start >= timeout) {
                    window.clearInterval(interval);
                    throw new Error('Timed out loading "' + path + '".');
                }
            }, 10);
        }
    }

    function recursiveLoader(d) {
        if (path.length) {
            var name = path.shift();
            var p = pathFromModuleName(name);
            if (!p || locked(p)) {
                return recursiveLoader(d);
            }

            lock(p);
            d = insertScript(p).then(function() {
                recursiveLoader(d);
                unlockOnChecker(name, p);
            }, function(reason) {
                throw new Error(reason);
            });
        }
        else {
            if (!d) {
                returnDefer.resolve();
                return;
            }

            d.then(function(val) {
                returnDefer.resolve(val);
            }, function(val) {
                returnDefer.reject(val);
            });
        }
    }

    if (isSequence) {
        recursiveLoader();
    }
    else {
        var counter = 0;
        while (path.length > 0) {
            var name = path.shift();
            var p = pathFromModuleName(name);
            if (!p || locked(p)) {
                continue;
            }

            counter++;
            lock(p);

            var successFn = function(name, p, val) {
                if ((--counter) == 0) returnDefer.resolve(val);
                unlockOnChecker(name, p);
            };

            insertScript(p).then(successFn.bind(0, name, p), function(err) {
                returnDefer.reject(err);
            });
        }
        if (counter == 0) {
            returnDefer.resolve();
        }
    }

    return returnDefer.promise;
}

angular.extend(loaderFn, {
    config: function(cfg) {
        angular.extend(config, cfg);
        return loaderFn;
    },
    lock: function(name) {
        lock('ext:' + name);
    },
    unlock: function(name) {
        unlock('ext:' + name);
    }
});

angular.extend(angular, {
    loader: loaderFn,
    requires: function(name, checkerFn) {
        if (typeof name == 'object') {
            for (var n in name) {
                angular.requires(n, name[n]);
            }
        }
        else {
            angular.loader(name, {
                checker: checkerFn
            });
        }

        return angular;
    },
    module: function() {
        var name = arguments[0];
        var requires = arguments[1];
        var ret = angularModuleOriginalFn.apply(angular, arguments);

        // If module() was called with only 1 argument, it was to get the module
        // and not create a new one.
        if (arguments.length == 1) {
            return ret;
        }

        if (requires instanceof Array) {
            for (var i = 0; i < requires.length; i++) {
                var path = pathFromModuleName(requires[i]);
                if (!path || locked(requires[i])) {
                    continue;
                }

                lock(requires[i]);
                insertScript(path);
            }
        }

        var path = pathFromModuleName(name);
        if (path) {
            unlock(name);
        }
        return ret;
    }
});

// Load the first module.
lock(mainModulePathArg);
angular.loader(mainModulePathArg);

})();<commit_msg>Throw error when AngularJS is missing.<commit_after>/* Copyright (C) 2013 Hans Larsen */
'use strict';

/**
 * AngularJS Loader.
 * Automatically load scripts based on angular.module() calls (ala AMD).
 *******************************************************************************
 * In my experience this is faster than RequireJS in our case (around 60 scripts
 * both including utility functions and angular modules).
 *******************************************************************************
 * Documentation: see http://github.com/hansl/angularjs-loader
 */
(function() {

// Make sure AngularJS is loaded first.
if (!window['angular']) {
    throw new Error('AngularJS-loader requires Angular to be loaded first.');
}

// Get our script tag.
var allScriptTags = document.getElementsByTagName('script');
var angularJsLoaderScriptTag = allScriptTags[allScriptTags.length - 1];

var mainModulePathArg = getAttribute('app');
var rootPathArg = getAttribute('root', '');
var timeoutArg = getAttribute('timeout', 30000);

var angularModuleOriginalFn = angular.module;

var config = {};

var defaultTransformPathList = [
    function isAbsoluteUrl(path) {
        return path.search(/^(https?:)?\/\/.+/) == 0 ? null : path;
    },
    function prependRootPath(path) {
        return (rootPathArg ? rootPathArg + '/' : '') + path;
    },
    function appendJsExtension(path) {
        return path.search(/\.js$/) == -1 ? path + '.js' : path;
    }
];

function getConfig(name, defaultValue) {
    if (name in config) {
        return config[name];
    }
    else {
        return defaultValue;
    }
}

/**
 * A really simple promise object.
 */
function deferred() {
    var success = [];
    var error = [];
    var pending = true;
    var value;
    var reason;

    var deferred = {
        pending: function() {
            return pending;
        },
        resolve: function(val) {
            if (!pending) {
                throw new Error('Deferred resolved twice.');
            }
            value = val;
            for (var i = 0; i < success.length; i++) {
                success[i](val);
            }
            pending = false;
        },
        reject: function(val) {
            reason = val;
            for (var i = 0; i < error.length; i++) {
                error[i](val);
            }
            pending = false;
        },
        promise: {
            then: function(fn, errFn) {
                if (!pending) {
                    if (value) {
                        fn && fn(value);
                    }
                    else {
                        errFn && errFn(reason);
                    }
                }
                else {
                    if (fn) {
                        success.push(fn);
                    }
                    if (errFn) {
                        error.push(errFn);
                    }
                }
                return deferred.promise;
            },
            error: function(fn) {
                return deferred.then(null, fn);
            }
        }
    };

    return deferred;
}

function transformPath(path, transformList) {
    var original = path;
    for (var i = 0, fn; fn = transformList[i]; i++) {
        var old = path;
        path = fn(path, original);
        if (path === null) {
            return old;
        }
    }
    return path;
}

function pathFromModuleName(name) {
    var map = getConfig('path', {});
    if (map[name] === null) return null;

    var transformList = getConfig('pathTransform', [])
                                .concat(defaultTransformPathList);
    var path = transformPath(name in map ? map[name] : name, transformList);

    return path;
}

var lockCount = 0;
var isBootstrapped = false;
var locks = {};

function locked(name) {
    return name in locks;
}

function lock(name) {
    if (name in locks) {
        throw new Error('Path "' + name + '" is being loaded twice.')
        return false;
    }
    locks[name] = false;
    lockCount++;
}

function unlock(name) {
    if (!(name in locks)) {
        throw new Error('Path "' + name + '" was not loaded.');
    }
    if (locks[name]) {
        throw new Error('Path "' + name + '" was loaded twice.');
    }
    locks[name] = true;

    if (--lockCount == 0) {
        if (isBootstrapped) {
            throw new Error('App already bootstrapped.');
        }

        isBootstrapped = true;

        window.setTimeout(function() {
            // We check again in case the file introduced new dependencies.
            angular.bootstrap(document, [mainModulePathArg]);
        }, 0);
    }
}

function insertScript(path) {
    var d = deferred();

    var newScriptTag = document.createElement('script');
    newScriptTag.type = "text/javascript";
    newScriptTag.src = path;

    newScriptTag.addEventListener('load', function(ev) { d.resolve(ev); });
    newScriptTag.addEventListener('error', function(ev) { d.reject(ev); });
    window.setTimeout(function() {
        if (d.pending()) {
            d.reject(new Error('Script did not load in time.'));
        }
    }, timeoutArg);
    document.head.appendChild(newScriptTag);

    return d.promise;
}

function getAttribute(name, defaultValue) {
    if (angularJsLoaderScriptTag.attributes[name]) {
        return angularJsLoaderScriptTag.attributes[name].value;
    }
    else if (typeof defaultValue == 'undefined') {
        throw new Error('Need to specify an "' + name
                      + '" attribute to angularjs-loader.');
    }
    return defaultValue;
}

function loaderFn(path, options) {
    if (options === undefined) {
        options = {};
    }
    if (typeof path == 'string') {
        path = [path];
    }

    var isSequence = options.sequence || false;
    var returnDefer = deferred();
    if (path.length == 0) {
        returnDefer.resolve();
        return returnDefer;
    }

    var checkerFn = options.checker || function() { return true; };
    var checkerMap = {};

    if (typeof checkerFn == 'object') {
        checkerMap = checkerFn;
    }
    else {
        for (var i = 0; i < path.length; i++) {
            checkerMap[path[i]] = checkerFn;
        }
    }

    angular.extend(checkerMap, getConfig('checker', {}));

    // Replace all the values in checkerMap by a function. If it's already
    // do nothing. If it's a string or an array adhere to the documentation.
    for (var script in checkerMap) {
        var fn = checkerMap[script];
        if (typeof fn == 'function') {
            continue;
        }

        if (typeof fn == 'string') {
            fn = [fn];
        }

        checkerMap[script] = function() {
            for (var i = 0; i < fn.length; i++) {
                if (typeof window[fn[i]] == 'undefined') {
                    return false;
                }
            }
            return true;
        };
    }

    var timeout = options.timeout || timeoutArg;

    function unlockOnChecker(name, lock) {
        if (!(name in checkerMap)) {
            unlock(lock);
            return;
        }
        else {
            if (checkerMap[name](name)) {
                unlock(lock);
                return;
            }

            var start = +new Date();
            var interval = window.setInterval(function() {
                if (checkerMap[name](name)) {
                    // For every interval created we will clear it by design.
                    window.clearInterval(interval);
                    unlock(lock);
                }
                else if (new Date() - start >= timeout) {
                    window.clearInterval(interval);
                    throw new Error('Timed out loading "' + path + '".');
                }
            }, 10);
        }
    }

    function recursiveLoader(d) {
        if (path.length) {
            var name = path.shift();
            var p = pathFromModuleName(name);
            if (!p || locked(p)) {
                return recursiveLoader(d);
            }

            lock(p);
            d = insertScript(p).then(function() {
                recursiveLoader(d);
                unlockOnChecker(name, p);
            }, function(reason) {
                throw new Error(reason);
            });
        }
        else {
            if (!d) {
                returnDefer.resolve();
                return;
            }

            d.then(function(val) {
                returnDefer.resolve(val);
            }, function(val) {
                returnDefer.reject(val);
            });
        }
    }

    if (isSequence) {
        recursiveLoader();
    }
    else {
        var counter = 0;
        while (path.length > 0) {
            var name = path.shift();
            var p = pathFromModuleName(name);
            if (!p || locked(p)) {
                continue;
            }

            counter++;
            lock(p);

            var successFn = function(name, p, val) {
                if ((--counter) == 0) returnDefer.resolve(val);
                unlockOnChecker(name, p);
            };

            insertScript(p).then(successFn.bind(0, name, p), function(err) {
                returnDefer.reject(err);
            });
        }
        if (counter == 0) {
            returnDefer.resolve();
        }
    }

    return returnDefer.promise;
}

angular.extend(loaderFn, {
    config: function(cfg) {
        angular.extend(config, cfg);
        return loaderFn;
    },
    lock: function(name) {
        lock('ext:' + name);
    },
    unlock: function(name) {
        unlock('ext:' + name);
    }
});

angular.extend(angular, {
    loader: loaderFn,
    requires: function(name, checkerFn) {
        if (typeof name == 'object') {
            for (var n in name) {
                angular.requires(n, name[n]);
            }
        }
        else {
            angular.loader(name, {
                checker: checkerFn
            });
        }

        return angular;
    },
    module: function() {
        var name = arguments[0];
        var requires = arguments[1];
        var ret = angularModuleOriginalFn.apply(angular, arguments);

        // If module() was called with only 1 argument, it was to get the module
        // and not create a new one.
        if (arguments.length == 1) {
            return ret;
        }

        if (requires instanceof Array) {
            for (var i = 0; i < requires.length; i++) {
                var path = pathFromModuleName(requires[i]);
                if (!path || locked(requires[i])) {
                    continue;
                }

                lock(requires[i]);
                insertScript(path);
            }
        }

        var path = pathFromModuleName(name);
        if (path) {
            unlock(name);
        }
        return ret;
    }
});

// Load the first module.
lock(mainModulePathArg);
angular.loader(mainModulePathArg);

})();<|endoftext|>