<commit_before>/// <reference path="../declares.d.ts" />
'use strict';
define(["require", "exports"], function (require, exports) {
    exports.language = {
        displayName: 'ObjectPascal',
        name: 'objectpascal',
        mimeTypes: [],
        ignoreCase: true,
        defaultToken: '',
        lineComment: '//',
        blockCommentStart: '{',
        blockCommentEnd: '}',

        brackets: [
            { token: 'delimiter.array', open: '[', close: ']' },
            { token: 'delimiter.parenthesis', open: '(', close: ')' },
            { token: 'delimiter.generic', open: '<', close: '>' },
            { token: 'keyword.tag-begin', open: 'begin', close: 'end' },
            { token: 'keyword.tag-begin', open: 'try', close: 'end' },
            { token: 'keyword.tag-begin', open: 'class', close: 'end' },
            { token: 'keyword.tag-begin', open: 'interface', close: 'end' },
            { token: 'keyword.tag-begin', open: 'unit', close: 'end' },
            { token: 'keyword.tag-begin', open: 'program', close: 'end' },
            { token: 'keyword.tag-if', open: 'if', close: 'then' },
            { token: 'keyword.tag-repeat', open: 'repeat', close: 'until' },
            { token: 'keyword.tag-do', open: 'while', close: 'do' },
            { token: 'keyword.tag-do', open: 'for', close: 'do' },
            { token: 'keyword.tag-do', open: 'on', close: 'do' },
        ],

        textAfterBrackets: true,
        autoClosingPairs: [
          ['{', '}'],
          ['[', ']'],
          ['(', ')'],
          ['\'', '\'']],

        // the default separators except `@$`
        wordDefinition: /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
        keywords: [
            'ABSOLUTE',
            'ABSTRACT',
            'AND',
            'ARRAY',
            'ASM',
            'ASSEMBLER',
            'BEGIN',
            'CASE',
            'CONST',
            'CONSTRUCTOR',
            'DESTRUCTOR',
            'DISPID',
            'DIV',
            'DISPINTERFACE',
            'DO',
            'DOWNTO',
            'ELSE',
            'END',
            'EXCEPT',
            'EXPORTS',
            'EXTENDED',
            'EXTERNAL',
            'FAR',
            'FINALLY',
            'FINALIZATION',
            'FOR',
            'FORWARD',
            'FUNCTION',
            'GOTO',
            'HELPER',
            'IF',
            'IMPLEMENTATION',
            'IN',
            'INDEX',
            'INHERITED',
            'INITIALIZATION',
            'INLINE',
            'INTERFACE',
            'INTERRUPT',
            'LABEL',
            'LIBRARY',
            'MESSAGE',
            'NEAR',
            'NOT',
            'OBJECT',
            'OF',
            'ON',
            'OPERATOR',
            'OUT',
            'OVERLOAD',
            'OVERRIDE',
            'PACKED',
            'PRIVATE',
            'PROCEDURE',
            'PROGRAM',
            'PROPERTY',
            'PROTECTED',
            'PUBLIC',
            'PUBLISHED',
            'READ',
            'RECORD',
            'REFERENCE',
            'REPEAT',
            'RESIDENT',
            'RESOURCESTRING',
            'SAFECALL',
            'SET',
            'STATIC',
            'STDCALL',
            'STRICT',
            'THEN',
            'TO',
            'TRY',
            'TYPE',
            'UNIT',
            'UNTIL',
            'USES',
            'VAR',
            'VIRTUAL',
            'WHILE',
            'WRITE',
            'WITH',
        ],

        tagwords: [
            'begin',
            'try',
            'unit',
            'class',
            'program',
            'interface',
            'if',
            'then',
            'repeat',
            'until',
            'while',
            'do',
            'for',
            'on',
            'end'
        ],

        operators: [
            '=',
            '>',
            '<',
            '!',
            '~',
            '?',
            ':',
            '+',
            '-',
            '*',
            '/',
            'div',
            'mod',
            'not',
            'and',
            'or',
            'xor',
            'shl',
            'shr',
            'is',
            'as',
            '&',
            '^',
            '@',
            ':=',
          ],

          flowchangers: [
            'exit',
            'continue',
            'break',
            'abort',
            'halt'
          ],

          warnings: [
            'RunError',
            'raise',
            'deprecated',
            'experimental',
            'assert'
          ],

          types: [
            'ansichar',
            'ansistring',
            'boolean',
            'byte',
            'cardinal',
            'char',
            'double',
            'dword',
            'file',
            'integer',
            'int64',
            'longint',
            'longword',
            'nativeint',
            'nativeuint',
            'pansichar',
            'pchar',
            'pwidechar',
            'pointer',
            'real',
            'shortint',
            'shortstring',
            'single',
            'smallint',
            'string',
            'widechar',
            'widestring',
            'word',
          ],

          constants: [
             'true',
             'false',
             'nil',
             'self',
             'result',
          ],

        // we include these common regular expressions
        symbols: /[=><!~?:&|+\-*\/\^%]+/,
        escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
        // The main tokenizer for our languages
        tokenizer: {
            root: [
                { include: '@whitespace' },
                [/[a-zA-Z_]\w*/, { cases: {
                  '@tagwords': '@brackets',
                  '@operators': 'token.keyword.operator',
                  '@flowchangers': 'token.keyword.flow',
                  '@warnings': 'token.warn-token',
                  '@constants': 'token.key',
                  '@types': 'token.type',
                  '@keywords': { token: 'keyword' },
                  '@default': 'identifier' } }],
                [/[()\[\]]/, '@brackets'],
                [/[<>](?!@symbols)/, '@brackets'],
                [/@symbols/, { cases: {
                  '@operators': 'token.keyword.operator',
                  '@default': '' } }],
                [/@\s*[a-zA-Z_\$][\w\$]*/, 'number.hex'],
                [/\d*\d+[eE]([\-+]?\d+)?[fFdD]?/, 'number.float'],
                [/\d*\.\d+([eE][\-+]?\d+)?[fFdD]?/, 'number.float'],
                [/0[xX][0-9a-fA-F_]*[0-9a-fA-F][Ll]?/, 'number.hex'],
                [/0[0-7_]*[0-7][Ll]?/, 'number.octal'],
                [/0[bB][0-1_]*[0-1][Ll]?/, 'number.binary'],
                [/\d+[fFdD]/, 'number.float'],
                [/\d+[lL]?/, 'number'],
                [/[;,.]/, 'delimiter'],
                [/'([^'\\]|\\.)*$/, 'string.invalid'],
                [/'/, 'string', '@string'],
                [/'[^\\']'/, 'string'],
                [/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
                [/'/, 'string.invalid']
            ],
            whitespace: [
                [/[ \t\r\n]+/, ''],
                [/{(?!\$)/, 'comment', '@comment'],
                [/{\$/, 'annotation', '@compilerdirective'],
                [/\(\*/, 'comment', '@braceasteriskcomment'],
                [/\/\/.*$/, 'comment'],
            ],

            comment: [
                [/[^}]+/, 'comment'],
                [/}/, 'comment', '@pop'],
                [/{/, 'comment'],
            ],

            braceasteriskcomment: [
                [/((?!\*\)).)+/, 'comment'],
                [/\*\)/, 'comment', '@pop'],
                [/\(\*/, 'comment'],
            ],

            compilerdirective: [
                [/[^}]+/, 'annotation'],
                [/}/, 'annotation', '@pop'],
                [/{\$/, 'annotation'],
            ],

            string: [
                [/[^\\']+/, 'string'],
                [/@escapes/, 'string.escape'],
                [/\\./, 'string.escape.invalid'],
                [/'/, 'string', '@pop']
            ],
        },
    };
});
<commit_msg>Hex numbers are displayed well<commit_after>/// <reference path="../declares.d.ts" />
'use strict';
define(["require", "exports"], function (require, exports) {
    exports.language = {
        displayName: 'ObjectPascal',
        name: 'objectpascal',
        mimeTypes: [],
        ignoreCase: true,
        defaultToken: '',
        lineComment: '//',
        blockCommentStart: '{',
        blockCommentEnd: '}',

        brackets: [
            { token: 'delimiter.array', open: '[', close: ']' },
            { token: 'delimiter.parenthesis', open: '(', close: ')' },
            { token: 'delimiter.generic', open: '<', close: '>' },
            { token: 'keyword.tag-begin', open: 'begin', close: 'end' },
            { token: 'keyword.tag-begin', open: 'try', close: 'end' },
            { token: 'keyword.tag-begin', open: 'class', close: 'end' },
            { token: 'keyword.tag-begin', open: 'interface', close: 'end' },
            { token: 'keyword.tag-begin', open: 'unit', close: 'end' },
            { token: 'keyword.tag-begin', open: 'program', close: 'end' },
            { token: 'keyword.tag-if', open: 'if', close: 'then' },
            { token: 'keyword.tag-repeat', open: 'repeat', close: 'until' },
            { token: 'keyword.tag-do', open: 'while', close: 'do' },
            { token: 'keyword.tag-do', open: 'for', close: 'do' },
            { token: 'keyword.tag-do', open: 'on', close: 'do' },
        ],

        textAfterBrackets: true,
        autoClosingPairs: [
          ['{', '}'],
          ['[', ']'],
          ['(', ')'],
          ['\'', '\'']],

        // the default separators except `@$`
        wordDefinition: /(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
        keywords: [
            'ABSOLUTE',
            'ABSTRACT',
            'AND',
            'ARRAY',
            'ASM',
            'ASSEMBLER',
            'BEGIN',
            'CASE',
            'CONST',
            'CONSTRUCTOR',
            'DESTRUCTOR',
            'DISPID',
            'DIV',
            'DISPINTERFACE',
            'DO',
            'DOWNTO',
            'ELSE',
            'END',
            'EXCEPT',
            'EXPORTS',
            'EXTENDED',
            'EXTERNAL',
            'FAR',
            'FINALLY',
            'FINALIZATION',
            'FOR',
            'FORWARD',
            'FUNCTION',
            'GOTO',
            'HELPER',
            'IF',
            'IMPLEMENTATION',
            'IN',
            'INDEX',
            'INHERITED',
            'INITIALIZATION',
            'INLINE',
            'INTERFACE',
            'INTERRUPT',
            'LABEL',
            'LIBRARY',
            'MESSAGE',
            'NEAR',
            'NOT',
            'OBJECT',
            'OF',
            'ON',
            'OPERATOR',
            'OUT',
            'OVERLOAD',
            'OVERRIDE',
            'PACKED',
            'PRIVATE',
            'PROCEDURE',
            'PROGRAM',
            'PROPERTY',
            'PROTECTED',
            'PUBLIC',
            'PUBLISHED',
            'READ',
            'RECORD',
            'REFERENCE',
            'REPEAT',
            'RESIDENT',
            'RESOURCESTRING',
            'SAFECALL',
            'SET',
            'STATIC',
            'STDCALL',
            'STRICT',
            'THEN',
            'TO',
            'TRY',
            'TYPE',
            'UNIT',
            'UNTIL',
            'USES',
            'VAR',
            'VIRTUAL',
            'WHILE',
            'WRITE',
            'WITH',
        ],

        tagwords: [
            'begin',
            'try',
            'unit',
            'class',
            'program',
            'interface',
            'if',
            'then',
            'repeat',
            'until',
            'while',
            'do',
            'for',
            'on',
            'end'
        ],

        operators: [
            '=',
            '>',
            '<',
            '!',
            '~',
            '?',
            ':',
            '+',
            '-',
            '*',
            '/',
            'div',
            'mod',
            'not',
            'and',
            'or',
            'xor',
            'shl',
            'shr',
            'is',
            'as',
            '&',
            '^',
            '@',
            ':=',
          ],

          flowchangers: [
            'exit',
            'continue',
            'break',
            'abort',
            'halt'
          ],

          warnings: [
            'RunError',
            'raise',
            'deprecated',
            'experimental',
            'assert'
          ],

          types: [
            'ansichar',
            'ansistring',
            'boolean',
            'byte',
            'cardinal',
            'char',
            'double',
            'dword',
            'file',
            'integer',
            'int64',
            'longint',
            'longword',
            'nativeint',
            'nativeuint',
            'pansichar',
            'pchar',
            'pwidechar',
            'pointer',
            'real',
            'shortint',
            'shortstring',
            'single',
            'smallint',
            'string',
            'widechar',
            'widestring',
            'word',
          ],

          constants: [
             'true',
             'false',
             'nil',
             'self',
             'result',
          ],

        // we include these common regular expressions
        symbols: /[=><!~?:&|+\-*\/\^%]+/,
        escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
        // The main tokenizer for our languages
        tokenizer: {
            root: [
                { include: '@whitespace' },
                [/[a-zA-Z_]\w*/, { cases: {
                  '@tagwords': '@brackets',
                  '@operators': 'token.keyword.operator',
                  '@flowchangers': 'token.keyword.flow',
                  '@warnings': 'token.warn-token',
                  '@constants': 'token.key',
                  '@types': 'token.type',
                  '@keywords': { token: 'keyword' },
                  '@default': 'identifier' } }],
                [/[()\[\]]/, '@brackets'],
                [/[<>](?!@symbols)/, '@brackets'],
                [/@symbols/, { cases: {
                  '@operators': 'token.keyword.operator',
                  '@default': '' } }],
                [/@\s*[a-zA-Z_\$][\w\$]*/, 'number.hex'],
                [/\d*\d+[eE]([\-+]?\d+)?[fFdD]?/, 'number.float'],
                [/\d*\.\d+([eE][\-+]?\d+)?[fFdD]?/, 'number.float'],
                [/[\$][0-9a-fA-F_]*[0-9a-fA-F]?/, 'number.hex'],
                [/0[0-7_]*[0-7][Ll]?/, 'number.octal'],
                [/0[bB][0-1_]*[0-1][Ll]?/, 'number.binary'],
                [/\d+[fFdD]/, 'number.float'],
                [/\d+[lL]?/, 'number'],
                [/[;,.]/, 'delimiter'],
                [/'([^'\\]|\\.)*$/, 'string.invalid'],
                [/'/, 'string', '@string'],
                [/'[^\\']'/, 'string'],
                [/(')(@escapes)(')/, ['string', 'string.escape', 'string']],
                [/'/, 'string.invalid']
            ],
            whitespace: [
                [/[ \t\r\n]+/, ''],
                [/{(?!\$)/, 'comment', '@comment'],
                [/{\$/, 'annotation', '@compilerdirective'],
                [/\(\*/, 'comment', '@braceasteriskcomment'],
                [/\/\/.*$/, 'comment'],
            ],

            comment: [
                [/[^}]+/, 'comment'],
                [/}/, 'comment', '@pop'],
                [/{/, 'comment'],
            ],

            braceasteriskcomment: [
                [/((?!\*\)).)+/, 'comment'],
                [/\*\)/, 'comment', '@pop'],
                [/\(\*/, 'comment'],
            ],

            compilerdirective: [
                [/[^}]+/, 'annotation'],
                [/}/, 'annotation', '@pop'],
                [/{\$/, 'annotation'],
            ],

            string: [
                [/[^\\']+/, 'string'],
                [/@escapes/, 'string.escape'],
                [/\\./, 'string.escape.invalid'],
                [/'/, 'string', '@pop']
            ],
        },
    };
});
<|endoftext|>


<commit_before>/**
 * SVGInjector v1.1.0 - Fast, caching, dynamic inline SVG DOM injection library
 * https://github.com/iconic/SVGInjector
 *
 * Copyright (c) 2014 Waybury <hello@waybury.com>
 * @license MIT
 */

(function (window, document) {

  'use strict';

  // Environment
  var isLocal = window.location.protocol === 'file:';
  var hasSvgSupport = document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1');

  function uniqueClasses(list) {
    list = list.split(' ');

    var hash = {};
    var i = list.length;
    var out = [];

    while (i--) {
      if (!hash.hasOwnProperty(list[i])) {
        hash[list[i]] = 1;
        out.unshift(list[i]);
      }
    }

    return out.join(' ');
  }

  /**
   * cache (or polyfill for <= IE8) Array.forEach()
   * source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
   */
  var forEach = Array.prototype.forEach || function (fn, scope) {
    if (this === void 0 || this === null || typeof fn !== 'function') {
      throw new TypeError();
    }

    /* jshint bitwise: false */
    var i, len = this.length >>> 0;
    /* jshint bitwise: true */

    for (i = 0; i < len; ++i) {
      if (i in this) {
        fn.call(scope, this[i], i, this);
      }
    }
  };

  // SVG Cache
  var svgCache = {};

  var injectCount = 0;
  var injectedElements = [];

  // Request Queue
  var requestQueue = [];

  // Script running status
  var ranScripts = {};

  var cloneSvg = function (sourceSvg) {
    return sourceSvg.cloneNode(true);
  };

  var queueRequest = function (url, callback) {
    requestQueue[url] = requestQueue[url] || [];
    requestQueue[url].push(callback);
  };

  var processRequestQueue = function (url) {
    for (var i = 0, len = requestQueue[url].length; i < len; i++) {
      // Make these calls async so we avoid blocking the page/renderer
      /* jshint loopfunc: true */
      (function (index) {
        setTimeout(function () {
          requestQueue[url][index](cloneSvg(svgCache[url]));
        }, 0);
      })(i);
      /* jshint loopfunc: false */
    }
  };

  var loadSvg = function (url, callback) {
    if (svgCache[url] !== undefined) {
      if (svgCache[url] instanceof SVGSVGElement) {
        // We already have it in cache, so use it
        callback(cloneSvg(svgCache[url]));
      }
      else {
        // We don't have it in cache yet, but we are loading it, so queue this request
        queueRequest(url, callback);
      }
    }
    else {

      if (!window.XMLHttpRequest) {
        callback('Browser does not support XMLHttpRequest');
        return false;
      }

      // Seed the cache to indicate we are loading this URL already
      svgCache[url] = {};
      queueRequest(url, callback);

      var httpRequest = new XMLHttpRequest();

      httpRequest.onreadystatechange = function () {
        // readyState 4 = complete
        if (httpRequest.readyState === 4) {

          // Handle status
          if (httpRequest.status === 404 || httpRequest.responseXML === null) {
            callback('Unable to load SVG file: ' + url);

            if (isLocal) callback('Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver.');

            callback();
            return false;
          }

          // 200 success from server, or 0 when using file:// protocol locally
          if (httpRequest.status === 200 || (isLocal && httpRequest.status === 0)) {

            /* globals Document */
            if (httpRequest.responseXML instanceof Document) {
              // Cache it
              svgCache[url] = httpRequest.responseXML.documentElement;
            }
            /* globals -Document */

            // IE9 doesn't create a responseXML Document object from loaded SVG,
            // and throws a "DOM Exception: HIERARCHY_REQUEST_ERR (3)" error when injected.
            //
            // So, we'll just create our own manually via the DOMParser using
            // the the raw XML responseText.
            //
            // :NOTE: IE8 and older doesn't have DOMParser, but they can't do SVG either, so...
            else if (DOMParser && (DOMParser instanceof Function)) {
              var xmlDoc;
              try {
                var parser = new DOMParser();
                xmlDoc = parser.parseFromString(httpRequest.responseText, 'text/xml');
              }
              catch (e) {
                xmlDoc = undefined;
              }

              if (!xmlDoc || xmlDoc.getElementsByTagName('parsererror').length) {
                callback('Unable to parse SVG file: ' + url);
                return false;
              }
              else {
                // Cache it
                svgCache[url] = xmlDoc.documentElement;
              }
            }

            // We've loaded a new asset, so process any requests waiting for it
            processRequestQueue(url);
          }
          else {
            callback('There was a problem injecting the SVG: ' + httpRequest.status + ' ' + httpRequest.statusText);
            return false;
          }
        }
      };

      httpRequest.open('GET', url);

      // Treat and parse the response as XML, even if the
      // server sends us a different mimetype
      if (httpRequest.overrideMimeType) httpRequest.overrideMimeType('text/xml');

      httpRequest.send();
    }
  };

  // Inject a single element
  var injectElement = function (el, evalScripts, pngFallback, callback) {

    // Grab the src or data-src attribute
    var imgUrl = el.getAttribute('data-src') || el.getAttribute('src');

    // We can only inject SVG
    if (!(/svg$/i).test(imgUrl)) {
      callback('Attempted to inject a file with a non-svg extension: ' + imgUrl);
      return;
    }

    // If we don't have SVG support try to fall back to a png,
    // either defined per-element via data-fallback or data-png,
    // or globally via the pngFallback directory setting
    if (!hasSvgSupport) {
      var perElementFallback = el.getAttribute('data-fallback') || el.getAttribute('data-png');

      // Per-element specific PNG fallback defined, so use that
      if (perElementFallback) {
        el.setAttribute('src', perElementFallback);
        callback(null);
      }
      // Global PNG fallback directoriy defined, use the same-named PNG
      else if (pngFallback) {
        el.setAttribute('src', pngFallback + '/' + imgUrl.split('/').pop().replace('.svg', '.png'));
        callback(null);
      }
      // um...
      else {
        callback('This browser does not support SVG and no PNG fallback was defined.');
      }

      return;
    }

    // Make sure we aren't already in the process of injecting this element to
    // avoid a race condition if multiple injections for the same element are run.
    // :NOTE: Using indexOf() only _after_ we check for SVG support and bail,
    // so no need for IE8 indexOf() polyfill
    if (injectedElements.indexOf(el) !== -1) {
      return;
    }

    // Remember the request to inject this element, in case other injection
    // calls are also trying to replace this element before we finish
    injectedElements.push(el);

    // Try to avoid loading the orginal image src if possible.
    el.setAttribute('src', '');

    // Load it up
    loadSvg(imgUrl, function (svg) {

      if (typeof svg === 'undefined' || typeof svg === 'string') {
        callback(svg);
        return false;
      }

      var imgId = el.getAttribute('id');
      if (imgId) {
        svg.setAttribute('id', imgId);
      }

      var imgTitle = el.getAttribute('title');
      if (imgTitle) {
        svg.setAttribute('title', imgTitle);
      }

      // Concat the SVG classes + 'injected-svg' + the img classes
      var classMerge = [].concat(svg.getAttribute('class') || [], 'injected-svg', el.getAttribute('class') || []).join(' ');
      svg.setAttribute('class', uniqueClasses(classMerge));

      var imgStyle = el.getAttribute('style');
      if (imgStyle) {
        svg.setAttribute('style', imgStyle);
      }

      // Copy all the data elements to the svg
      var imgData = [].filter.call(el.attributes, function (at) {
        return (/^data-\w[\w\-]*$/).test(at.name);
      });
      forEach.call(imgData, function (dataAttr) {
        if (dataAttr.name && dataAttr.value) {
          svg.setAttribute(dataAttr.name, dataAttr.value);
        }
      });

      // Make sure any internally referenced clipPath ids and their
      // clip-path references are unique.
      //
      // This addresses the issue of having multiple instances of the
      // same SVG on a page and only the first clipPath id is referenced.
      //
      // Browsers often shortcut the SVG Spec and don't use clipPaths
      // contained in parent elements that are hidden, so if you hide the first
      // SVG instance on the page, then all other instances lose their clipping.
      // Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=376027
      var clipPaths = svg.querySelectorAll('defs clipPath[id]');
      var newClipPathName;
      for (var i = 0, clipPathsLen = clipPaths.length; i < clipPathsLen; i++) {
        newClipPathName = clipPaths[i].id + '-' + injectCount;
        // :NOTE: using a substring match attr selector here to deal with IE "adding extra quotes in url() attrs"
        var usingClipPath = svg.querySelectorAll('[clip-path*="' + clipPaths[i].id + '"]');
        for (var j = 0, usingClipPathLen = usingClipPath.length; j < usingClipPathLen; j++) {
          usingClipPath[j].setAttribute('clip-path', 'url(#' + newClipPathName + ')');
        }
        clipPaths[i].id = newClipPathName;
      }

      // Remove any unwanted/invalid namespaces that might have been added by SVG editing tools
      svg.removeAttribute('xmlns:a');

      // Post page load injected SVGs don't automatically have their script
      // elements run, so we'll need to make that happen, if requested

      // Find then prune the scripts
      var scripts = svg.querySelectorAll('script');
      var scriptsToEval = [];
      var script, scriptType;

      for (var k = 0, scriptsLen = scripts.length; k < scriptsLen; k++) {
        scriptType = scripts[k].getAttribute('type');

        // Only process javascript types.
        // SVG defaults to 'application/ecmascript' for unset types
        if (!scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript') {

          // innerText for IE, textContent for other browsers
          script = scripts[k].innerText || scripts[k].textContent;

          // Stash
          scriptsToEval.push(script);

          // Tidy up and remove the script element since we don't need it anymore
          svg.removeChild(scripts[k]);
        }
      }

      // Run/Eval the scripts if needed
      if (scriptsToEval.length > 0 && (evalScripts === 'always' || (evalScripts === 'once' && !ranScripts[imgUrl]))) {
        for (var l = 0, scriptsToEvalLen = scriptsToEval.length; l < scriptsToEvalLen; l++) {

          // :NOTE: Yup, this is a form of eval, but it is being used to eval code
          // the caller has explictely asked to be loaded, and the code is in a caller
          // defined SVG file... not raw user input.
          //
          // Also, the code is evaluated in a closure and not in the global scope.
          // If you need to put something in global scope, use 'window'
          new Function(scriptsToEval[l])(window); // jshint ignore:line
        }

        // Remember we already ran scripts for this svg
        ranScripts[imgUrl] = true;
      }

      // Replace the image with the svg
      el.parentNode.replaceChild(svg, el);

      // Now that we no longer need it, drop references
      // to the original element so it can be GC'd
      delete injectedElements[injectedElements.indexOf(el)];
      el = null;

      // Increment the injected count
      injectCount++;

      callback(svg);
    });
  };

  /**
   * SVGInjector
   *
   * Replace the given elements with their full inline SVG DOM elements.
   *
   * :NOTE: We are using get/setAttribute with SVG because the SVG DOM spec differs from HTML DOM and
   * can return other unexpected object types when trying to directly access svg properties.
   * ex: "className" returns a SVGAnimatedString with the class value found in the "baseVal" property,
   * instead of simple string like with HTML Elements.
   *
   * @param {mixes} Array of or single DOM element
   * @param {object} options
   * @param {function} callback
   * @return {object} Instance of SVGInjector
   */
  var SVGInjector = function (elements, options, done) {

    // Options & defaults
    options = options || {};

    // Should we run the scripts blocks found in the SVG
    // 'always' - Run them every time
    // 'once' - Only run scripts once for each SVG
    // [false|'never'] - Ignore scripts
    var evalScripts = options.evalScripts || 'always';

    // Location of fallback pngs, if desired
    var pngFallback = options.pngFallback || false;

    // Callback to run during each SVG injection, returning the SVG injected
    var eachCallback = options.each;

    // Do the injection...
    if (elements.length !== undefined) {
      var elementsLoaded = 0;
      forEach.call(elements, function (element) {
        injectElement(element, evalScripts, pngFallback, function (svg) {
          if (eachCallback && typeof eachCallback === 'function') eachCallback(svg);
          if (done && elements.length === ++elementsLoaded) done(elementsLoaded);
        });
      });
    }
    else {
      if (elements) {
        injectElement(elements, evalScripts, pngFallback, function (svg) {
          if (eachCallback && typeof eachCallback === 'function') eachCallback(svg);
          if (done) done(1);
          elements = null;
        });
      }
      else {
        if (done) done(0);
      }
    }
  };

  /* global module, exports: true, define */
  // Node.js or CommonJS
  if (typeof module === 'object' && typeof module.exports === 'object') {
    module.exports = exports = SVGInjector;
  }
  // AMD support
  else if (typeof define === 'function' && define.amd) {
    define(function () {
      return SVGInjector;
    });
  }
  // Otherwise, attach to window as global
  else if (typeof window === 'object') {
    window.SVGInjector = SVGInjector;
  }
  /* global -module, -exports, -define */

}(window, document));
<commit_msg>Fix for issue #17 - "SVG Injector doesn't work if there is a URL parameter". Updated the regex that was matching for an svg file extension to allow for query strings.<commit_after>/**
 * SVGInjector v1.1.0 - Fast, caching, dynamic inline SVG DOM injection library
 * https://github.com/iconic/SVGInjector
 *
 * Copyright (c) 2014 Waybury <hello@waybury.com>
 * @license MIT
 */

(function (window, document) {

  'use strict';

  // Environment
  var isLocal = window.location.protocol === 'file:';
  var hasSvgSupport = document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#BasicStructure', '1.1');

  function uniqueClasses(list) {
    list = list.split(' ');

    var hash = {};
    var i = list.length;
    var out = [];

    while (i--) {
      if (!hash.hasOwnProperty(list[i])) {
        hash[list[i]] = 1;
        out.unshift(list[i]);
      }
    }

    return out.join(' ');
  }

  /**
   * cache (or polyfill for <= IE8) Array.forEach()
   * source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
   */
  var forEach = Array.prototype.forEach || function (fn, scope) {
    if (this === void 0 || this === null || typeof fn !== 'function') {
      throw new TypeError();
    }

    /* jshint bitwise: false */
    var i, len = this.length >>> 0;
    /* jshint bitwise: true */

    for (i = 0; i < len; ++i) {
      if (i in this) {
        fn.call(scope, this[i], i, this);
      }
    }
  };

  // SVG Cache
  var svgCache = {};

  var injectCount = 0;
  var injectedElements = [];

  // Request Queue
  var requestQueue = [];

  // Script running status
  var ranScripts = {};

  var cloneSvg = function (sourceSvg) {
    return sourceSvg.cloneNode(true);
  };

  var queueRequest = function (url, callback) {
    requestQueue[url] = requestQueue[url] || [];
    requestQueue[url].push(callback);
  };

  var processRequestQueue = function (url) {
    for (var i = 0, len = requestQueue[url].length; i < len; i++) {
      // Make these calls async so we avoid blocking the page/renderer
      /* jshint loopfunc: true */
      (function (index) {
        setTimeout(function () {
          requestQueue[url][index](cloneSvg(svgCache[url]));
        }, 0);
      })(i);
      /* jshint loopfunc: false */
    }
  };

  var loadSvg = function (url, callback) {
    if (svgCache[url] !== undefined) {
      if (svgCache[url] instanceof SVGSVGElement) {
        // We already have it in cache, so use it
        callback(cloneSvg(svgCache[url]));
      }
      else {
        // We don't have it in cache yet, but we are loading it, so queue this request
        queueRequest(url, callback);
      }
    }
    else {

      if (!window.XMLHttpRequest) {
        callback('Browser does not support XMLHttpRequest');
        return false;
      }

      // Seed the cache to indicate we are loading this URL already
      svgCache[url] = {};
      queueRequest(url, callback);

      var httpRequest = new XMLHttpRequest();

      httpRequest.onreadystatechange = function () {
        // readyState 4 = complete
        if (httpRequest.readyState === 4) {

          // Handle status
          if (httpRequest.status === 404 || httpRequest.responseXML === null) {
            callback('Unable to load SVG file: ' + url);

            if (isLocal) callback('Note: SVG injection ajax calls do not work locally without adjusting security setting in your browser. Or consider using a local webserver.');

            callback();
            return false;
          }

          // 200 success from server, or 0 when using file:// protocol locally
          if (httpRequest.status === 200 || (isLocal && httpRequest.status === 0)) {

            /* globals Document */
            if (httpRequest.responseXML instanceof Document) {
              // Cache it
              svgCache[url] = httpRequest.responseXML.documentElement;
            }
            /* globals -Document */

            // IE9 doesn't create a responseXML Document object from loaded SVG,
            // and throws a "DOM Exception: HIERARCHY_REQUEST_ERR (3)" error when injected.
            //
            // So, we'll just create our own manually via the DOMParser using
            // the the raw XML responseText.
            //
            // :NOTE: IE8 and older doesn't have DOMParser, but they can't do SVG either, so...
            else if (DOMParser && (DOMParser instanceof Function)) {
              var xmlDoc;
              try {
                var parser = new DOMParser();
                xmlDoc = parser.parseFromString(httpRequest.responseText, 'text/xml');
              }
              catch (e) {
                xmlDoc = undefined;
              }

              if (!xmlDoc || xmlDoc.getElementsByTagName('parsererror').length) {
                callback('Unable to parse SVG file: ' + url);
                return false;
              }
              else {
                // Cache it
                svgCache[url] = xmlDoc.documentElement;
              }
            }

            // We've loaded a new asset, so process any requests waiting for it
            processRequestQueue(url);
          }
          else {
            callback('There was a problem injecting the SVG: ' + httpRequest.status + ' ' + httpRequest.statusText);
            return false;
          }
        }
      };

      httpRequest.open('GET', url);

      // Treat and parse the response as XML, even if the
      // server sends us a different mimetype
      if (httpRequest.overrideMimeType) httpRequest.overrideMimeType('text/xml');

      httpRequest.send();
    }
  };

  // Inject a single element
  var injectElement = function (el, evalScripts, pngFallback, callback) {

    // Grab the src or data-src attribute
    var imgUrl = el.getAttribute('data-src') || el.getAttribute('src');

    // We can only inject SVG
    if (!(/\.svg/i).test(imgUrl)) {
      callback('Attempted to inject a file with a non-svg extension: ' + imgUrl);
      return;
    }

    // If we don't have SVG support try to fall back to a png,
    // either defined per-element via data-fallback or data-png,
    // or globally via the pngFallback directory setting
    if (!hasSvgSupport) {
      var perElementFallback = el.getAttribute('data-fallback') || el.getAttribute('data-png');

      // Per-element specific PNG fallback defined, so use that
      if (perElementFallback) {
        el.setAttribute('src', perElementFallback);
        callback(null);
      }
      // Global PNG fallback directoriy defined, use the same-named PNG
      else if (pngFallback) {
        el.setAttribute('src', pngFallback + '/' + imgUrl.split('/').pop().replace('.svg', '.png'));
        callback(null);
      }
      // um...
      else {
        callback('This browser does not support SVG and no PNG fallback was defined.');
      }

      return;
    }

    // Make sure we aren't already in the process of injecting this element to
    // avoid a race condition if multiple injections for the same element are run.
    // :NOTE: Using indexOf() only _after_ we check for SVG support and bail,
    // so no need for IE8 indexOf() polyfill
    if (injectedElements.indexOf(el) !== -1) {
      return;
    }

    // Remember the request to inject this element, in case other injection
    // calls are also trying to replace this element before we finish
    injectedElements.push(el);

    // Try to avoid loading the orginal image src if possible.
    el.setAttribute('src', '');

    // Load it up
    loadSvg(imgUrl, function (svg) {

      if (typeof svg === 'undefined' || typeof svg === 'string') {
        callback(svg);
        return false;
      }

      var imgId = el.getAttribute('id');
      if (imgId) {
        svg.setAttribute('id', imgId);
      }

      var imgTitle = el.getAttribute('title');
      if (imgTitle) {
        svg.setAttribute('title', imgTitle);
      }

      // Concat the SVG classes + 'injected-svg' + the img classes
      var classMerge = [].concat(svg.getAttribute('class') || [], 'injected-svg', el.getAttribute('class') || []).join(' ');
      svg.setAttribute('class', uniqueClasses(classMerge));

      var imgStyle = el.getAttribute('style');
      if (imgStyle) {
        svg.setAttribute('style', imgStyle);
      }

      // Copy all the data elements to the svg
      var imgData = [].filter.call(el.attributes, function (at) {
        return (/^data-\w[\w\-]*$/).test(at.name);
      });
      forEach.call(imgData, function (dataAttr) {
        if (dataAttr.name && dataAttr.value) {
          svg.setAttribute(dataAttr.name, dataAttr.value);
        }
      });

      // Make sure any internally referenced clipPath ids and their
      // clip-path references are unique.
      //
      // This addresses the issue of having multiple instances of the
      // same SVG on a page and only the first clipPath id is referenced.
      //
      // Browsers often shortcut the SVG Spec and don't use clipPaths
      // contained in parent elements that are hidden, so if you hide the first
      // SVG instance on the page, then all other instances lose their clipping.
      // Reference: https://bugzilla.mozilla.org/show_bug.cgi?id=376027
      var clipPaths = svg.querySelectorAll('defs clipPath[id]');
      var newClipPathName;
      for (var i = 0, clipPathsLen = clipPaths.length; i < clipPathsLen; i++) {
        newClipPathName = clipPaths[i].id + '-' + injectCount;
        // :NOTE: using a substring match attr selector here to deal with IE "adding extra quotes in url() attrs"
        var usingClipPath = svg.querySelectorAll('[clip-path*="' + clipPaths[i].id + '"]');
        for (var j = 0, usingClipPathLen = usingClipPath.length; j < usingClipPathLen; j++) {
          usingClipPath[j].setAttribute('clip-path', 'url(#' + newClipPathName + ')');
        }
        clipPaths[i].id = newClipPathName;
      }

      // Remove any unwanted/invalid namespaces that might have been added by SVG editing tools
      svg.removeAttribute('xmlns:a');

      // Post page load injected SVGs don't automatically have their script
      // elements run, so we'll need to make that happen, if requested

      // Find then prune the scripts
      var scripts = svg.querySelectorAll('script');
      var scriptsToEval = [];
      var script, scriptType;

      for (var k = 0, scriptsLen = scripts.length; k < scriptsLen; k++) {
        scriptType = scripts[k].getAttribute('type');

        // Only process javascript types.
        // SVG defaults to 'application/ecmascript' for unset types
        if (!scriptType || scriptType === 'application/ecmascript' || scriptType === 'application/javascript') {

          // innerText for IE, textContent for other browsers
          script = scripts[k].innerText || scripts[k].textContent;

          // Stash
          scriptsToEval.push(script);

          // Tidy up and remove the script element since we don't need it anymore
          svg.removeChild(scripts[k]);
        }
      }

      // Run/Eval the scripts if needed
      if (scriptsToEval.length > 0 && (evalScripts === 'always' || (evalScripts === 'once' && !ranScripts[imgUrl]))) {
        for (var l = 0, scriptsToEvalLen = scriptsToEval.length; l < scriptsToEvalLen; l++) {

          // :NOTE: Yup, this is a form of eval, but it is being used to eval code
          // the caller has explictely asked to be loaded, and the code is in a caller
          // defined SVG file... not raw user input.
          //
          // Also, the code is evaluated in a closure and not in the global scope.
          // If you need to put something in global scope, use 'window'
          new Function(scriptsToEval[l])(window); // jshint ignore:line
        }

        // Remember we already ran scripts for this svg
        ranScripts[imgUrl] = true;
      }

      // Replace the image with the svg
      el.parentNode.replaceChild(svg, el);

      // Now that we no longer need it, drop references
      // to the original element so it can be GC'd
      delete injectedElements[injectedElements.indexOf(el)];
      el = null;

      // Increment the injected count
      injectCount++;

      callback(svg);
    });
  };

  /**
   * SVGInjector
   *
   * Replace the given elements with their full inline SVG DOM elements.
   *
   * :NOTE: We are using get/setAttribute with SVG because the SVG DOM spec differs from HTML DOM and
   * can return other unexpected object types when trying to directly access svg properties.
   * ex: "className" returns a SVGAnimatedString with the class value found in the "baseVal" property,
   * instead of simple string like with HTML Elements.
   *
   * @param {mixes} Array of or single DOM element
   * @param {object} options
   * @param {function} callback
   * @return {object} Instance of SVGInjector
   */
  var SVGInjector = function (elements, options, done) {

    // Options & defaults
    options = options || {};

    // Should we run the scripts blocks found in the SVG
    // 'always' - Run them every time
    // 'once' - Only run scripts once for each SVG
    // [false|'never'] - Ignore scripts
    var evalScripts = options.evalScripts || 'always';

    // Location of fallback pngs, if desired
    var pngFallback = options.pngFallback || false;

    // Callback to run during each SVG injection, returning the SVG injected
    var eachCallback = options.each;

    // Do the injection...
    if (elements.length !== undefined) {
      var elementsLoaded = 0;
      forEach.call(elements, function (element) {
        injectElement(element, evalScripts, pngFallback, function (svg) {
          if (eachCallback && typeof eachCallback === 'function') eachCallback(svg);
          if (done && elements.length === ++elementsLoaded) done(elementsLoaded);
        });
      });
    }
    else {
      if (elements) {
        injectElement(elements, evalScripts, pngFallback, function (svg) {
          if (eachCallback && typeof eachCallback === 'function') eachCallback(svg);
          if (done) done(1);
          elements = null;
        });
      }
      else {
        if (done) done(0);
      }
    }
  };

  /* global module, exports: true, define */
  // Node.js or CommonJS
  if (typeof module === 'object' && typeof module.exports === 'object') {
    module.exports = exports = SVGInjector;
  }
  // AMD support
  else if (typeof define === 'function' && define.amd) {
    define(function () {
      return SVGInjector;
    });
  }
  // Otherwise, attach to window as global
  else if (typeof window === 'object') {
    window.SVGInjector = SVGInjector;
  }
  /* global -module, -exports, -define */

}(window, document));
<|endoftext|>


<commit_before>describe('Actions suggestions-stats directive', function() {
    'use strict';

    var scope, element, createElement;

    beforeEach(module('data-prep.actions-suggestions'));
    beforeEach(module('htmlTemplates'));

    beforeEach(module('pascalprecht.translate', function ($translateProvider) {
        $translateProvider.translations('en', {
            'COLON': ': '
        });
        $translateProvider.preferredLanguage('en');
    }));

    beforeEach(inject(function($rootScope, $compile) {
        scope = $rootScope.$new();

        createElement = function() {
            scope = $rootScope.$new();
            element = angular.element('<actions-suggestions></actions-suggestions>');
            $compile(element)(scope);
            scope.$digest();
        };
    }));

    afterEach(function() {
        scope.$destroy();
        element.remove();
    });

    it('should set "Action" in title when no column is selected', inject(function(SuggestionService) {
        //given
        SuggestionService.currentColumn = null;

        //when
        createElement();

        //then
        expect(element.find('.title').text().trim()).toBe('Actions');
    }));

    it('should set column name in title', inject(function(SuggestionService) {
        //given
        SuggestionService.currentColumn = {name: 'Col 1'};

        //when
        createElement();

        //then
        expect(element.find('.title').text().trim()).toBe('Actions: Col 1');
    }));
});
<commit_msg>TDP-551: Add input search action filter directive unit tests<commit_after>describe('Actions suggestions-stats directive', function() {
    'use strict';

    var scope, element, createElement;
    var body = angular.element('body');
    beforeEach(module('data-prep.actions-suggestions'));
    beforeEach(module('htmlTemplates'));

    beforeEach(module('pascalprecht.translate', function ($translateProvider) {
        $translateProvider.translations('en', {
            'COLON': ': '
        });
        $translateProvider.preferredLanguage('en');
    }));

    beforeEach(inject(function($rootScope, $compile) {
        scope = $rootScope.$new();
        createElement = function() {
            scope = $rootScope.$new();
            element = angular.element('<actions-suggestions></actions-suggestions>');
            body.append(element);
            $compile(element)(scope);
            scope.$digest();
        };
    }));

    afterEach(function() {
        scope.$destroy();
        element.remove();
    });

    it('should set "Action" in title when no column is selected', inject(function(SuggestionService) {
        //given
        SuggestionService.currentColumn = null;

        //when
        createElement();

        //then
        expect(element.find('.title').text().trim()).toBe('Actions');
    }));

    it('should set column name in title', inject(function(SuggestionService) {
        //given
        SuggestionService.currentColumn = {name: 'Col 1'};

        //when
        createElement();

        //then
        expect(element.find('.title').text().trim()).toBe('Actions: Col 1');
    }));

    it('should display all suggested actions', inject(function(ColumnSuggestionService) {
        //when
        createElement();
        ColumnSuggestionService.transformations = [
            {
                'name': 'ceil_value',
                'label': 'Ceil value'
            },
            {
                'name': 'floor_value',
                'label': 'Floor value'
            },
            {
                'name': 'round_value',
                'label': 'Round value'
            }
        ];
        scope.$digest();

        //then
        expect(element.find('.accordion').length).toBe(3);
    }));

    it('should display searched suggested actions', inject(function(ColumnSuggestionService) {
        //when
        createElement();
        ColumnSuggestionService.transformations = [
            {
                'name': 'ceil_value',
                'label': 'Ceil value'
            },
            {
                'name': 'floor_value',
                'label': 'Floor value'
            },
            {
                'name': 'round_value',
                'label': 'Round value'
            }
        ];
        scope.$digest();

        element.controller('actionsSuggestions').searchActionString ='oo';
        scope.$digest();

        //then
        expect(element.find('.accordion').length).toBe(1);
    }));

});
<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Emitter", "Tone/core/Timeline"], function (Tone) {

	/**
	 *  shim
	 *  @private
	 */
	if (!window.hasOwnProperty("AudioContext") && window.hasOwnProperty("webkitAudioContext")){
		window.AudioContext = window.webkitAudioContext;
	}

	/**
	 *  @class Wrapper around the native AudioContext.
	 *  @extends {Tone.Emitter}
	 *  @param {AudioContext=} context optionally pass in a context
	 */
	Tone.Context = function(context){

		Tone.Emitter.call(this);

		if (!context){
			context = new window.AudioContext();
		}
		this._context = context;
		// extend all of the methods
		for (var prop in this._context){
			this._defineProperty(this._context, prop);
		}

		/**
		 *  The default latency hint
		 *  @type  {String}
		 *  @private
		 */
		this._latencyHint = "interactive";

		/**
		 *  An object containing all of the constants AudioBufferSourceNodes
		 *  @type  {Object}
		 *  @private
		 */
		this._constants = {};

		///////////////////////////////////////////////////////////////////////
		// WORKER
		///////////////////////////////////////////////////////////////////////

		/**
		 *  The amount of time events are scheduled
		 *  into the future
		 *  @type  {Number}
		 *  @private
		 */
		this._lookAhead = 0.1;

		/**
		 *  How often the update look runs
		 *  @type  {Number}
		 *  @private
		 */
		this._updateInterval = this._lookAhead/3;

		/**
		 *  A reference to the actual computed update interval
		 *  @type  {Number}
		 *  @private
		 */
		this._computedUpdateInterval = 0;

		/**
		 *  The web worker which is used to update Tone.Clock
		 *  @private
		 *  @type  {WebWorker}
		 */
		this._worker = this._createWorker();

		///////////////////////////////////////////////////////////////////////
		// TIMEOUTS
		///////////////////////////////////////////////////////////////////////

		/**
		 *  All of the setTimeout events.
		 *  @type  {Tone.Timeline}
		 *  @private
		 */
		this._timeouts = new Tone.Timeline();

		/**
		 *  The timeout id counter
		 *  @private
		 *  @type {Number}
		 */
		this._timeoutIds = 0;

		this.on("tick", this._timeoutLoop.bind(this));

	};

	Tone.extend(Tone.Context, Tone.Emitter);
	Tone.Emitter.mixin(Tone.Context);

	/**
	 *  Define a property on this Tone.Context.
	 *  This is used to extend the native AudioContext
	 *  @param  {AudioContext}  context
	 *  @param  {String}  prop
	 *  @private
	 */
	Tone.Context.prototype._defineProperty = function(context, prop){
		if (Tone.isUndef(this[prop])){
			Object.defineProperty(this, prop, {
				get : function(){
					if (typeof context[prop] === "function"){
						return context[prop].bind(context);
					} else {
						return context[prop];
					}
				},
				set : function(val){
					context[prop] = val;
				}
			});
		}
	};

	/**
	 *  The current audio context time
	 *  @return  {Number}
	 */
	Tone.Context.prototype.now = function(){
		return this._context.currentTime;
	};

	/**
	 *  Generate a web worker
	 *  @return  {WebWorker}
	 *  @private
	 */
	Tone.Context.prototype._createWorker = function(){

		//URL Shim
		window.URL = window.URL || window.webkitURL;

		var blob = new Blob([
			//the initial timeout time
			"var timeoutTime = "+(this._updateInterval * 1000).toFixed(1)+";" +
			//onmessage callback
			"self.onmessage = function(msg){" +
			"	timeoutTime = parseInt(msg.data);" +
			"};" +
			//the tick function which posts a message
			//and schedules a new tick
			"function tick(){" +
			"	setTimeout(tick, timeoutTime);" +
			"	self.postMessage('tick');" +
			"}" +
			//call tick initially
			"tick();"
		]);
		var blobUrl = URL.createObjectURL(blob);
		var worker = new Worker(blobUrl);

		worker.addEventListener("message", function(){
			// tick the clock
			this.emit("tick");
		}.bind(this));

		//lag compensation
		worker.addEventListener("message", function(){
			var now = this.now();
			if (Tone.isNumber(this._lastUpdate)){
				var diff = now - this._lastUpdate;
				this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);
			}
			this._lastUpdate = now;
		}.bind(this));

		return worker;
	};

	/**
	 *  Generate a looped buffer at some constant value.
	 *  @param  {Number}  val
	 *  @return  {BufferSourceNode}
	 */
	Tone.Context.prototype.getConstant = function(val){
		if (this._constants[val]){
			return this._constants[val];
		} else {
			var buffer = this._context.createBuffer(1, 128, this._context.sampleRate);
			var arr = buffer.getChannelData(0);
			for (var i = 0; i < arr.length; i++){
				arr[i] = val;
			}
			var constant = this._context.createBufferSource();
			constant.channelCount = 1;
			constant.channelCountMode = "explicit";
			constant.buffer = buffer;
			constant.loop = true;
			constant.start(0);
			this._constants[val] = constant;
			return constant;
		}
	};

	/**
	 *  The private loop which keeps track of the context scheduled timeouts
	 *  Is invoked from the clock source
	 *  @private
	 */
	Tone.Context.prototype._timeoutLoop = function(){
		var now = this.now();
		while(this._timeouts && this._timeouts.length && this._timeouts.peek().time <= now){
			this._timeouts.shift().callback();
		}
	};

	/**
	 *  A setTimeout which is gaurenteed by the clock source.
	 *  Also runs in the offline context.
	 *  @param  {Function}  fn       The callback to invoke
	 *  @param  {Seconds}    timeout  The timeout in seconds
	 *  @returns {Number} ID to use when invoking Tone.Context.clearTimeout
	 */
	Tone.Context.prototype.setTimeout = function(fn, timeout){
		this._timeoutIds++;
		var now = this.now();
		this._timeouts.add({
			callback : fn,
			time : now + timeout,
			id : this._timeoutIds
		});
		return this._timeoutIds;
	};

	/**
	 *  Clears a previously scheduled timeout with Tone.context.setTimeout
	 *  @param  {Number}  id  The ID returned from setTimeout
	 *  @return  {Tone.Context}  this
	 */
	Tone.Context.prototype.clearTimeout = function(id){
		this._timeouts.forEach(function(event){
			if (event.id === id){
				this.remove(event);
			}
		});
		return this;
	};

	/**
	 *  This is the time that the clock is falling behind
	 *  the scheduled update interval. The Context automatically
	 *  adjusts for the lag and schedules further in advance.
	 *  @type {Number}
	 *  @memberOf Tone.Context
	 *  @name lag
	 *  @static
	 *  @readOnly
	 */
	Object.defineProperty(Tone.Context.prototype, "lag", {
		get : function(){
			var diff = this._computedUpdateInterval - this._updateInterval;
			diff = Math.max(diff, 0);
			return diff;
		}
	});

	/**
	 *  The amount of time in advance that events are scheduled.
	 *  The lookAhead will adjust slightly in response to the
	 *  measured update time to try to avoid clicks.
	 *  @type {Number}
	 *  @memberOf Tone.Context
	 *  @name lookAhead
	 *  @static
	 */
	Object.defineProperty(Tone.Context.prototype, "lookAhead", {
		get : function(){
			return this._lookAhead;
		},
		set : function(lA){
			this._lookAhead = lA;
		}
	});

	/**
	 *  How often the Web Worker callback is invoked.
	 *  This number corresponds to how responsive the scheduling
	 *  can be. Context.updateInterval + Context.lookAhead gives you the
	 *  total latency between scheduling an event and hearing it.
	 *  @type {Number}
	 *  @memberOf Tone.Context
	 *  @name updateInterval
	 *  @static
	 */
	Object.defineProperty(Tone.Context.prototype, "updateInterval", {
		get : function(){
			return this._updateInterval;
		},
		set : function(interval){
			this._updateInterval = Math.max(interval, Tone.blockTime);
			this._worker.postMessage(Math.max(interval * 1000, 1));
		}
	});

	/**
	 *  The type of playback, which affects tradeoffs between audio
	 *  output latency and responsiveness.
	 *
	 *  In addition to setting the value in seconds, the latencyHint also
	 *  accepts the strings "interactive" (prioritizes low latency),
	 *  "playback" (prioritizes sustained playback), "balanced" (balances
	 *  latency and performance), and "fastest" (lowest latency, might glitch more often).
	 *  @type {String|Seconds}
	 *  @memberOf Tone.Context#
	 *  @name latencyHint
	 *  @static
	 *  @example
	 * //set the lookAhead to 0.3 seconds
	 * Tone.context.latencyHint = 0.3;
	 */
	Object.defineProperty(Tone.Context.prototype, "latencyHint", {
		get : function(){
			return this._latencyHint;
		},
		set : function(hint){
			var lookAhead = hint;
			this._latencyHint = hint;
			if (Tone.isString(hint)){
				switch(hint){
					case "interactive" :
						lookAhead = 0.1;
						this._context.latencyHint = hint;
						break;
					case "playback" :
						lookAhead = 0.8;
						this._context.latencyHint = hint;
						break;
					case "balanced" :
						lookAhead = 0.25;
						this._context.latencyHint = hint;
						break;
					case "fastest" :
						this._context.latencyHint = "interactive";
						lookAhead = 0.01;
						break;
				}
			}
			this.lookAhead = lookAhead;
			this.updateInterval = lookAhead/3;
		}
	});

	/**
	 *  Clean up
	 *  @returns {Tone.Context} this
	 */
	Tone.Context.prototype.dispose = function(){
		Tone.Emitter.prototype.dispose.call(this);
		this._worker = null;
		this._timeouts.dispose();
		this._timeouts = null;
		for(var con in this._constants){
			this._constants[con].disconnect();
		}
		this._constants = null;
		this.close();
		return this;
	};

	/**
	 *  Shim all connect/disconnect and some deprecated methods which are still in
	 *  some older implementations.
	 *  @private
	 */
	function shimConnect(){

		var nativeConnect = AudioNode.prototype.connect;
		var nativeDisconnect = AudioNode.prototype.disconnect;

		//replace the old connect method
		function toneConnect(B, outNum, inNum){
			if (B.input){
				inNum = Tone.defaultArg(inNum, 0);
				if (Tone.isArray(B.input)){
					this.connect(B.input[inNum]);
				} else {
					this.connect(B.input, outNum, inNum);
				}
			} else {
				try {
					if (B instanceof AudioNode){
						nativeConnect.call(this, B, outNum, inNum);
					} else {
						nativeConnect.call(this, B, outNum);
					}
				} catch (e) {
					throw new Error("error connecting to node: "+B+"\n"+e);
				}
			}
		}

		//replace the old disconnect method
		function toneDisconnect(B, outNum, inNum){
			if (B && B.input && Tone.isArray(B.input)){
				inNum = Tone.defaultArg(inNum, 0);
				this.disconnect(B.input[inNum], outNum, 0);
			} else if (B && B.input){
				this.disconnect(B.input, outNum, inNum);
			} else {
				try {
					nativeDisconnect.apply(this, arguments);
				} catch (e) {
					throw new Error("error disconnecting node: "+B+"\n"+e);
				}
			}
		}

		if (AudioNode.prototype.connect !== toneConnect){
			AudioNode.prototype.connect = toneConnect;
			AudioNode.prototype.disconnect = toneDisconnect;
		}
	}

	// set the audio context initially
	if (Tone.supported){
		shimConnect();
		Tone.context = new Tone.Context();
	} else {
		console.warn("This browser does not support Tone.js");
	}

	return Tone.Context;
});<commit_msg>lookAhead is not static<commit_after>define(["Tone/core/Tone", "Tone/core/Emitter", "Tone/core/Timeline"], function (Tone) {

	/**
	 *  shim
	 *  @private
	 */
	if (!window.hasOwnProperty("AudioContext") && window.hasOwnProperty("webkitAudioContext")){
		window.AudioContext = window.webkitAudioContext;
	}

	/**
	 *  @class Wrapper around the native AudioContext.
	 *  @extends {Tone.Emitter}
	 *  @param {AudioContext=} context optionally pass in a context
	 */
	Tone.Context = function(context){

		Tone.Emitter.call(this);

		if (!context){
			context = new window.AudioContext();
		}
		this._context = context;
		// extend all of the methods
		for (var prop in this._context){
			this._defineProperty(this._context, prop);
		}

		/**
		 *  The default latency hint
		 *  @type  {String}
		 *  @private
		 */
		this._latencyHint = "interactive";

		/**
		 *  An object containing all of the constants AudioBufferSourceNodes
		 *  @type  {Object}
		 *  @private
		 */
		this._constants = {};

		///////////////////////////////////////////////////////////////////////
		// WORKER
		///////////////////////////////////////////////////////////////////////

		/**
		 *  The amount of time events are scheduled
		 *  into the future
		 *  @type  {Number}
		 *  @private
		 */
		this._lookAhead = 0.1;

		/**
		 *  How often the update look runs
		 *  @type  {Number}
		 *  @private
		 */
		this._updateInterval = this._lookAhead/3;

		/**
		 *  A reference to the actual computed update interval
		 *  @type  {Number}
		 *  @private
		 */
		this._computedUpdateInterval = 0;

		/**
		 *  The web worker which is used to update Tone.Clock
		 *  @private
		 *  @type  {WebWorker}
		 */
		this._worker = this._createWorker();

		///////////////////////////////////////////////////////////////////////
		// TIMEOUTS
		///////////////////////////////////////////////////////////////////////

		/**
		 *  All of the setTimeout events.
		 *  @type  {Tone.Timeline}
		 *  @private
		 */
		this._timeouts = new Tone.Timeline();

		/**
		 *  The timeout id counter
		 *  @private
		 *  @type {Number}
		 */
		this._timeoutIds = 0;

		this.on("tick", this._timeoutLoop.bind(this));

	};

	Tone.extend(Tone.Context, Tone.Emitter);
	Tone.Emitter.mixin(Tone.Context);

	/**
	 *  Define a property on this Tone.Context.
	 *  This is used to extend the native AudioContext
	 *  @param  {AudioContext}  context
	 *  @param  {String}  prop
	 *  @private
	 */
	Tone.Context.prototype._defineProperty = function(context, prop){
		if (Tone.isUndef(this[prop])){
			Object.defineProperty(this, prop, {
				get : function(){
					if (typeof context[prop] === "function"){
						return context[prop].bind(context);
					} else {
						return context[prop];
					}
				},
				set : function(val){
					context[prop] = val;
				}
			});
		}
	};

	/**
	 *  The current audio context time
	 *  @return  {Number}
	 */
	Tone.Context.prototype.now = function(){
		return this._context.currentTime;
	};

	/**
	 *  Generate a web worker
	 *  @return  {WebWorker}
	 *  @private
	 */
	Tone.Context.prototype._createWorker = function(){

		//URL Shim
		window.URL = window.URL || window.webkitURL;

		var blob = new Blob([
			//the initial timeout time
			"var timeoutTime = "+(this._updateInterval * 1000).toFixed(1)+";" +
			//onmessage callback
			"self.onmessage = function(msg){" +
			"	timeoutTime = parseInt(msg.data);" +
			"};" +
			//the tick function which posts a message
			//and schedules a new tick
			"function tick(){" +
			"	setTimeout(tick, timeoutTime);" +
			"	self.postMessage('tick');" +
			"}" +
			//call tick initially
			"tick();"
		]);
		var blobUrl = URL.createObjectURL(blob);
		var worker = new Worker(blobUrl);

		worker.addEventListener("message", function(){
			// tick the clock
			this.emit("tick");
		}.bind(this));

		//lag compensation
		worker.addEventListener("message", function(){
			var now = this.now();
			if (Tone.isNumber(this._lastUpdate)){
				var diff = now - this._lastUpdate;
				this._computedUpdateInterval = Math.max(diff, this._computedUpdateInterval * 0.97);
			}
			this._lastUpdate = now;
		}.bind(this));

		return worker;
	};

	/**
	 *  Generate a looped buffer at some constant value.
	 *  @param  {Number}  val
	 *  @return  {BufferSourceNode}
	 */
	Tone.Context.prototype.getConstant = function(val){
		if (this._constants[val]){
			return this._constants[val];
		} else {
			var buffer = this._context.createBuffer(1, 128, this._context.sampleRate);
			var arr = buffer.getChannelData(0);
			for (var i = 0; i < arr.length; i++){
				arr[i] = val;
			}
			var constant = this._context.createBufferSource();
			constant.channelCount = 1;
			constant.channelCountMode = "explicit";
			constant.buffer = buffer;
			constant.loop = true;
			constant.start(0);
			this._constants[val] = constant;
			return constant;
		}
	};

	/**
	 *  The private loop which keeps track of the context scheduled timeouts
	 *  Is invoked from the clock source
	 *  @private
	 */
	Tone.Context.prototype._timeoutLoop = function(){
		var now = this.now();
		while(this._timeouts && this._timeouts.length && this._timeouts.peek().time <= now){
			this._timeouts.shift().callback();
		}
	};

	/**
	 *  A setTimeout which is gaurenteed by the clock source.
	 *  Also runs in the offline context.
	 *  @param  {Function}  fn       The callback to invoke
	 *  @param  {Seconds}    timeout  The timeout in seconds
	 *  @returns {Number} ID to use when invoking Tone.Context.clearTimeout
	 */
	Tone.Context.prototype.setTimeout = function(fn, timeout){
		this._timeoutIds++;
		var now = this.now();
		this._timeouts.add({
			callback : fn,
			time : now + timeout,
			id : this._timeoutIds
		});
		return this._timeoutIds;
	};

	/**
	 *  Clears a previously scheduled timeout with Tone.context.setTimeout
	 *  @param  {Number}  id  The ID returned from setTimeout
	 *  @return  {Tone.Context}  this
	 */
	Tone.Context.prototype.clearTimeout = function(id){
		this._timeouts.forEach(function(event){
			if (event.id === id){
				this.remove(event);
			}
		});
		return this;
	};

	/**
	 *  This is the time that the clock is falling behind
	 *  the scheduled update interval. The Context automatically
	 *  adjusts for the lag and schedules further in advance.
	 *  @type {Number}
	 *  @memberOf Tone.Context
	 *  @name lag
	 *  @static
	 *  @readOnly
	 */
	Object.defineProperty(Tone.Context.prototype, "lag", {
		get : function(){
			var diff = this._computedUpdateInterval - this._updateInterval;
			diff = Math.max(diff, 0);
			return diff;
		}
	});

	/**
	 *  The amount of time in advance that events are scheduled.
	 *  The lookAhead will adjust slightly in response to the
	 *  measured update time to try to avoid clicks.
	 *  @type {Number}
	 *  @memberOf Tone.Context
	 *  @name lookAhead
	 */
	Object.defineProperty(Tone.Context.prototype, "lookAhead", {
		get : function(){
			return this._lookAhead;
		},
		set : function(lA){
			this._lookAhead = lA;
		}
	});

	/**
	 *  How often the Web Worker callback is invoked.
	 *  This number corresponds to how responsive the scheduling
	 *  can be. Context.updateInterval + Context.lookAhead gives you the
	 *  total latency between scheduling an event and hearing it.
	 *  @type {Number}
	 *  @memberOf Tone.Context
	 *  @name updateInterval
	 *  @static
	 */
	Object.defineProperty(Tone.Context.prototype, "updateInterval", {
		get : function(){
			return this._updateInterval;
		},
		set : function(interval){
			this._updateInterval = Math.max(interval, Tone.blockTime);
			this._worker.postMessage(Math.max(interval * 1000, 1));
		}
	});

	/**
	 *  The type of playback, which affects tradeoffs between audio
	 *  output latency and responsiveness.
	 *
	 *  In addition to setting the value in seconds, the latencyHint also
	 *  accepts the strings "interactive" (prioritizes low latency),
	 *  "playback" (prioritizes sustained playback), "balanced" (balances
	 *  latency and performance), and "fastest" (lowest latency, might glitch more often).
	 *  @type {String|Seconds}
	 *  @memberOf Tone.Context#
	 *  @name latencyHint
	 *  @static
	 *  @example
	 * //set the lookAhead to 0.3 seconds
	 * Tone.context.latencyHint = 0.3;
	 */
	Object.defineProperty(Tone.Context.prototype, "latencyHint", {
		get : function(){
			return this._latencyHint;
		},
		set : function(hint){
			var lookAhead = hint;
			this._latencyHint = hint;
			if (Tone.isString(hint)){
				switch(hint){
					case "interactive" :
						lookAhead = 0.1;
						this._context.latencyHint = hint;
						break;
					case "playback" :
						lookAhead = 0.8;
						this._context.latencyHint = hint;
						break;
					case "balanced" :
						lookAhead = 0.25;
						this._context.latencyHint = hint;
						break;
					case "fastest" :
						this._context.latencyHint = "interactive";
						lookAhead = 0.01;
						break;
				}
			}
			this.lookAhead = lookAhead;
			this.updateInterval = lookAhead/3;
		}
	});

	/**
	 *  Clean up
	 *  @returns {Tone.Context} this
	 */
	Tone.Context.prototype.dispose = function(){
		Tone.Emitter.prototype.dispose.call(this);
		this._worker = null;
		this._timeouts.dispose();
		this._timeouts = null;
		for(var con in this._constants){
			this._constants[con].disconnect();
		}
		this._constants = null;
		this.close();
		return this;
	};

	/**
	 *  Shim all connect/disconnect and some deprecated methods which are still in
	 *  some older implementations.
	 *  @private
	 */
	function shimConnect(){

		var nativeConnect = AudioNode.prototype.connect;
		var nativeDisconnect = AudioNode.prototype.disconnect;

		//replace the old connect method
		function toneConnect(B, outNum, inNum){
			if (B.input){
				inNum = Tone.defaultArg(inNum, 0);
				if (Tone.isArray(B.input)){
					this.connect(B.input[inNum]);
				} else {
					this.connect(B.input, outNum, inNum);
				}
			} else {
				try {
					if (B instanceof AudioNode){
						nativeConnect.call(this, B, outNum, inNum);
					} else {
						nativeConnect.call(this, B, outNum);
					}
				} catch (e) {
					throw new Error("error connecting to node: "+B+"\n"+e);
				}
			}
		}

		//replace the old disconnect method
		function toneDisconnect(B, outNum, inNum){
			if (B && B.input && Tone.isArray(B.input)){
				inNum = Tone.defaultArg(inNum, 0);
				this.disconnect(B.input[inNum], outNum, 0);
			} else if (B && B.input){
				this.disconnect(B.input, outNum, inNum);
			} else {
				try {
					nativeDisconnect.apply(this, arguments);
				} catch (e) {
					throw new Error("error disconnecting node: "+B+"\n"+e);
				}
			}
		}

		if (AudioNode.prototype.connect !== toneConnect){
			AudioNode.prototype.connect = toneConnect;
			AudioNode.prototype.disconnect = toneDisconnect;
		}
	}

	// set the audio context initially
	if (Tone.supported){
		shimConnect();
		Tone.context = new Tone.Context();
	} else {
		console.warn("This browser does not support Tone.js");
	}

	return Tone.Context;
});<|endoftext|>


<commit_before>/* globals FormData, Promise, Vue */
// define
var FileUploadComponent = Vue.extend({
  template: '
<input type="file" name="{{ name }}" id="{{ id || name }}" accept="{{ accept }}" v-on:click="fileInputClick" v-on:change="fileInputChange" multiple="{{ multiple }}"><slot></slot><button type="button" v-on:click="fileUpload">Upload</button>
',
  props: {
    class: String,
    name: {
      type: String,
      required: true
    },
    id: String,
    action: {
      type: String,
      required: true
    },
    accept: String,
    multiple: String,
    headers: Object
  },
  data: function() {
    return {
      myFiles: [] // a container for the files in our field
    };
  },
  methods: {
    fileInputClick: function() {
      // click actually triggers after the file dialog opens
      this.$dispatch('onFileClick', this.myFiles);
    },
    fileInputChange: function() {
      // get the group of files assigned to this field
      var ident = this.id || this.name
      this.myFiles = document.getElementById(ident).files;
      this.$dispatch('onFileChange', this.myFiles);
    },
    _onProgress: function(e) {
      // this is an internal call in XHR to update the progress
      e.percent = (e.loaded / e.total) * 100;
      this.$dispatch('onFileProgress', e);
    },
    _handleUpload: function(file) {
      this.$dispatch('beforeFileUpload', file);
      var form = new FormData();
      var xhr = new XMLHttpRequest();
      try {
        form.append('Content-Type', file.type || 'application/octet-stream');
        // our request will have the file in the ['file'] key
        form.append('file', file);
      } catch (err) {
        this.$dispatch('onFileError', file, err);
        return;
      }

      return new Promise(function(resolve, reject) {

        xhr.upload.addEventListener('progress', this._onProgress, false);

        xhr.onreadystatechange = function() {
          if (xhr.readyState < 4) {
            return;
          }
          if (xhr.status < 400) {
            var res = JSON.parse(xhr.responseText);
            this.$dispatch('onFileUpload', file, res);
            resolve(file);
          } else {
            var err = new Error(xhr.responseText);
            err.status = xhr.status;
            err.statusText = xhr.statusText;
            this.$dispatch('onFileError', file, err);
            reject(err);
          }
        }.bind(this);

        xhr.onerror = function() {
          var err = new Error(xhr.responseText);
          err.status = xhr.status;
          err.statusText = xhr.statusText;
          this.$dispatch('onFileError', file, err);
          reject(err);
        }.bind(this);

        xhr.open('POST', this.action, true);
        if (this.headers) {
          for(var header in this.headers) {
            xhr.setRequestHeader(header, this.headers[header]);
          }
        }
        xhr.send(form);
        this.$dispatch('afterFileUpload', file);
      }.bind(this));
    },
    fileUpload: function() {
      if(this.myFiles.length > 0) {
        // a hack to push all the Promises into a new array
        var arrayOfPromises = Array.prototype.slice.call(this.myFiles, 0).map(function(file) {
          return this._handleUpload(file);
        }.bind(this));
        // wait for everything to finish
        Promise.all(arrayOfPromises).then(function(allFiles) {
          this.$dispatch('onAllFilesUploaded', allFiles);
        }.bind(this)).catch(function(err) {
          this.$dispatch('onFileError', this.myFiles, err);
        }.bind(this));
      } else {
        // someone tried to upload without adding files
        var err = new Error("No files to upload for this field");
        this.$dispatch('onFileError', this.myFiles, err);
      }
    }
  }
});

// register
Vue.component('file-upload', FileUploadComponent);<commit_msg>when an error is thrown, return json in the error, not an Error object<commit_after>/* globals FormData, Promise, Vue */
// define
var FileUploadComponent = Vue.extend({
  template: '
<input type="file" name="{{ name }}" id="{{ id || name }}" accept="{{ accept }}" v-on:click="fileInputClick" v-on:change="fileInputChange" multiple="{{ multiple }}"><slot></slot><button type="button" v-on:click="fileUpload">Upload</button>
',
  props: {
    class: String,
    name: {
      type: String,
      required: true
    },
    id: String,
    action: {
      type: String,
      required: true
    },
    accept: String,
    multiple: String,
    headers: Object
  },
  data: function() {
    return {
      myFiles: [] // a container for the files in our field
    };
  },
  methods: {
    fileInputClick: function() {
      // click actually triggers after the file dialog opens
      this.$dispatch('onFileClick', this.myFiles);
    },
    fileInputChange: function() {
      // get the group of files assigned to this field
      var ident = this.id || this.name
      this.myFiles = document.getElementById(ident).files;
      this.$dispatch('onFileChange', this.myFiles);
    },
    _onProgress: function(e) {
      // this is an internal call in XHR to update the progress
      e.percent = (e.loaded / e.total) * 100;
      this.$dispatch('onFileProgress', e);
    },
    _handleUpload: function(file) {
      this.$dispatch('beforeFileUpload', file);
      var form = new FormData();
      var xhr = new XMLHttpRequest();
      try {
        form.append('Content-Type', file.type || 'application/octet-stream');
        // our request will have the file in the ['file'] key
        form.append('file', file);
      } catch (err) {
        this.$dispatch('onFileError', file, err);
        return;
      }

      return new Promise(function(resolve, reject) {

        xhr.upload.addEventListener('progress', this._onProgress, false);

        xhr.onreadystatechange = function() {
          if (xhr.readyState < 4) {
            return;
          }
          if (xhr.status < 400) {
            var res = JSON.parse(xhr.responseText);
            this.$dispatch('onFileUpload', file, res);
            resolve(file);
          } else {
            var err = JSON.parse(xhr.responseText);
            err.status = xhr.status;
            err.statusText = xhr.statusText;
            this.$dispatch('onFileError', file, err);
            reject(err);
          }
        }.bind(this);

        xhr.onerror = function() {
          var err = JSON.parse(xhr.responseText);
          err.status = xhr.status;
          err.statusText = xhr.statusText;
          this.$dispatch('onFileError', file, err);
          reject(err);
        }.bind(this);

        xhr.open('POST', this.action, true);
        if (this.headers) {
          for(var header in this.headers) {
            xhr.setRequestHeader(header, this.headers[header]);
          }
        }
        xhr.send(form);
        this.$dispatch('afterFileUpload', file);
      }.bind(this));
    },
    fileUpload: function() {
      if(this.myFiles.length > 0) {
        // a hack to push all the Promises into a new array
        var arrayOfPromises = Array.prototype.slice.call(this.myFiles, 0).map(function(file) {
          return this._handleUpload(file);
        }.bind(this));
        // wait for everything to finish
        Promise.all(arrayOfPromises).then(function(allFiles) {
          this.$dispatch('onAllFilesUploaded', allFiles);
        }.bind(this)).catch(function(err) {
          this.$dispatch('onFileError', this.myFiles, err);
        }.bind(this));
      } else {
        // someone tried to upload without adding files
        var err = new Error("No files to upload for this field");
        this.$dispatch('onFileError', this.myFiles, err);
      }
    }
  }
});

// register
Vue.component('file-upload', FileUploadComponent);<|endoftext|>


<commit_before>import React, {Component} from 'react';
import Dialog from 'react-toolbox/lib/dialog/Dialog'
import Tooltip from 'react-toolbox/lib/tooltip'
import Icon from 'react-toolbox/lib/font_icon/FontIcon'

const TooltipIcon = Tooltip(Icon);

class ConfirmDeleteButton extends Component {
  propTypes = {
    onDelete: React.PropTypes.func.isRequired,
    tooltip: React.PropTypes.string,
    title: React.PropTypes.string
  }
  state = {
    confirmationPopup: false
  }
  open(ev) {
    ev.preventDefault();
    ev.stopPropagation();
    this.setState({ confirmationPopup: true })
  }
  close() {
    this.setState({ confirmationPopup: false })
  }
  render() {
    const {tooltip, title} = this.props;
    return (

        <TooltipIcon
          tooltip={tooltip || "Borrar"}
          value="clear"
          style={{color: '#757575'}}
          onClick={(ev) => this.open(ev)}
        />
        <Dialog
          active={this.state.confirmationPopup}
          onEscKeyDown={() => this.close()}
          onOverlayClick={() => this.close()}
          title={title || "Confirmar borrado"}
          actions={[
            {label: 'Si', primary: true, onClick: () => {
              this.close();
              this.props.onDelete();
            }},
            {label: 'No', onClick: () => this.close()}
          ]}
        >
¿Está seguro?
</Dialog>

    );
  }
}

export default ConfirmDeleteButton;
<commit_msg>fix: propTypes warning<commit_after>import React, {Component} from 'react';
import Dialog from 'react-toolbox/lib/dialog/Dialog'
import Tooltip from 'react-toolbox/lib/tooltip'
import Icon from 'react-toolbox/lib/font_icon/FontIcon'

const TooltipIcon = Tooltip(Icon);

class ConfirmDeleteButton extends Component {
  static propTypes = {
    onDelete: React.PropTypes.func.isRequired,
    tooltip: React.PropTypes.string,
    title: React.PropTypes.string
  }
  state = {
    confirmationPopup: false
  }
  open(ev) {
    ev.preventDefault();
    ev.stopPropagation();
    this.setState({ confirmationPopup: true })
  }
  close() {
    this.setState({ confirmationPopup: false })
  }
  render() {
    const {tooltip, title} = this.props;
    return (

        <TooltipIcon
          tooltip={tooltip || "Borrar"}
          value="clear"
          style={{color: '#757575'}}
          onClick={(ev) => this.open(ev)}
        />
        <Dialog
          active={this.state.confirmationPopup}
          onEscKeyDown={() => this.close()}
          onOverlayClick={() => this.close()}
          title={title || "Confirmar borrado"}
          actions={[
            {label: 'Si', primary: true, onClick: () => {
              this.close();
              this.props.onDelete();
            }},
            {label: 'No', onClick: () => this.close()}
          ]}
        >
¿Está seguro?
</Dialog>

    );
  }
}

export default ConfirmDeleteButton;
<|endoftext|>


<commit_before>/*
 * grunt-jstestdriver
 * https://github.com/rickyclegg/grunt-jstestdriver
 *
 * Copyright (c) 2013 Ricky Clegg
 * Licensed under the MIT license.
 */
'use strict';
module.exports = function (grunt) {

    var INVALID_FLAGS = ['browser', 'config', 'dryRunFor', 'port', 'server', 'serverHandlerPrefix', 'canFail'];

    grunt.registerTask('jstestdriver', 'Grunt task for uniting testing using JS Test Driver.', function () {

        var options = this.options({
                tests: 'all',
                canFail: false
            }),
            config = grunt.config.get('jstestdriver'),
            done = this.async(),
            numberOfConfigs,
            numberOfPassedTests = 0,
            numberOfFailedTests = 0,
            failedTests = [];

        grunt.verbose.writeflags(options, 'Options');

        function taskComplete() {
            if (!options.canFail && failedTests.length > 0) {
                grunt.fail.fatal(failedTests.join('\n\n'));
                done(false);
            } else {
                grunt.log.ok('Total Passed: ' +
                    numberOfPassedTests + ', Fails: ' + numberOfFailedTests);
                done();
            }
        }

        function runJSTestDriver(configFileLocation, options) {
            var cp;

            function setNumberOfPassesAndFails(result) {
                var resultAsStr = result.toString(),
                    passedReg = /\d+(?=;\sFails)/,
                    failsReg = /\d+(?=;\sErrors)/;

                if (resultAsStr && resultAsStr.indexOf('RuntimeException') === -1) {
                    numberOfPassedTests += parseInt(passedReg.exec(resultAsStr)[0], 10);
                    numberOfFailedTests += parseInt(failsReg.exec(resultAsStr)[0], 10);
                } else {
                    grunt.fail.fatal('Did you start your server?\n' + resultAsStr);
                }
            }

            function hasFailedTests(result) {
                var prop, resultStr = "";

                for (prop in result) {
                    if (result.hasOwnProperty(prop)) {
                        resultStr += result[prop];
                    }
                }

                return resultStr.indexOf("Error:") > -1;
            }

            function processCompleteTests() {
                grunt.log.verbose.writeln('>> Finished running file: ' + configFileLocation);
                grunt.log.verbose.writeln('');

                numberOfConfigs -= 1;
                if (numberOfConfigs === 0) {
                    taskComplete();
                }
            }

            function processed(error, result) {
                setNumberOfPassesAndFails(result);

                if (error || hasFailedTests(result)) {
                    failedTests.push(result);
                    grunt.verbose.writeln('   ONE or MORE tests have failed in:');
                } else {
                    grunt.verbose.writeln(result);
                }

                processCompleteTests();
            }

            function getOptionsArray(options) {
                var names, name, i, l, arr = [];

                names = Object.getOwnPropertyNames(options);
                l = names.length;
                for (i = 0; i < l; i += 1) {
                    name = names[i];

                    if (INVALID_FLAGS.indexOf(name) === -1) {
                        arr.push("--" + name);
                        arr.push(options[name]);
                    } else {
                        if (name !== 'canFail') {
                            grunt.verbose.writeln('WARNING - ' +
                                name + ' is not a valid config for use with the grunt-jstestdriver!');
                        }
                    }
                }

                return arr;
            }

            cp = grunt.util.spawn({
                cmd: 'java',
                args: ["-jar",
                       __dirname + '/../lib/jstestdriver.jar',
                       "--config",
                       configFileLocation].concat(getOptionsArray(options))
            }, processed);

            if (grunt.option('verbose')) {
                cp.stdout.pipe(process.stdout);
                cp.stderr.pipe(process.stderr);
            }
        }

        if (typeof config.files === 'string') {
            config.files = [config.files];
        }

        if (options.testOutput) {
            grunt.file.mkdir(options.testOutput);
        }

        numberOfConfigs = config.files.length;

        grunt.util.async.forEach(config.files, function (filename) {
            runJSTestDriver(filename, options);
        }.bind(this));
    });

};
<commit_msg>tasks now runs server, attaches phantom instance AND runs tests before exiting<commit_after>/*
 * grunt-jstestdriver
 * https://github.com/rickyclegg/grunt-jstestdriver
 *
 * Copyright (c) 2013 Ricky Clegg
 * Licensed under the MIT license.
 */
'use strict';
module.exports = function (grunt) {

    var INVALID_FLAGS = ['browser', 'config', 'dryRunFor', 'port', 'server', 'serverHandlerPrefix', 'canFail'];

    // npm lib
    var phantomjs = require('grunt-lib-phantomjs').init(grunt);

    grunt.registerTask('jstestdriver', 'Grunt task for unit testing using JS Test Driver.', function () {

        var options = this.options({
                tests: 'all'
            }),
            config = grunt.config.get('jstestdriver'),
            done = this.async(),
            numberOfConfigs,
            numberOfPassedTests = 0,
            numberOfFailedTests = 0,
            failedTests = [];

        grunt.verbose.writeflags(options, 'Options');

        function taskComplete() {

            grunt.log.writeln('');
            grunt.log.ok('Total Passed: ' + numberOfPassedTests + ', Fails: ' + numberOfFailedTests);

            if (failedTests.length > 0) {
                //grunt.fail.fatal(failedTests.join('\n\n'));
                done(false);
            } else {
                done();
            }
        }

        function runJSTestDriver(configFileLocation, options) {
            var cp;

            function setNumberOfPassesAndFails(result) {
                var resultAsStr = result.toString(),
                    passedReg = /\d+(?=;\sFails)/,
                    failsReg = /\d+(?=;\sErrors)/;

                if (resultAsStr && resultAsStr.indexOf('RuntimeException') === -1) {
                    numberOfPassedTests += parseInt(passedReg.exec(resultAsStr)[0], 10);
                    numberOfFailedTests += parseInt(failsReg.exec(resultAsStr)[0], 10);
                }
            }

            function hasFailedTests(result) {
                var prop, resultStr = "";

                for (prop in result) {
                    if (result.hasOwnProperty(prop)) {
                        resultStr += result[prop];
                    }
                }

                return resultStr.indexOf("Error:") > -1;
            }

            function processCompleteTests() {
                grunt.log.verbose.writeln('>> Finished running file: ' + configFileLocation);
                grunt.log.verbose.writeln('');

                numberOfConfigs -= 1;
                if (numberOfConfigs === 0) {
                    taskComplete();
                }
            }

            function onTestRunComplete(error, result) {

                setNumberOfPassesAndFails(result.stdout);

                if (error || hasFailedTests(result)) {
                    failedTests.push(result);
                    grunt.verbose.writeln('   ONE or MORE tests have failed in:');
                } else {
                    grunt.verbose.writeln(result);
                }

                processCompleteTests();
            }

            function getOptionsArray(options) {
                var names, name, i, l, arr = [];

                names = Object.getOwnPropertyNames(options);
                l = names.length;
                for (i = 0; i < l; i += 1) {
                    name = names[i];

                    if (INVALID_FLAGS.indexOf(name) === -1) {
                        arr.push("--" + name);
                        arr.push(options[name]);
                    } else {
                        grunt.verbose.writeln('WARNING - ' +
                            name + ' is not a valid config for use with the grunt-jstestdriver!');
                    }
                }

                return arr;
            }

            var jarFile = __dirname + '\\..\\lib\\jstestdriver.jar';
            var jstdCmd = {
                cmd: 'java',
                args: ["-jar",
                       jarFile,
                       "--config",
                       configFileLocation,
                       '--reset',
                       '--server',
                       'http://localhost:4224'].concat(getOptionsArray(options))
            };

            grunt.log.writeln('Starting jstd server...\n');
            var server = grunt.util.spawn({
                cmd: 'java',
                args: [
                    "-jar",
                    jarFile,
                    "--port",
                    "4224"
                ]
            }, function(error, result, code){
                grunt.verbose.writeln(error);
            });

            function itDidntWork (msg) {
                grunt.log.writeln(msg);
                done(false);
            }

            function initPhantom (callback) {
                grunt.log.writeln("Starting PhantomJS...");

                var gotHeartbeat = false;
                phantomjs.on('onResourceReceived', function(request){

                    if(/\/capture$/.test(request.url) && request.status == 404){
                        itDidntWork('server did not respond');
                    }
                    if(/\/heartbeat$/.test(request.url) && !gotHeartbeat){
                        gotHeartbeat = true;
                        callback();
                    }

                });

                phantomjs.spawn("http://localhost:4224/capture", { options: {} });
            }

            function startTestRunner () {
                grunt.log.writeln("Running tests...\n");
                cp = grunt.util.spawn(jstdCmd, onTestRunComplete);
                cp.stdout.pipe(process.stdout);
                cp.stderr.pipe(process.stderr);
            }

            setTimeout(function(){

                if (!server.killed && !server.exitCode) {

                    initPhantom(startTestRunner);

                } else {
                    itDidntWork('failed to start server');
                }
            }, 5000);
        }

        if (typeof config.files === 'string') {
            config.files = [config.files];
        }

        if (options.testOutput) {
            grunt.file.mkdir(options.testOutput);
        }

        numberOfConfigs = config.files.length;

        grunt.util.async.forEach(config.files, function (filename) {
            runJSTestDriver(filename, options);
        }.bind(this));
    });

};
<|endoftext|>