<commit_before>/**
 * @fileOverview Transport
 * @todo 支持chunked传输，优势：
 * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，
 * 而不需要重头再传一次。另外断点续传也需要用chunked方式。
 */
define( 'webuploader/core/runtime/html5/transport', [ 'webuploader/base',
        'webuploader/core/runtime/html5/runtime'
        ], function( Base, Html5Runtime ) {

    var $ = Base.$,
        noop = Base.noop,
        defaultOpts = {
            server: '',

            // 跨域时，是否允许携带cookie
            withCredentials: false,
            fileVar: 'file',
            chunked: true,
            chunkSize: 1024 * 512,    // 0.5M.
            chunkRetryCount: 3,    // 当chunk传输时出错，可以重试3次。
            timeout: 2 * 60 * 1000,    // 2分钟
            formData: {},
            headers: {}
        };

    function Transport( opts ) {
        opts = this.options = $.extend( true, {}, defaultOpts, opts || {} );
    }

    $.extend( Transport.prototype, {
        state: 'pending',

        // @todo ie支持
        _initAjax: function() {
            var me = this,
                opts = me.options,
                xhr = new XMLHttpRequest();

            if ( !('withCredentials' in xhr) &&
                    typeof XDomainRequest !== 'undefined' ) {
                xhr = new XDomainRequest();
            }

            xhr.upload.onprogress = function( e ) {
                var percentage = 0;

                if ( e.lengthComputable ) {
                    percentage = e.loaded / e.total;
                }

                return me._onprogress.call( me, percentage );
            };

            xhr.onreadystatechange = function() {
                var ret, rHeaders, reject;

                if ( xhr.readyState !== 4 ) {
                    return;
                }

                xhr.upload.onprogress = noop;
                xhr.onreadystatechange = noop;
                clearTimeout( me.timoutTimer );
                me._xhr = null;

                // 只考虑200的情况
                if ( xhr.status === 200 ) {
                    ret = me._parseResponse( xhr.responseText );
                    ret._raw = xhr.responseText;
                    rHeaders = me._getXhrHeaders( xhr );

                    // 说明server端返回的数据有问题。
                    if ( !me.trigger( 'accept', ret, rHeaders, function( val ) {
                        reject = val;
                    } ) ) {
                        reject = reject || 'server';
                    } else {
                        return me._onsuccess.call( me, ret, rHeaders );
                    }
                }

                reject = reject || (xhr.status ? 'http' : 'timeout');
                return me._reject( reject );
            };

            return me._xhr = xhr;
        },

        _onprogress: function( percentage ) {
            var opts = this.options,
                start, end, total;

            if ( this.chunks ) {
                total = this._blob.size;
                start = this.chunk * opts.chunkSize;
                end = Math.min( start + opts.chunkSize, total );

                percentage = (start + percentage * (end -start)) / total;
            }

            this._notify( percentage );
        },

        _onsuccess: function( ret, headers ) {
            if ( this.chunks && this.chunk < this.chunks - 1 ) {
                this.chunk++;
                this._upload();
            } else {
                this._resolve( ret, headers );
            }
        },

        _notify: function( percentage ) {
            this.trigger( 'progress', percentage || 0 );
        },

        _resolve: function( ret, headers ) {
            this.state = 'done';
            this.trigger( 'success', ret, headers );
            this.trigger( 'complete' );
        },

        _reject: function( reason ) {
            // @todo
            // 如果是timeout abort, 在chunk传输模式中应该自动重传。
            // chunkRetryCount = 3;
            this.state = 'fail';
            this.trigger( 'error', reason );
            this.trigger( 'complete' );
        },

        _setRequestHeader: function( xhr, headers ) {
            $.each( headers, function( key, val ) {
                xhr.setRequestHeader( key, val );
            } );
        },

        _getXhrHeaders: function( xhr ) {
            var str = xhr.getAllResponseHeaders(),
                ret = {},
                match;

            $.each( str.split( /\n/ ), function( i, str ) {
                match = /^(.*?): (.*)$/.exec( str );

                if ( match ) {
                    ret[ match[ 1 ] ] = match[ 2 ];
                }
            } );

            return ret;
        },

        _parseResponse: function( json ) {
            var ret;

            try {
                ret = JSON.parse( json );
            } catch ( ex ) {
                ret = {};
            }

            return ret;
        },

        _upload: function() {
            if ( this.paused ) {
                return this;
            }

            var opts = this.options,
                xhr = this._initAjax(),
                formData = new FormData(),
                blob = this._blob,
                slice = blob.slice || blob.webkitSlice || blob.mozSlice,
                start, end;

            if ( this.chunks ) {
                start = this.chunk * opts.chunkSize;
                end = Math.min( blob.size, start + opts.chunkSize );

                blob = slice.call( blob, start, end );
                opts.formData.chunk = this.chunk;
                opts.formData.chunks = this.chunks;

                start === 0 &&
                        xhr.overrideMimeType( 'application/octet-stream' );
            }

            // 外部可以在这个时机中添加其他信息
            this.trigger( 'beforeSend', opts.formData, opts.headers, xhr );

            $.each( opts.formData, function( key, val ) {
                formData.append( key, val );
            } );

            formData.append( opts.fileVar, blob, opts.formData &&
                    opts.formData.name || '' );

            if ( opts.withCredentials && 'withCredentials' in xhr ) {
                xhr.withCredentials = true;
                xhr.open( 'POST', opts.server, true );
            } else {
                xhr.open( 'POST', opts.server );
            }

            this._setRequestHeader( xhr, opts.headers );

            if ( opts.timeout ) {
                this.timoutTimer = setTimeout(function() {
                    xhr.abort();
                }, opts.timeout );
            }

            xhr.send( formData );
            this.state = 'progress';
            return this;
        },

        pause: function() {
            if ( this.paused ) {
                return;
            }

            this.paused = true;

            if ( this._xhr ) {
                this._xhr.upload.onprogress = noop;
                this._xhr.onreadystatechange = noop;
                clearTimeout( this.timoutTimer );
                this._xhr.abort();
                this._onprogress( 0 );
            }
        },

        resume: function() {
            if ( !this.paused ) {
                return;
            }

            this.paused = false;
            this._upload();
        },

        cancel: function() {
            if ( this._xhr ) {
                this._xhr.upload.onprogress = noop;
                this._xhr.onreadystatechange = noop;
                clearTimeout( this.timoutTimer );
                this._xhr.abort();
                this._xhr = null;
            }
        },

        /**
         * 以Blob的方式发送数据到服务器
         * @method sendAsBlob
         * @param {Blob} blob Blob数据
         * @return {Transport} 返回实例自己，便于链式调用。
         * @chainable
         */
        sendAsBlob: function( blob ) {
            var opts = this.options;

            if ( opts.chunked && blob.size > opts.chunkSize ) {
                this.chunk = 0;
                this.chunks = Math.ceil( blob.size / opts.chunkSize );
            }

            this._blob = blob;

            this._upload();
            this._notify( 0 );
            return this;
        },

        destroy: function() {
            this._blob = null;
        }

    } );

    // 静态方法直接发送内容。
    Transport.sendAsBlob = function( blob, options ) {
        var instance = new Transport( options );
        instance.sendAsBlob( blob );
        return instance;
    };

    Html5Runtime.register( 'Transport', Transport );
} );<commit_msg>修复withCredentials ie10报错问题<commit_after>/**
 * @fileOverview Transport
 * @todo 支持chunked传输，优势：
 * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，
 * 而不需要重头再传一次。另外断点续传也需要用chunked方式。
 */
define( 'webuploader/core/runtime/html5/transport', [ 'webuploader/base',
        'webuploader/core/runtime/html5/runtime'
        ], function( Base, Html5Runtime ) {

    var $ = Base.$,
        noop = Base.noop,
        defaultOpts = {
            server: '',

            // 跨域时，是否允许携带cookie
            withCredentials: false,
            fileVar: 'file',
            chunked: true,
            chunkSize: 1024 * 512,    // 0.5M.
            chunkRetryCount: 3,    // 当chunk传输时出错，可以重试3次。
            timeout: 2 * 60 * 1000,    // 2分钟
            formData: {},
            headers: {}
        };

    function Transport( opts ) {
        opts = this.options = $.extend( true, {}, defaultOpts, opts || {} );
    }

    $.extend( Transport.prototype, {
        state: 'pending',

        // @todo ie支持
        _initAjax: function() {
            var me = this,
                opts = me.options,
                xhr = new XMLHttpRequest();

            if ( !('withCredentials' in xhr) &&
                    typeof XDomainRequest !== 'undefined' ) {
                xhr = new XDomainRequest();
            }

            xhr.upload.onprogress = function( e ) {
                var percentage = 0;

                if ( e.lengthComputable ) {
                    percentage = e.loaded / e.total;
                }

                return me._onprogress.call( me, percentage );
            };

            xhr.onreadystatechange = function() {
                var ret, rHeaders, reject;

                if ( xhr.readyState !== 4 ) {
                    return;
                }

                xhr.upload.onprogress = noop;
                xhr.onreadystatechange = noop;
                clearTimeout( me.timoutTimer );
                me._xhr = null;

                // 只考虑200的情况
                if ( xhr.status === 200 ) {
                    ret = me._parseResponse( xhr.responseText );
                    ret._raw = xhr.responseText;
                    rHeaders = me._getXhrHeaders( xhr );

                    // 说明server端返回的数据有问题。
                    if ( !me.trigger( 'accept', ret, rHeaders, function( val ) {
                        reject = val;
                    } ) ) {
                        reject = reject || 'server';
                    } else {
                        return me._onsuccess.call( me, ret, rHeaders );
                    }
                }

                reject = reject || (xhr.status ? 'http' : 'timeout');
                return me._reject( reject );
            };

            return me._xhr = xhr;
        },

        _onprogress: function( percentage ) {
            var opts = this.options,
                start, end, total;

            if ( this.chunks ) {
                total = this._blob.size;
                start = this.chunk * opts.chunkSize;
                end = Math.min( start + opts.chunkSize, total );

                percentage = (start + percentage * (end -start)) / total;
            }

            this._notify( percentage );
        },

        _onsuccess: function( ret, headers ) {
            if ( this.chunks && this.chunk < this.chunks - 1 ) {
                this.chunk++;
                this._upload();
            } else {
                this._resolve( ret, headers );
            }
        },

        _notify: function( percentage ) {
            this.trigger( 'progress', percentage || 0 );
        },

        _resolve: function( ret, headers ) {
            this.state = 'done';
            this.trigger( 'success', ret, headers );
            this.trigger( 'complete' );
        },

        _reject: function( reason ) {
            // @todo
            // 如果是timeout abort, 在chunk传输模式中应该自动重传。
            // chunkRetryCount = 3;
            this.state = 'fail';
            this.trigger( 'error', reason );
            this.trigger( 'complete' );
        },

        _setRequestHeader: function( xhr, headers ) {
            $.each( headers, function( key, val ) {
                xhr.setRequestHeader( key, val );
            } );
        },

        _getXhrHeaders: function( xhr ) {
            var str = xhr.getAllResponseHeaders(),
                ret = {},
                match;

            $.each( str.split( /\n/ ), function( i, str ) {
                match = /^(.*?): (.*)$/.exec( str );

                if ( match ) {
                    ret[ match[ 1 ] ] = match[ 2 ];
                }
            } );

            return ret;
        },

        _parseResponse: function( json ) {
            var ret;

            try {
                ret = JSON.parse( json );
            } catch ( ex ) {
                ret = {};
            }

            return ret;
        },

        _upload: function() {
            if ( this.paused ) {
                return this;
            }

            var opts = this.options,
                xhr = this._initAjax(),
                formData = new FormData(),
                blob = this._blob,
                slice = blob.slice || blob.webkitSlice || blob.mozSlice,
                start, end;

            if ( this.chunks ) {
                start = this.chunk * opts.chunkSize;
                end = Math.min( blob.size, start + opts.chunkSize );

                blob = slice.call( blob, start, end );
                opts.formData.chunk = this.chunk;
                opts.formData.chunks = this.chunks;

                start === 0 &&
                        xhr.overrideMimeType( 'application/octet-stream' );
            }

            // 外部可以在这个时机中添加其他信息
            this.trigger( 'beforeSend', opts.formData, opts.headers, xhr );

            $.each( opts.formData, function( key, val ) {
                formData.append( key, val );
            } );

            formData.append( opts.fileVar, blob, opts.formData &&
                    opts.formData.name || '' );

            if ( opts.withCredentials && 'withCredentials' in xhr ) {
                xhr.open( 'POST', opts.server, true );
                xhr.withCredentials = true;
            } else {
                xhr.open( 'POST', opts.server );
            }

            this._setRequestHeader( xhr, opts.headers );

            if ( opts.timeout ) {
                this.timoutTimer = setTimeout(function() {
                    xhr.abort();
                }, opts.timeout );
            }

            xhr.send( formData );
            this.state = 'progress';
            return this;
        },

        pause: function() {
            if ( this.paused ) {
                return;
            }

            this.paused = true;

            if ( this._xhr ) {
                this._xhr.upload.onprogress = noop;
                this._xhr.onreadystatechange = noop;
                clearTimeout( this.timoutTimer );
                this._xhr.abort();
                this._onprogress( 0 );
            }
        },

        resume: function() {
            if ( !this.paused ) {
                return;
            }

            this.paused = false;
            this._upload();
        },

        cancel: function() {
            if ( this._xhr ) {
                this._xhr.upload.onprogress = noop;
                this._xhr.onreadystatechange = noop;
                clearTimeout( this.timoutTimer );
                this._xhr.abort();
                this._xhr = null;
            }
        },

        /**
         * 以Blob的方式发送数据到服务器
         * @method sendAsBlob
         * @param {Blob} blob Blob数据
         * @return {Transport} 返回实例自己，便于链式调用。
         * @chainable
         */
        sendAsBlob: function( blob ) {
            var opts = this.options;

            if ( opts.chunked && blob.size > opts.chunkSize ) {
                this.chunk = 0;
                this.chunks = Math.ceil( blob.size / opts.chunkSize );
            }

            this._blob = blob;

            this._upload();
            this._notify( 0 );
            return this;
        },

        destroy: function() {
            this._blob = null;
        }

    } );

    // 静态方法直接发送内容。
    Transport.sendAsBlob = function( blob, options ) {
        var instance = new Transport( options );
        instance.sendAsBlob( blob );
        return instance;
    };

    Html5Runtime.register( 'Transport', Transport );
} );<|endoftext|>


<commit_before>var responseUtil = require("../util/responseUtil.js");

var requestHandlers = [];

function hasHandlers(handlers) {
    requestHandlers = handlers;
}

function route(request, response) {
    console.log("Received request to " + request.url);
    var handled = false;
    requestHandlers.forEach(function(handler) {
        if (!handled && handler.shouldHandle(request)) {
            console.log("Routing to handler: " + handler.getHandlerName());
            handler.handle(request, response);
            handled = true;
        }
    });
    if (!handled) {
        console.warn("No request handler found for: " + request.url);
        responseUtil.notFound(response);
    }
}

exports.route = route;
exports.hasHandlers = hasHandlers;<commit_msg>Not blowing up when error happens during handling of request<commit_after>var responseUtil = require("../util/responseUtil.js");

var requestHandlers = [];

function hasHandlers(handlers) {
    requestHandlers = handlers;
}

function route(request, response) {
    console.log("Received request to " + request.url);
    var handled = false;
    requestHandlers.forEach(function(handler) {
        if (!handled && handler.shouldHandle(request)) {
            console.log("Routing to handler: " + handler.getHandlerName());
            try {
                handler.handle(request, response);
            } catch (err) {
                console.error(err);
                responseUtil.textPlain(response, 500, err.toString());
            }
            handled = true;
        }
    });
    if (!handled) {
        console.warn("No request handler found for: " + request.url);
        responseUtil.notFound(response);
    }
}

exports.route = route;
exports.hasHandlers = hasHandlers;<|endoftext|>


<commit_before>// @flow

import os from 'os'
import pMap from 'p-map'
import pReduce from 'p-reduce'
import flatten from 'lodash/flatten'
import promiseDefer from 'promise.defer'
import {
  Job,
  PundleError,
  getChunk,
  getFileName,
  getFileImportHash,
  type Chunk,
  type ImportResolved,
  type ImportRequest,
  type ComponentFileResolverResult,
  type WorkerProcessResult,
} from 'pundle-api'
import type { Config } from 'pundle-core-load-config'

import WorkerDelegate from '../worker/delegate'
import type { RunOptions } from '../types'

// TODO: Locks for files and chunks
export default class Master {
  config: Config
  options: RunOptions
  resolverWorker: WorkerDelegate
  processorWorkers: Array<WorkerDelegate>
  processQueue: Array<{| payload: ImportResolved, resolve: Function, reject: Function |}>

  constructor(config: Config, options: RunOptions) {
    this.config = config
    this.options = options
    this.processQueue = []

    this.resolverWorker = this._createWorker()
    this.processorWorkers = os.cpus().map(() => this._createWorker())
  }
  _createWorker(): WorkerDelegate {
    return new WorkerDelegate(this.options, {
      processQueue: this.processQueue,
      handleResolve: request => this.resolve(request),
    })
  }
  getAllWorkers(): Array<WorkerDelegate> {
    return [this.resolverWorker].concat(this.processorWorkers)
  }
  async spawnWorkers() {
    try {
      await Promise.all(
        this.getAllWorkers().map(async worker => {
          if (worker.isAlive()) return
          try {
            await worker.spawn()
          } catch (error) {
            worker.dispose()
            throw error
          }
        }),
      )
    } catch (error) {
      throw new PundleError('DAEMON', 'WORKER_CRASHED', null, null, `Worker crashed during initial spawn: ${error.message}`)
    }
  }
  dispose() {
    this.getAllWorkers().forEach(function(worker) {
      worker.dispose()
    })
  }
  report(issue: $FlowFixMe) {
    console.log('issue reported to master', issue)
  }

  async execute(): Promise<void> {
    const job = new Job()
    const entries = await Promise.all(
      this.config.entry.map(entry =>
        this.resolve({
          request: entry,
          requestFile: null,
          ignoredResolvers: [],
        }),
      ),
    )
    await pMap(entries, entry => this.processChunk(getChunk(entry.format, null, entry.resolved), job))
    const generated = await this.generate(job)

    // TODO: Maybe do something else?
    return generated
  }
  async generate(
    givenJob: Job,
  ): Promise<Array<{ id: string, fileName: string | false, format: string, contents: string | Buffer }>> {
    let job = givenJob.clone()
    const jobTransformers = this.config.components.filter(c => c.type === 'job-transformer')

    job = await pReduce(
      jobTransformers,
      async (value, component) => {
        const result = await component.callback(value)
        // TODO: Validation
        return result || value
      },
      job,
    )

    const chunkGenerators = this.config.components.filter(c => c.type === 'chunk-generator')
    if (!chunkGenerators.length) {
      throw new Error('No chunk-generator components configured')
    }

    const generated = await pMap(job.chunks.values(), async chunk => {
      for (let i = 0, { length } = chunkGenerators; i < length; i++) {
        const generator = chunkGenerators[i]
        const result = await generator.callback(chunk, job, {
          getFileName: output => getFileName(this.config.output.formats, output),
        })
        if (result) {
          return result.map(item => ({
            ...item,
            id: chunk.id,
            fileName: getFileName(this.config.output.formats, {
              id: chunk.id,
              entry: chunk.entry,
              format: item.format,
            }),
          }))
        }
      }
      throw new Error(
        `All generators refused to generate chunk of format '${chunk.format}' with label '${chunk.label}' and entry '${
          chunk.entry
        }'`,
      )
    })

    return flatten(generated)
  }
  async processChunk(chunk: Chunk, job: Job): Promise<void> {
    const { entry } = chunk
    if (!entry) {
      // TODO: Return silently instead?
      throw new Error('Cannot process chunk without entry')
    }
    const lockKey = `c${chunk.id}`
    if (job.locks.has(lockKey)) {
      return
    }
    if (job.chunks.has(chunk.id)) {
      return
    }

    job.locks.add(lockKey)
    try {
      job.chunks.set(chunk.id, chunk)

      await this.processFileTree(
        {
          format: chunk.format,
          filePath: entry,
        },
        false,
        job,
      )
    } catch (error) {
      job.chunks.delete(chunk.id)
      throw error
    } finally {
      job.locks.delete(lockKey)
    }
  }
  // TODO: Use cached old files here if present on the job?
  async processFileTree(request: ImportResolved, forcedOverwrite: boolean, job: Job): Promise<void> {
    const lockKey = getFileImportHash(request.filePath, request.format)
    const oldFile = job.files.get(lockKey)
    if (job.locks.has(lockKey)) {
      return
    }
    if (oldFile && !forcedOverwrite) {
      return
    }
    job.locks.add(lockKey)

    try {
      const newFile = await this.queuedProcess(request)
      job.files.set(newFile.id, newFile)
      await Promise.all([
        pMap(newFile.imports, fileImport => this.processFileTree(fileImport, false, job)),
        pMap(newFile.chunks, fileChunk => this.processChunk(fileChunk, job)),
      ])
    } catch (error) {
      if (oldFile) {
        job.files.set(lockKey, oldFile)
      } else {
        job.files.delete(lockKey)
      }
      throw error
    } finally {
      job.locks.delete(lockKey)
    }
  }
  async resolve(request: ImportRequest): Promise<ComponentFileResolverResult> {
    return this.resolverWorker.resolve(request)
  }
  async queuedProcess(payload: ImportResolved): Promise<WorkerProcessResult> {
    const currentWorker = this.processorWorkers.find(worker => worker.busyProcessing === 0)
    let promise
    if (currentWorker) {
      promise = currentWorker.process(payload)
    } else {
      const { promise: deferredPromise, resolve, reject } = promiseDefer()
      this.processQueue.push({
        payload,
        resolve,
        reject,
      })
      promise = deferredPromise
    }

    const result = await promise
    if (typeof result.contents === 'object' && result.contents) {
      return {
        ...result,
        contents: Buffer.from(result.contents),
      }
    }
    return result
  }
}
<commit_msg>:bug: Spawn two less workers because main thread + resolve<commit_after>// @flow

import os from 'os'
import pMap from 'p-map'
import pReduce from 'p-reduce'
import flatten from 'lodash/flatten'
import promiseDefer from 'promise.defer'
import {
  Job,
  PundleError,
  getChunk,
  getFileName,
  getFileImportHash,
  type Chunk,
  type ImportResolved,
  type ImportRequest,
  type ComponentFileResolverResult,
  type WorkerProcessResult,
} from 'pundle-api'
import type { Config } from 'pundle-core-load-config'

import WorkerDelegate from '../worker/delegate'
import type { RunOptions } from '../types'

// TODO: Locks for files and chunks
export default class Master {
  config: Config
  options: RunOptions
  resolverWorker: WorkerDelegate
  processorWorkers: Array<WorkerDelegate>
  processQueue: Array<{| payload: ImportResolved, resolve: Function, reject: Function |}>

  constructor(config: Config, options: RunOptions) {
    this.config = config
    this.options = options
    this.processQueue = []

    this.resolverWorker = this._createWorker()
    this.processorWorkers = os
      .cpus()
      // Minus two because we have current plus resolver
      .slice(-2)
      .map(() => this._createWorker())
  }
  _createWorker(): WorkerDelegate {
    return new WorkerDelegate(this.options, {
      processQueue: this.processQueue,
      handleResolve: request => this.resolve(request),
    })
  }
  getAllWorkers(): Array<WorkerDelegate> {
    return [this.resolverWorker].concat(this.processorWorkers)
  }
  async spawnWorkers() {
    try {
      await Promise.all(
        this.getAllWorkers().map(async worker => {
          if (worker.isAlive()) return
          try {
            await worker.spawn()
          } catch (error) {
            worker.dispose()
            throw error
          }
        }),
      )
    } catch (error) {
      throw new PundleError('DAEMON', 'WORKER_CRASHED', null, null, `Worker crashed during initial spawn: ${error.message}`)
    }
  }
  dispose() {
    this.getAllWorkers().forEach(function(worker) {
      worker.dispose()
    })
  }
  report(issue: $FlowFixMe) {
    console.log('issue reported to master', issue)
  }

  async execute(): Promise<void> {
    const job = new Job()
    const entries = await Promise.all(
      this.config.entry.map(entry =>
        this.resolve({
          request: entry,
          requestFile: null,
          ignoredResolvers: [],
        }),
      ),
    )
    await pMap(entries, entry => this.processChunk(getChunk(entry.format, null, entry.resolved), job))
    const generated = await this.generate(job)

    // TODO: Maybe do something else?
    return generated
  }
  async generate(
    givenJob: Job,
  ): Promise<Array<{ id: string, fileName: string | false, format: string, contents: string | Buffer }>> {
    let job = givenJob.clone()
    const jobTransformers = this.config.components.filter(c => c.type === 'job-transformer')

    job = await pReduce(
      jobTransformers,
      async (value, component) => {
        const result = await component.callback(value)
        // TODO: Validation
        return result || value
      },
      job,
    )

    const chunkGenerators = this.config.components.filter(c => c.type === 'chunk-generator')
    if (!chunkGenerators.length) {
      throw new Error('No chunk-generator components configured')
    }

    const generated = await pMap(job.chunks.values(), async chunk => {
      for (let i = 0, { length } = chunkGenerators; i < length; i++) {
        const generator = chunkGenerators[i]
        const result = await generator.callback(chunk, job, {
          getFileName: output => getFileName(this.config.output.formats, output),
        })
        if (result) {
          return result.map(item => ({
            ...item,
            id: chunk.id,
            fileName: getFileName(this.config.output.formats, {
              id: chunk.id,
              entry: chunk.entry,
              format: item.format,
            }),
          }))
        }
      }
      throw new Error(
        `All generators refused to generate chunk of format '${chunk.format}' with label '${chunk.label}' and entry '${
          chunk.entry
        }'`,
      )
    })

    return flatten(generated)
  }
  async processChunk(chunk: Chunk, job: Job): Promise<void> {
    const { entry } = chunk
    if (!entry) {
      // TODO: Return silently instead?
      throw new Error('Cannot process chunk without entry')
    }
    const lockKey = `c${chunk.id}`
    if (job.locks.has(lockKey)) {
      return
    }
    if (job.chunks.has(chunk.id)) {
      return
    }

    job.locks.add(lockKey)
    try {
      job.chunks.set(chunk.id, chunk)

      await this.processFileTree(
        {
          format: chunk.format,
          filePath: entry,
        },
        false,
        job,
      )
    } catch (error) {
      job.chunks.delete(chunk.id)
      throw error
    } finally {
      job.locks.delete(lockKey)
    }
  }
  // TODO: Use cached old files here if present on the job?
  async processFileTree(request: ImportResolved, forcedOverwrite: boolean, job: Job): Promise<void> {
    const lockKey = getFileImportHash(request.filePath, request.format)
    const oldFile = job.files.get(lockKey)
    if (job.locks.has(lockKey)) {
      return
    }
    if (oldFile && !forcedOverwrite) {
      return
    }
    job.locks.add(lockKey)

    try {
      const newFile = await this.queuedProcess(request)
      job.files.set(newFile.id, newFile)
      await Promise.all([
        pMap(newFile.imports, fileImport => this.processFileTree(fileImport, false, job)),
        pMap(newFile.chunks, fileChunk => this.processChunk(fileChunk, job)),
      ])
    } catch (error) {
      if (oldFile) {
        job.files.set(lockKey, oldFile)
      } else {
        job.files.delete(lockKey)
      }
      throw error
    } finally {
      job.locks.delete(lockKey)
    }
  }
  async resolve(request: ImportRequest): Promise<ComponentFileResolverResult> {
    return this.resolverWorker.resolve(request)
  }
  async queuedProcess(payload: ImportResolved): Promise<WorkerProcessResult> {
    const currentWorker = this.processorWorkers.find(worker => worker.busyProcessing === 0)
    let promise
    if (currentWorker) {
      promise = currentWorker.process(payload)
    } else {
      const { promise: deferredPromise, resolve, reject } = promiseDefer()
      this.processQueue.push({
        payload,
        resolve,
        reject,
      })
      promise = deferredPromise
    }

    const result = await promise
    if (typeof result.contents === 'object' && result.contents) {
      return {
        ...result,
        contents: Buffer.from(result.contents),
      }
    }
    return result
  }
}
<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';

import { fetchUserSnaps } from '../../actions/snaps';
import { fetchBuilds } from '../../actions/snap-builds';
import { LinkButton } from '../vanilla/button';
import { HeadingThree } from '../vanilla/heading';
import FirstTimeHeading from '../first-time-heading';
import RepositoriesList from '../repositories-list';
import styles from './repositories-home.css';
import Spinner from '../spinner';

// loading container styles not to duplicate .spinner class
import { spinner as spinnerStyles } from '../../containers/container.css';

let interval;
const SNAP_POLL_PERIOD = (15 * 1000);

class RepositoriesHome extends Component {
  fetchData(props) {
    const { snaps } = props;

    if (snaps.success) {
      // if user doesn't have enabled repos open add repositories view
      if (snaps.snaps.length === 0) {
        this.props.router.replace('/dashboard/select-repositories');
        return;
      }

      snaps.snaps.forEach((snap) => {
        this.props.dispatch(fetchBuilds(snap.git_repository_url, snap.self_link));
      });
    }
  }

  componentDidMount() {
    const { authenticated } = this.props.auth;
    const { updateSnaps } = this.props;
    const owner = this.props.user.login;

    if (authenticated) {
      updateSnaps(owner);
      if (!interval) {
        interval = setInterval(() => {
          updateSnaps(owner);
        }, SNAP_POLL_PERIOD);
      }
    }
  }

  componentWillUnmount() {
    clearInterval(interval);
    interval = null;
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.snaps.success !== nextProps.snaps.success) {
      this.fetchData(nextProps);
    }
  }

  renderRepositoriesList() {
    const { snaps, snapBuilds } = this.props;

    return (

        <FirstTimeHeading snaps={snaps} snapBuilds={snapBuilds} isOnMyRepos={true} />

          <HeadingThree>Repos to build and publish</HeadingThree>

            <LinkButton appearance="neutral" to="/dashboard/select-repositories">
              Add repos…
            </LinkButton>

        <RepositoriesList />

    );
  }

  renderSpinner() {
    return (

        <Spinner />

    );
  }

  render() {
    const { snaps } = this.props;
    const hasSnaps = (snaps.snaps && Object.keys(snaps.snaps).length > 0);
    // show spinner until we know if user has any enabled repos
    return (snaps.isFetching && !hasSnaps)
      ? this.renderSpinner()
      : this.renderRepositoriesList();
  }
}

RepositoriesHome.propTypes = {
  auth: PropTypes.object.isRequired,
  user: PropTypes.object,
  snaps: PropTypes.object.isRequired,
  snapBuilds: PropTypes.object.isRequired,
  dispatch: PropTypes.func.isRequired,
  router: PropTypes.object.isRequired,
  updateSnaps: PropTypes.func.isRequired
};

function mapStateToProps(state) {
  const {
    auth,
    user,
    snaps,
    snapBuilds
  } = state;

  return {
    auth,
    user,
    snaps,
    snapBuilds
  };
}

function mapDispatchToProps(dispatch) {
  return {
    updateSnaps: (owner) => {
      dispatch(fetchUserSnaps(owner));
    }
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(RepositoriesHome));
export const RepositoriesHomeRaw = RepositoriesHome;
<commit_msg>489: Bugfix: "dispatch" is undefined on dashboard (#490)<commit_after>import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router';

import { fetchUserSnaps } from '../../actions/snaps';
import { fetchBuilds } from '../../actions/snap-builds';
import { LinkButton } from '../vanilla/button';
import { HeadingThree } from '../vanilla/heading';
import FirstTimeHeading from '../first-time-heading';
import RepositoriesList from '../repositories-list';
import styles from './repositories-home.css';
import Spinner from '../spinner';

// loading container styles not to duplicate .spinner class
import { spinner as spinnerStyles } from '../../containers/container.css';

let interval;
const SNAP_POLL_PERIOD = (15 * 1000);

class RepositoriesHome extends Component {
  fetchData(props) {
    const { snaps } = props;

    if (snaps.success) {
      // if user doesn't have enabled repos open add repositories view
      if (snaps.snaps.length === 0) {
        this.props.router.replace('/dashboard/select-repositories');
        return;
      }

      snaps.snaps.forEach((snap) => {
        this.props.fetchBuilds(snap.git_repository_url, snap.self_link);
      });
    }
  }

  componentDidMount() {
    const { authenticated } = this.props.auth;
    const { updateSnaps } = this.props;
    const owner = this.props.user.login;

    if (authenticated) {
      updateSnaps(owner);
      if (!interval) {
        interval = setInterval(() => {
          updateSnaps(owner);
        }, SNAP_POLL_PERIOD);
      }
    }
  }

  componentWillUnmount() {
    clearInterval(interval);
    interval = null;
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.snaps.success !== nextProps.snaps.success) {
      this.fetchData(nextProps);
    }
  }

  renderRepositoriesList() {
    const { snaps, snapBuilds } = this.props;

    return (

        <FirstTimeHeading snaps={snaps} snapBuilds={snapBuilds} isOnMyRepos={true} />

          <HeadingThree>Repos to build and publish</HeadingThree>

            <LinkButton appearance="neutral" to="/dashboard/select-repositories">
              Add repos…
            </LinkButton>

        <RepositoriesList />

    );
  }

  renderSpinner() {
    return (

        <Spinner />

    );
  }

  render() {
    const { snaps } = this.props;
    const hasSnaps = (snaps.snaps && Object.keys(snaps.snaps).length > 0);
    // show spinner until we know if user has any enabled repos
    return (snaps.isFetching && !hasSnaps)
      ? this.renderSpinner()
      : this.renderRepositoriesList();
  }
}

RepositoriesHome.propTypes = {
  auth: PropTypes.object.isRequired,
  user: PropTypes.object,
  snaps: PropTypes.object.isRequired,
  snapBuilds: PropTypes.object.isRequired,
  router: PropTypes.object.isRequired,
  updateSnaps: PropTypes.func.isRequired,
  fetchBuilds: PropTypes.func.isRequired
};

function mapStateToProps(state) {
  const {
    auth,
    user,
    snaps,
    snapBuilds
  } = state;

  return {
    auth,
    user,
    snaps,
    snapBuilds
  };
}

function mapDispatchToProps(dispatch) {
  return {
    updateSnaps: (owner) => {
      dispatch(fetchUserSnaps(owner));
    },
    fetchBuilds: (repositoryUrl, snapLink) => {
      dispatch(fetchBuilds(repositoryUrl, snapLink));
    }
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(RepositoriesHome));
export const RepositoriesHomeRaw = RepositoriesHome;
<|endoftext|>


<commit_before>'use strict'

var crypto = require('crypto')
var querystring = require('querystring')
var filesystem = require('fs')

var AWS = require('aws-sdk')
var config = require('./config.json')
var uuid = require('uuid')
var validator = require('validator')

module.exports.handler = (event, context, callback) => {
  var docClient = new AWS.DynamoDB.DocumentClient()
  var form = querystring.parse(event.body)
  var payload = {}

  if (form['_honeypot'] !== undefined && !validator.isEmpty(form['_honeypot'])) {
    callback(null, response(422, 'You shall not pass'))
  }

  if (form['_send-to'] === undefined || !validator.isEmail(form['_send-to'])) {
    callback(null, response(422, 'Form not sent, the admin has not set up a send-to address.'))
  }

  payload.id = uuid.v4()
  var data = {}
  for (var key in form) {
    data[key] = validator.trim(form[key])
  }
  payload.data = encrypt(JSON.stringify(data))

  docClient.put({TableName: config.TABLE_NAME, Item: payload}, (error) => {
    if (error) {
      callback(null, response(422, 'Form not sent, there was an error adding it to the database.'))
    }

    if (form['_redirect-to'] !== undefined && validator.isURL(form['_redirect-to'])) {
      callback(null, response(301, 'Form submission successfully made.', form['_redirect-to']))
    }

    callback(null, response(200, 'Form submission successfully made.'))
  })
}

function response(statusCode, message, redirect) {
  var response = {
    statusCode: statusCode,
    headers: {
      'Content-Type': 'text/html'
    },
    body: generateView(message)
  }

  if (redirect !== undefined) {
    response.headers.Location = redirect
  }

  return response
}

function encrypt(text) {
  var cipher = crypto.createCipher('aes-256-ctr', config.ENCRYPTION_KEY)
  var crypted = cipher.update(text, 'utf8', 'hex')
  crypted += cipher.final('hex');
  return crypted;
}

function generateView(message) {
  var template =  filesystem.readFileSync('template.html').toString()

  if (!template) {
    return message
  }

  return template.replace('{{ message }}', message)
}
<commit_msg>add custom messages via config.json<commit_after>'use strict'

var crypto = require('crypto')
var querystring = require('querystring')
var filesystem = require('fs')

var AWS = require('aws-sdk')
var config = require('./config.json')
var uuid = require('uuid')
var validator = require('validator')

module.exports.handler = (event, context, callback) => {
  var docClient = new AWS.DynamoDB.DocumentClient()
  var form = querystring.parse(event.body)
  var payload = {}

  if (form['_honeypot'] !== undefined && !validator.isEmpty(form['_honeypot'])) {
    callback(null, response(422, config.MSG_HONEYPOT || 'You shall not pass'))
  }

  if (form['_send-to'] === undefined || !validator.isEmail(form['_send-to'])) {
    callback(null, response(422, config.MSG_MISSING_SEND_TO || 'Form not sent, the admin has not set up a send-to address.'))
  }

  payload.id = uuid.v4()
  var data = {}
  for (var key in form) {
    data[key] = validator.trim(form[key])
  }
  payload.data = encrypt(JSON.stringify(data))

  docClient.put({TableName: config.TABLE_NAME, Item: payload}, (error) => {
    if (error) {
      callback(null, response(422, config.MSG_DB_ERROR || 'Form not sent, there was an error adding it to the database.'))
    }

    if (form['_redirect-to'] !== undefined && validator.isURL(form['_redirect-to'])) {
      callback(null, response(301, config.MSG_SUCCESS || 'Form submission successfully made.', form['_redirect-to']))
    }

    callback(null, response(200, config.MSG_SUCCESS || 'Form submission successfully made.'))
  })
}

function response(statusCode, message, redirect) {
  var response = {
    statusCode: statusCode,
    headers: {
      'Content-Type': 'text/html'
    },
    body: generateView(message)
  }

  if (redirect !== undefined) {
    response.headers.Location = redirect
  }

  return response
}

function encrypt(text) {
  var cipher = crypto.createCipher('aes-256-ctr', config.ENCRYPTION_KEY)
  var crypted = cipher.update(text, 'utf8', 'hex')
  crypted += cipher.final('hex');
  return crypted;
}

function generateView(message) {
  var template =  filesystem.readFileSync('template.html').toString()

  if (!template) {
    return message
  }

  return template.replace('{{ message }}', message)
}
<|endoftext|>


<commit_before>var KINDLEBOX_MODAL_ID = 'kindlebox-device-picker';
var KINDLEBOX_FORM_ID = 'kindlebox-devices-form';
var KINDLEBOX_DEVICES_ID = 'kindlebox-devices-container';

var kindleboxDevices = [];
var whitelistedEmailer = false;

function setDevice(deviceNum) {
  window.location.hash = '#/home/devices/' + deviceNum;
}

function htmlToString($html) {
  var text = '';
  try {
    text = $html[0].childNodes[0].textContent.trim();
  } catch(error) {
  }
  return text;
}

function getNumDevices() {
  return $('.deviceName_myx.a-size-base').length;
}

function getDevices() {
  if (kindleboxDevices.length > 0) {
    return kindleboxDevices;
  }

  var numDevices = getNumDevices();
  var devices = [];
  for (var i = 1; i <= numDevices; i++) {
    setDevice(i);
    var emailContainer = $('#dv_dt_email_value');
    if (emailContainer.length > 0) {
      var device = {
        'tag': htmlToString($('#dv_dt_name_value')),
        'email': htmlToString(emailContainer),
        'type': htmlToString($('#deviceDetail_type_myx_value')),
      };
      devices.push(device);
    }
  }
  kindleboxDevices = devices;
  return devices;
}

function whitelistEmailer(emailer, successCallback) {
  // If we've already succesfully whitelisted the emailer in this load of the
  // bookmarklet, go straight to the callback.
  if (whitelistedEmailer) {
    successCallback();
    return;
  }

  $.post('https://www.amazon.com/mn/dcw/myx/ajax-activity', {
    "data": '{"param":{"WhitelistEmail":{"newEmail":"' + emailer + '"}}}',
    "csrfToken": csrfToken,
  }, function(res) {
    try {
      if (res.WhitelistEmail.success || res.WhitelistEmail.error == 'DUPLICATE_ITEM') {
          whitelistedEmailer = true;
          successCallback();
      } else {
        throw res.WhitelistEmail.error;
      }
    } catch (err) {
      console.log(err);
    }
  }, "json");
}

function addModal(kindleboxCsrfToken, appUrl, emailer) {
  // If the modal has already been added and it has the right number of
  // devices, don't do anything.
  if ($("#" + KINDLEBOX_MODAL_ID).length > 0) {
    return;
  }

  var $modalHtml = $('
' +
      '
' +
      '
' +
      '
' +
      '      <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' +
      '
Kindlebox
' +
      '
' +
      '
' +
      '        Select your Kindle device(s)!' +
      '        <form id="' + KINDLEBOX_FORM_ID + '" action="' + appUrl + '/activate" method="POST">' +
      '          <input type="hidden" name="csrf_token" value="' + kindleboxCsrfToken + '">' +
      '          <input type="hidden" name="kindle_names" value="">' +
      '
' +
      '
' +
      '        </form>' +
      '
' +
      '
' +
      '
' +
      '          Oops, no devices were selected! Try again :)' +
      '
' +
      '        <button id="activate-kindlebox-btn" type="button" class="btn btn-primary">Activate Kindlebox</button>' +
      '
' +
      '
' +
      '
' +
      '
');

  $modalHtml.find('#kindlebox-error').hide();

  // Handler for submitting the picker form.
  function activateKindlebox() {
    var devices = $.makeArray($("#" + KINDLEBOX_FORM_ID).find(".kindlebox-device-checkbox:checked"));
    if (devices.length == 0) {
      $('#kindlebox-error').clearQueue().fadeIn().delay(3000).fadeOut();
      return;
    }
    var kindleNames = devices.map(function(device) {
      return device.name;
    });
    $("[name='kindle_names']").val(JSON.stringify(kindleNames));
    $("#" + KINDLEBOX_FORM_ID).submit();
  }
  $modalHtml.find("#activate-kindlebox-btn").click(function() {
    whitelistEmailer(emailer, activateKindlebox);
  });

  // Add a checkbox for each device eligible for Kindlebox.
  var devices = getDevices();
  for (var i = 0; i < devices.length; i++) {
    var label = devices[i].tag;
    if (devices[i].type) {
      label += ' (' + devices[i].type + ')';
    }
    $modalHtml.find("#" + KINDLEBOX_DEVICES_ID).append('
' +
      '  <input type="checkbox" id="kindlebox-device-' + i + '" class="kindlebox-device-checkbox" name="' + devices[i].email + '">' +
      '  ' +
         label +
       '' +
      '
');
  }

  $('body').append($modalHtml);
}

function showModal() {
  $('#' + KINDLEBOX_MODAL_ID).modal();
}

function submitKindleName(kindleName) {
  $.post('/set-user-info', {
    'kindle_name': kindleName
  }, function(data) {
    if (data.success) {
      this.props.kindleNameHandler(kindleName, data.emailer);
      $(':focus').blur();
      this.handleBlur();
    }
  }.bind(this));
}
<commit_msg>change modal if no devices detected<commit_after>var KINDLEBOX_MODAL_ID = 'kindlebox-device-picker';
var KINDLEBOX_FORM_ID = 'kindlebox-devices-form';
var KINDLEBOX_DEVICES_ID = 'kindlebox-devices-container';

var kindleboxDevices = [];
var whitelistedEmailer = false;

function setDevice(deviceNum) {
  window.location.hash = '#/home/devices/' + deviceNum;
}

function htmlToString($html) {
  var text = '';
  try {
    text = $html[0].childNodes[0].textContent.trim();
  } catch(error) {
  }
  return text;
}

function getNumDevices() {
  return $('.deviceName_myx.a-size-base').length;
}

function getDevices() {
  if (kindleboxDevices.length > 0) {
    return kindleboxDevices;
  }

  var numDevices = getNumDevices();
  var devices = [];
  for (var i = 1; i <= numDevices; i++) {
    setDevice(i);
    var emailContainer = $('#dv_dt_email_value');
    if (emailContainer.length > 0) {
      var device = {
        'tag': htmlToString($('#dv_dt_name_value')),
        'email': htmlToString(emailContainer),
        'type': htmlToString($('#deviceDetail_type_myx_value')),
      };
      devices.push(device);
    }
  }
  kindleboxDevices = devices;
  return devices;
}

function whitelistEmailer(emailer, successCallback) {
  // If we've already succesfully whitelisted the emailer in this load of the
  // bookmarklet, go straight to the callback.
  if (whitelistedEmailer) {
    successCallback();
    return;
  }

  $.post('https://www.amazon.com/mn/dcw/myx/ajax-activity', {
    "data": '{"param":{"WhitelistEmail":{"newEmail":"' + emailer + '"}}}',
    "csrfToken": csrfToken,
  }, function(res) {
    try {
      if (res.WhitelistEmail.success || res.WhitelistEmail.error == 'DUPLICATE_ITEM') {
          whitelistedEmailer = true;
          successCallback();
      } else {
        throw res.WhitelistEmail.error;
      }
    } catch (err) {
      console.log(err);
    }
  }, "json");
}

function addModal(kindleboxCsrfToken, appUrl, emailer) {
  // If the modal has already been added and it has the right number of
  // devices, don't do anything.
  if ($("#" + KINDLEBOX_MODAL_ID).length > 0) {
    return;
  }

  var $modalHtml = $('
' +
      '
' +
      '
' +
      '
' +
      '      <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>' +
      '
Kindlebox
' +
      '
' +
      '
' +
      '        Select your Kindle device(s)!' +
      '        <form id="' + KINDLEBOX_FORM_ID + '" action="' + appUrl + '/activate" method="POST">' +
      '          <input type="hidden" name="csrf_token" value="' + kindleboxCsrfToken + '">' +
      '          <input type="hidden" name="kindle_names" value="">' +
      '
' +
      '
' +
      '        </form>' +
      '
' +
      '
' +
      '
' +
      '          Oops, no devices were selected! Try again :)' +
      '
' +
      '        <button id="activate-kindlebox-btn" type="button" class="btn btn-primary">Activate Kindlebox</button>' +
      '
' +
      '
' +
      '
' +
      '
');

  $modalHtml.find('#kindlebox-error').hide();

  // Handler for submitting the picker form.
  function activateKindlebox() {
    var devices = $.makeArray($("#" + KINDLEBOX_FORM_ID).find(".kindlebox-device-checkbox:checked"));
    if (devices.length == 0) {
      $('#kindlebox-error').clearQueue().fadeIn().delay(3000).fadeOut();
      return;
    }
    var kindleNames = devices.map(function(device) {
      return device.name;
    });
    $("[name='kindle_names']").val(JSON.stringify(kindleNames));
    $("#" + KINDLEBOX_FORM_ID).submit();
  }
  $modalHtml.find("#activate-kindlebox-btn").click(function() {
    whitelistEmailer(emailer, activateKindlebox);
  });

  // Add a checkbox for each device eligible for Kindlebox.
  var devices = getDevices();
  if (devices.length == 0) {
    $modalHtml.find('.modal-body').text('Oops, it seems you don\'t have any \
        devices eligible for Kindlebox! Make sure to register a \
        Kindle with this Amazon account before trying again :)')
    $modalHtml.find('#activate-kindlebox-btn').attr('disabled', 'disabled');
  } else {
    for (var i = 0; i < devices.length; i++) {
      var label = devices[i].tag;
      if (devices[i].type) {
        label += ' (' + devices[i].type + ')';
      }
      $modalHtml.find("#" + KINDLEBOX_DEVICES_ID).append('
' +
        '  <input type="checkbox" id="kindlebox-device-' + i + '" class="kindlebox-device-checkbox" name="' + devices[i].email + '">' +
        '  ' +
           label +
         '' +
        '
');
    }
  }

  $('body').append($modalHtml);
}

function showModal() {
  $('#' + KINDLEBOX_MODAL_ID).modal();
}

function submitKindleName(kindleName) {
  $.post('/set-user-info', {
    'kindle_name': kindleName
  }, function(data) {
    if (data.success) {
      this.props.kindleNameHandler(kindleName, data.emailer);
      $(':focus').blur();
      this.handleBlur();
    }
  }.bind(this));
}
<|endoftext|>


<commit_before>$(document).ready(function () {
    // Initialize the DataTable component
    var myTable = $('#teamsTable').DataTable({
        "searching": false,
        "ordering":  false,
        "lengthChange": false,
        "ajax": {
            "url": "/scores/api",
            "dataSrc": "ranks",
            "error": function() {
                alert("Unable to get data from server");
            }
        },
        "columns": [
            { "data": "rank", "class": "align_center" },
            { "data": "number", "class": "align_center"},
            { "data": "name", "class": "align_center" },
            { "data": "affiliation", "class": "align_center" },
            { "data": "round1", "class": "align_center" },
            { "data": "round2", "class": "align_center" },
            { "data": "round3", "class": "align_center" },
            { "data": "bestScore", "class": "align_center" }
        ],
        "info": false
    });

    // Set up the page looping
    var page = 1;
    var pageCount = myTable.page.info().pages;

    // Auto-advance through the datatable pages
    var page_advance = setInterval(function() {

        // If on the final page, reload the data then start again
        if(page >= pageCount) {
            console.log("reloading data");
            myTable.ajax.reload();
            myTable.page(0).draw(false);
            pageCount = myTable.page.info().pages;
            page = 0;
        }

        // Set the table page and redraw
        myTable.page(page).draw(false);
        page++;
    }, 10000);
});<commit_msg>Remove pagination controls from pit display<commit_after>$(document).ready(function () {
    // Initialize the DataTable component
    var myTable = $('#teamsTable').DataTable({
        "searching": false,
        "ordering":  false,
        "lengthChange": false,
        "ajax": {
            "url": "/scores/api",
            "dataSrc": "ranks",
            "error": function() {
                alert("Unable to get data from server");
            }
        },
        "columns": [
            { "data": "rank", "class": "align_center" },
            { "data": "number", "class": "align_center"},
            { "data": "name", "class": "align_center" },
            { "data": "affiliation", "class": "align_center" },
            { "data": "round1", "class": "align_center" },
            { "data": "round2", "class": "align_center" },
            { "data": "round3", "class": "align_center" },
            { "data": "bestScore", "class": "align_center" }
        ],
        "info": false
    });

    $('.dataTables_paginate').hide()

    // Set up the page looping
    var page = 1;
    var pageCount = myTable.page.info().pages;

    // Auto-advance through the datatable pages
    var page_advance = setInterval(function() {

        // If on the final page, reload the data then start again
        if(page >= pageCount) {
            console.log("reloading data");
            myTable.ajax.reload();
            myTable.page(0).draw(false);
            pageCount = myTable.page.info().pages;
            page = 0;
        }

        // Set the table page and redraw
        myTable.page(page).draw(false);
        page++;
    }, 10000);
});<|endoftext|>


<commit_before>/* Omega JS Canvas Scene Mixin
 *
 * Copyright (C) 2013-2014 Mohammed Morsi <mo@morsi.org>
 * Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
 */

//= require 'vendor/stats.min'

Omega.UI.CanvasSceneManager = {
  render_params : {
	  minFilter     : THREE.LinearFilter,
    magFilter     : THREE.LinearFilter,
    format        : THREE.RGBFormat,
    stencilBuffer : false
  },

  ui_props : {
    wpadding : 22,
    hpadding : 26
  },

  cam_props : {
    min_distance :   100,
    max_distance : 20000
  },

  render_stats : true,

  /// Setup Canvas 3D operations
  setup : function(){
    this._setup_stats();
    this._setup_scenes();
    this._setup_renderer();
    this._setup_cams();
    this._setup_components();

    THREEx.WindowResize(this.renderer, this.cam,
                        this.ui_props.wpadding,
                        this.ui_props.hpadding);
  },

  _setup_stats : function(){
    if(this.render_stats){
      this.stats = new Stats();
      this.stats.setMode(0);
      $('#render_stats').append(this.stats.domElement);

    }else{
      this.stats = {update : function(){}};
    }
  },

  _setup_scenes : function(){
    this.scene    = new THREE.Scene();
    this.skyScene = new THREE.Scene();
  },

  descendants : function(){
    return this.scene.getDescendants().concat(this.skyScene.getDescendants());
  },

  _setup_renderer : function(){
    var sw = window.innerWidth  - this.ui_props.wpadding,
        sh = window.innerHeight - this.ui_props.hpadding;

    this.renderer = new THREE.WebGLRenderer({antialias : true});
    this.renderer.setSize(sw, sh);

    this.renderer.autoClear = false;
    this.renderer.setClearColor(0x000000, 0.0);

    this.canvas.append(this.renderer.domElement);
  },

  _setup_cams : function(){
    var sw = window.innerWidth  - this.ui_props.wpadding,
        sh = window.innerHeight - this.ui_props.hpadding;
    var aspect = sw / sh;
    if(isNaN(aspect)) aspect = 1;

    this.cam    = new THREE.PerspectiveCamera(75, aspect, 1, 42000 );
    this.skyCam = new THREE.PerspectiveCamera(75, aspect, 1, 42000 );

    this._setup_cam_controls();
  },

  _setup_cam_controls : function(){
    var _this = this;
    this.cam_controls = new THREE.OrbitControls(this.cam);
    this.cam_controls.minDistance = this.cam_props.min_distance;
    this.cam_controls.maxDistance = this.cam_props.max_distance;;
    this.cam_controls.addEventListener('change', function(){ _this.render(); });
    this.cam_controls.domElement = this.renderer.domElement;
    this.reset_cam();
  },

  _setup_components : function(){
    var _this = this;
    this.skybox.init_gfx();
    this.axis.init_gfx();
    this.star_dust.init_gfx(this.page.config, function(){ _this._init_gfx(); });
  },

  _init_gfx : function(){
    this.animate();
  },

  // Request animation frame
  animate : function(){
    var _this = this;
    requestAnimationFrame(function() { _this.render(); });
    this._detect_hover();
  },

  // Render scene (used internally, no need to invoke manually)
  render : function(){
    /// clear renderer
    this.renderer.clear();

    /// apply cam rotations to sky cam (but not translations)
    this.skyCam.rotation.setFromRotationMatrix(
      new THREE.Matrix4().extractRotation(this.cam.matrixWorld ),
      this.skyCam.eulerOrder);

    /// invoke 'rendered_in' callbacks on scene descendants
    var children = this.scene.getDescendants();
    for(var c = 0; c < children.length; c++){
      var child = children[c];
      if(child.omega_obj && child.omega_obj.rendered_in)
        child.omega_obj.rendered_in(this, child);
    }

    /// render actual scenes
    this.renderer.render(this.skyScene, this.skyCam);
    this.renderer.render(this.scene, this.cam);

    /// render stats
    this.stats.update();
  }
};
<commit_msg>UI: s/eulerOrder/rotation.order in canvas scene mixin<commit_after>/* Omega JS Canvas Scene Mixin
 *
 * Copyright (C) 2013-2014 Mohammed Morsi <mo@morsi.org>
 * Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
 */

//= require 'vendor/stats.min'

Omega.UI.CanvasSceneManager = {
  render_params : {
	  minFilter     : THREE.LinearFilter,
    magFilter     : THREE.LinearFilter,
    format        : THREE.RGBFormat,
    stencilBuffer : false
  },

  ui_props : {
    wpadding : 22,
    hpadding : 26
  },

  cam_props : {
    min_distance :   100,
    max_distance : 20000
  },

  render_stats : true,

  /// Setup Canvas 3D operations
  setup : function(){
    this._setup_stats();
    this._setup_scenes();
    this._setup_renderer();
    this._setup_cams();
    this._setup_components();

    THREEx.WindowResize(this.renderer, this.cam,
                        this.ui_props.wpadding,
                        this.ui_props.hpadding);
  },

  _setup_stats : function(){
    if(this.render_stats){
      this.stats = new Stats();
      this.stats.setMode(0);
      $('#render_stats').append(this.stats.domElement);

    }else{
      this.stats = {update : function(){}};
    }
  },

  _setup_scenes : function(){
    this.scene    = new THREE.Scene();
    this.skyScene = new THREE.Scene();
  },

  descendants : function(){
    return this.scene.getDescendants().concat(this.skyScene.getDescendants());
  },

  _setup_renderer : function(){
    var sw = window.innerWidth  - this.ui_props.wpadding,
        sh = window.innerHeight - this.ui_props.hpadding;

    this.renderer = new THREE.WebGLRenderer({antialias : true});
    this.renderer.setSize(sw, sh);

    this.renderer.autoClear = false;
    this.renderer.setClearColor(0x000000, 0.0);

    this.canvas.append(this.renderer.domElement);
  },

  _setup_cams : function(){
    var sw = window.innerWidth  - this.ui_props.wpadding,
        sh = window.innerHeight - this.ui_props.hpadding;
    var aspect = sw / sh;
    if(isNaN(aspect)) aspect = 1;

    this.cam    = new THREE.PerspectiveCamera(75, aspect, 1, 42000 );
    this.skyCam = new THREE.PerspectiveCamera(75, aspect, 1, 42000 );

    this._setup_cam_controls();
  },

  _setup_cam_controls : function(){
    var _this = this;
    this.cam_controls = new THREE.OrbitControls(this.cam);
    this.cam_controls.minDistance = this.cam_props.min_distance;
    this.cam_controls.maxDistance = this.cam_props.max_distance;;
    this.cam_controls.addEventListener('change', function(){ _this.render(); });
    this.cam_controls.domElement = this.renderer.domElement;
    this.reset_cam();
  },

  _setup_components : function(){
    var _this = this;
    this.skybox.init_gfx();
    this.axis.init_gfx();
    this.star_dust.init_gfx(this.page.config, function(){ _this._init_gfx(); });
  },

  _init_gfx : function(){
    this.animate();
  },

  // Request animation frame
  animate : function(){
    var _this = this;
    requestAnimationFrame(function() { _this.render(); });
    this._detect_hover();
  },

  // Render scene (used internally, no need to invoke manually)
  render : function(){
    /// clear renderer
    this.renderer.clear();

    /// apply cam rotations to sky cam (but not translations)
    this.skyCam.rotation.setFromRotationMatrix(
      new THREE.Matrix4().extractRotation(this.cam.matrixWorld ),
      this.skyCam.rotation.order);

    /// invoke 'rendered_in' callbacks on scene descendants
    var children = this.scene.getDescendants();
    for(var c = 0; c < children.length; c++){
      var child = children[c];
      if(child.omega_obj && child.omega_obj.rendered_in)
        child.omega_obj.rendered_in(this, child);
    }

    /// render actual scenes
    this.renderer.render(this.skyScene, this.skyCam);
    this.renderer.render(this.scene, this.cam);

    /// render stats
    this.stats.update();
  }
};
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { Field } from 'redux-form';
import MenuItem from '@material-ui/core/MenuItem';
import { FETCH_SUCCEEDED } from '../../lib/fetchConstants';
import withAsyncFetch from './hocs/AsyncContainer';
import { fetchMetadataValuesForCountry, fetchMetadataValuesForState, fetchMetadataValuesForPrimaryLanguage, fetchMetadataValuesForCountryOfFocus, fetchMetadataValuesForMediaType } from '../../actions/systemActions';
import withIntlForm from './hocs/IntlForm';
import { TAG_SET_PUBLICATION_COUNTRY, TAG_SET_PUBLICATION_STATE, TAG_SET_PRIMARY_LANGUAGE, TAG_SET_COUNTRY_OF_FOCUS, TAG_SET_MEDIA_TYPE } from '../../lib/tagUtil';

const MODE_SELECT = 'MODE_SELECT';
const MODE_AUTOCOMPLETE = 'MODE_AUTOCOMPLETE';

const localMessages = {
  hintText: { id: 'metadata.pick.hint', defaultMessage: 'Pick a {label}' },
};

const MetadataPickerContainer = (props) => {
  const { initialValues, label, name, tags, isClearable, renderSelect, autocompleteHideOptions,
    renderSimpleAutoComplete, autocomplete, disabled, showDescription } = props;
  const { formatMessage } = props.intl;
  const mode = autocomplete ? MODE_AUTOCOMPLETE : MODE_SELECT;
  let content = null;
  switch (mode) {
    case MODE_SELECT:
      if (showDescription) {
        content = (
          <Field
            fullWidth
            name={name}
            component={renderSelect}
            disabled={disabled}
            label={label}
          >
            <MenuItem className="header-primary-menu" value={null} />
            {tags.map(t => (
              <MenuItem
                className="header-primary-menu"
                key={t.tags_id}
                value={t.tags_id}
              >

{t.label}

{t.description}

              </MenuItem>
            ))}
          </Field>
        );
      } else {
        content = (
          <Field
            fullWidth
            name={name}
            component={renderSelect}
            disabled={disabled}
            label={label}
          >
            <MenuItem value={null} />
            {tags.map(t => <MenuItem key={t.tags_id} value={t.tags_id}>{t.label}</MenuItem>)}
          </Field>
        );
      }
      break;
    case MODE_AUTOCOMPLETE:
      let styles = {};
      if (autocompleteHideOptions) {
        styles = {
          dropdownIndicator: () => ({ display: 'none' }),
        };
      }
      content = (
<<<<<<< HEAD

          <Field
            className="metadata-picker"
            // searchText={initialText}
            name={name}
            component={renderAutoComplete}
            label={formatMessage(localMessages.hintText, { label })}
            hintText={formatMessage(localMessages.hintText, { label })}
            openOnFocus
            fullWidth
            dataSource={tags}
            dataSourceConfig={{ text: 'label', value: 'tags_id' }}
            maxSearchResults={10}
          />

=======
        <React.Fragment>
          {label}
          <Field
            styles={styles}
            name={name}
            component={renderSimpleAutoComplete}
            placeholder={formatMessage(localMessages.hintText, { label })}
            fullWidth
            isDisabled={disabled}
            options={tags}
            defaultValue={initialValues}
            getOptionLabel={tag => tag.label}
            getOptionValue={tag => tag.tags_id}
            isClearable={isClearable}
          />
        </React.Fragment>
>>>>>>> 9a6736d812bbf0c056d52306800f98a316fdf6ce
      );
      break;
    default:
      content = '';
      break;
  }
  return (<div className={`metadata-picker metadata-picker-${name}`}>{content}
);
};

MetadataPickerContainer.propTypes = {
  // from parent
  id: PropTypes.number.isRequired,
  name: PropTypes.string.isRequired,
  initialValues: PropTypes.object,
  disabled: PropTypes.bool,
  autocomplete: PropTypes.bool,
  autocompleteHideOptions: PropTypes.bool,
  isClearable: PropTypes.bool,
  showDescription: PropTypes.bool,
  // from compositional chain
  intl: PropTypes.object.isRequired,
  renderSelect: PropTypes.func.isRequired,
  renderSimpleAutoComplete: PropTypes.func.isRequired,
  // from state
  fetchStatus: PropTypes.string,
  tags: PropTypes.array,
  label: PropTypes.string,
};

const mapStateToProps = (state, ownProps) => ({
  fetchStatus: state.system.metadata[ownProps.name].fetchStatus,
  label: state.system.metadata[ownProps.name].label,
  tags: state.system.metadata[ownProps.name].tags,
});

const mapDispatchToProps = (dispatch, ownProps) => ({
  fetchTagsInCollection: (tagId) => {
    switch (ownProps.id) {
      case TAG_SET_PUBLICATION_COUNTRY:
        dispatch(fetchMetadataValuesForCountry(tagId));
        break;
      case TAG_SET_PUBLICATION_STATE:
        dispatch(fetchMetadataValuesForState(tagId));
        break;
      case TAG_SET_PRIMARY_LANGUAGE:
        dispatch(fetchMetadataValuesForPrimaryLanguage(tagId));
        break;
      case TAG_SET_COUNTRY_OF_FOCUS:
        dispatch(fetchMetadataValuesForCountryOfFocus(tagId));
        break;
      case TAG_SET_MEDIA_TYPE:
        dispatch(fetchMetadataValuesForMediaType(tagId));
        break;
      default:
        break;
    }
  },
});

function mergeProps(stateProps, dispatchProps, ownProps) {
  return Object.assign({}, stateProps, dispatchProps, ownProps, {
    asyncFetch: () => {
      // these sets don't change, so only refetch them if you don't have them already in the store
      const alreadyLoadedTags = ((stateProps.fetchStatus === FETCH_SUCCEEDED) && (stateProps.tags.length > 0));
      if (!alreadyLoadedTags) {
        dispatchProps.fetchTagsInCollection(ownProps.id);
      }
    },
  });
}

export default
connect(mapStateToProps, mapDispatchToProps, mergeProps)(
  withIntlForm(
    withAsyncFetch(
      MetadataPickerContainer
    )
  )
);
<commit_msg>fix merge conflict<commit_after>import PropTypes from 'prop-types';
import React from 'react';
import { connect } from 'react-redux';
import { Field } from 'redux-form';
import MenuItem from '@material-ui/core/MenuItem';
import { FETCH_SUCCEEDED } from '../../lib/fetchConstants';
import withAsyncFetch from './hocs/AsyncContainer';
import { fetchMetadataValuesForCountry, fetchMetadataValuesForState, fetchMetadataValuesForPrimaryLanguage, fetchMetadataValuesForCountryOfFocus, fetchMetadataValuesForMediaType } from '../../actions/systemActions';
import withIntlForm from './hocs/IntlForm';
import { TAG_SET_PUBLICATION_COUNTRY, TAG_SET_PUBLICATION_STATE, TAG_SET_PRIMARY_LANGUAGE, TAG_SET_COUNTRY_OF_FOCUS, TAG_SET_MEDIA_TYPE } from '../../lib/tagUtil';

const MODE_SELECT = 'MODE_SELECT';
const MODE_AUTOCOMPLETE = 'MODE_AUTOCOMPLETE';

const localMessages = {
  hintText: { id: 'metadata.pick.hint', defaultMessage: 'Pick a {label}' },
};

const MetadataPickerContainer = (props) => {
  const { initialValues, label, name, tags, isClearable, renderSelect, autocompleteHideOptions,
    renderSimpleAutoComplete, autocomplete, disabled, showDescription } = props;
  const { formatMessage } = props.intl;
  const mode = autocomplete ? MODE_AUTOCOMPLETE : MODE_SELECT;
  let content = null;
  switch (mode) {
    case MODE_SELECT:
      if (showDescription) {
        content = (
          <Field
            fullWidth
            name={name}
            component={renderSelect}
            disabled={disabled}
            label={label}
          >
            <MenuItem className="header-primary-menu" value={null} />
            {tags.map(t => (
              <MenuItem
                className="header-primary-menu"
                key={t.tags_id}
                value={t.tags_id}
              >

{t.label}

{t.description}

              </MenuItem>
            ))}
          </Field>
        );
      } else {
        content = (
          <Field
            fullWidth
            name={name}
            component={renderSelect}
            disabled={disabled}
            label={label}
          >
            <MenuItem value={null} />
            {tags.map(t => <MenuItem key={t.tags_id} value={t.tags_id}>{t.label}</MenuItem>)}
          </Field>
        );
      }
      break;
    case MODE_AUTOCOMPLETE:
      let styles = {};
      if (autocompleteHideOptions) {
        styles = {
          dropdownIndicator: () => ({ display: 'none' }),
        };
      }
      content = (
        <React.Fragment>
          {label}
          <Field
            styles={styles}
            name={name}
            component={renderSimpleAutoComplete}
            placeholder={formatMessage(localMessages.hintText, { label })}
            fullWidth
            isDisabled={disabled}
            options={tags}
            defaultValue={initialValues}
            getOptionLabel={tag => tag.label}
            getOptionValue={tag => tag.tags_id}
            isClearable={isClearable}
          />
        </React.Fragment>
      );
      break;
    default:
      content = '';
      break;
  }
  return (<div className={`metadata-picker metadata-picker-${name}`}>{content}
);
};

MetadataPickerContainer.propTypes = {
  // from parent
  id: PropTypes.number.isRequired,
  name: PropTypes.string.isRequired,
  initialValues: PropTypes.object,
  disabled: PropTypes.bool,
  autocomplete: PropTypes.bool,
  autocompleteHideOptions: PropTypes.bool,
  isClearable: PropTypes.bool,
  showDescription: PropTypes.bool,
  // from compositional chain
  intl: PropTypes.object.isRequired,
  renderSelect: PropTypes.func.isRequired,
  renderSimpleAutoComplete: PropTypes.func.isRequired,
  // from state
  fetchStatus: PropTypes.string,
  tags: PropTypes.array,
  label: PropTypes.string,
};

const mapStateToProps = (state, ownProps) => ({
  fetchStatus: state.system.metadata[ownProps.name].fetchStatus,
  label: state.system.metadata[ownProps.name].label,
  tags: state.system.metadata[ownProps.name].tags,
});

const mapDispatchToProps = (dispatch, ownProps) => ({
  fetchTagsInCollection: (tagId) => {
    switch (ownProps.id) {
      case TAG_SET_PUBLICATION_COUNTRY:
        dispatch(fetchMetadataValuesForCountry(tagId));
        break;
      case TAG_SET_PUBLICATION_STATE:
        dispatch(fetchMetadataValuesForState(tagId));
        break;
      case TAG_SET_PRIMARY_LANGUAGE:
        dispatch(fetchMetadataValuesForPrimaryLanguage(tagId));
        break;
      case TAG_SET_COUNTRY_OF_FOCUS:
        dispatch(fetchMetadataValuesForCountryOfFocus(tagId));
        break;
      case TAG_SET_MEDIA_TYPE:
        dispatch(fetchMetadataValuesForMediaType(tagId));
        break;
      default:
        break;
    }
  },
});

function mergeProps(stateProps, dispatchProps, ownProps) {
  return Object.assign({}, stateProps, dispatchProps, ownProps, {
    asyncFetch: () => {
      // these sets don't change, so only refetch them if you don't have them already in the store
      const alreadyLoadedTags = ((stateProps.fetchStatus === FETCH_SUCCEEDED) && (stateProps.tags.length > 0));
      if (!alreadyLoadedTags) {
        dispatchProps.fetchTagsInCollection(ownProps.id);
      }
    },
  });
}

export default
connect(mapStateToProps, mapDispatchToProps, mergeProps)(
  withIntlForm(
    withAsyncFetch(
      MetadataPickerContainer
    )
  )
);
<|endoftext|>


<commit_before>/***************************************************************************************************
 * WINGS.GLOBAL  --  contains: global variables and functions, function extensions, etc.
 **************************************************************************************************/

// Create module namespace
wingS.namespace("global");

/**
 * Global variables
 */
wingS.global.debugMode = false;      // This flag might be set in order to control debug outputs
wingS.global.asyncHeaderCount = 0;   // Count of headers which are currently loaded asynchronously
wingS.global.asyncHeaderQueue = [];  // Queue of functions each of which downloads an async header
wingS.global.asyncHeaderCalls = [];  // Callbacks which are invoked when all headers are available

/**
 * Callback method which initializes the current frame. This method is called upon each reload.
 * @param {Object} configObject - an object representing the desired initial configuration, i.e:
 *  - {String} eventEpoch - keeps the event epoch of this frame (needed for all events)
 *  - {String} reloadResource - stores the URI of the ReloadResource (without the event epoch)
 *  - {String} updateResource - stores the URI of the UpdateResource (without the event epoch)
 *  - {boolean} updateEnabled - a flag indicating if this frame allows incremental updates
 *  - {Object} updateCursor - update cursor configuration (enabled, image, width, height, dx, dy)
 *  - {Object} autoAdjustLayout - configuration for automatic layout adjustments (enabled, delay)
 */
wingS.global.init =  function(configObject) {
    // Initialize -wingS.global-
    wingS.global.eventEpoch = configObject.eventEpoch;
    wingS.global.reloadResource = configObject.reloadResource;
    wingS.global.updateResource = configObject.updateResource;
    wingS.global.updateEnabled = configObject.updateEnabled;
    wingS.global.updateCursor = configObject.updateCursor;
    wingS.global.autoAdjustLayout = configObject.autoAdjustLayout;

    // Initialize -wingS.ajax-
    wingS.ajax.requestIsActive = false;
    wingS.ajax.requestQueue = new Array();
    if (wingS.global.updateCursor.enabled) {
        wingS.ajax.activityCursor = new wingS.ajax.ActivityCursor();
    }

    wingS.ajax.callbackObject = {
        success : function(request) { wingS.ajax.processRequestSuccess(request); },
        failure : function(request) { wingS.ajax.processRequestFailure(request); },
        upload  : function(request) { wingS.ajax.processRequestSuccess(request); }
    };
    wingS.ajax.setActivityIndicatorsVisible(false);

    // Initialize -wingS.layout-
    if (wingS.global.autoAdjustLayout.enabled) {
        wingS.layout.callbackObject = {
            _tOutId : 0,
            _adjust : function () {
                var currentSize = wingS.global.windowSize();
                var lastSize = window.lastSize;
                if (currentSize[0] != lastSize[0] || currentSize[1] != lastSize[1]) {
                    wingS.request.reloadFrame();
                }
            },
            adjust : function () {
                clearTimeout(this._tOutId);
                var layout = this;
                this._tOutId = setTimeout(
                    function() { layout._adjust(); },
                    wingS.global.autoAdjustLayout.delay);
            }
        };
        var layout = wingS.layout.callbackObject;
        YAHOO.util.Event.addListener(window, 'resize', layout.adjust, layout, true);
        window.lastSize = wingS.global.windowSize();
    }

    // Try to set loglevel in firebug/lite
    if ("console" in window) {
        var loglevel = configObject.loglevel;
        if (loglevel) {
            switch (loglevel) {
            case "off":
                console.error = function(){};
                // fall-through
            case "error":
                console.warn = function(){};
                // fall-through
            case "warn":
                console.info = function(){};
                // fall-through
            case "info":
                console.debug = function(){};
                // fall-through
            case "debug":
                break;
            }
        }
    }
};

wingS.global.windowSize =  function() {
    var size = [];
    if (self.innerHeight) // all except Explorer
    {
        size[0] = self.innerWidth;
        size[1] = self.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight)
    // Explorer 6 Strict Mode
    {
        size[0] = document.documentElement.clientWidth;
        size[1] = document.documentElement.clientHeight;
    }
    else if (document.body) // other Explorers
    {
        size[0] = document.body.clientWidth;
        size[1] = document.body.clientHeight;
    }
    return size;
}

/**
 * Adds a callback function which is invoked when all (asynchronously loaded) headers are available.
 * @param {Function} callback - the callback function to invoke
 */
wingS.global.onHeadersLoaded = function(callback) {
    if (wingS.global.asyncHeaderCount == 0 &&
        wingS.global.asyncHeaderQueue.length == 0) {
        // If there is no header download going on we
        // are free to invoke this callback directly.
        callback();
    } else {
        // Otherwise we have to enqueue this callback
        wingS.global.asyncHeaderCalls.push(callback);
    }
};

/**
 * Increases a counter which indicates the number of headers (asynchronously) loaded at the moment.
 */
wingS.global.startLoadingHeader = function() {
    wingS.global.asyncHeaderCount++;
};

/**
 * Decreases a counter which indicates the number of headers (asynchronously) loaded at the moment.
 */
wingS.global.finishedLoadingHeader = function() {
    if (wingS.global.asyncHeaderCount > 0) {
        // Only if something is going on
        wingS.global.asyncHeaderCount--;
        wingS.global.dequeueNextHeader();
    }
};

/**
 * Enqueues the given header download if another one is still in action.
 * @param {Function} load - the function to load the header with
 * @param {Array} args - the arguments needed by the load function
 * @return {boolean} true, if header was enqueued, false otherwise
 */
wingS.global.enqueueThisHeader = function(load, args) {
    if (wingS.global.asyncHeaderCount > 0) { // Load one header after another
        // This is because header 2 might require header 1 to be fully loaded
        wingS.global.asyncHeaderQueue.push( {"load" : load, "args" : args} );
        return true;
    }
    return false;
};

/**
 * Grabs the next available header download from the queue and starts it.
 */
wingS.global.dequeueNextHeader = function() {
    if (wingS.global.asyncHeaderQueue.length > 0) {
        // Remove and start first enqueued header download
        var header = wingS.global.asyncHeaderQueue.shift();
        var args = header.args;
        header.load(args[0], args[1], args[2], args[3]);
    } else {
        // Invoke all callback methods which have registered interest
        for (var i = 0; i < wingS.global.asyncHeaderCalls.length; i++) {
            wingS.global.asyncHeaderCalls[i]();
        }
        // Clear all callbacks upon each new request
        wingS.global.asyncHeaderCalls = new Array();

        // Reset activity indicators and active flag
        wingS.ajax.setActivityIndicatorsVisible(false);
        wingS.ajax.requestIsActive = false;

        // Send the next enqueued request
        wingS.ajax.dequeueNextRequest();
    }
};

/**
 * Enables client debugging at a certain level
 */
wingS.global.setClientDebug = function(loglevel) {
   if (loglevel === undefined || loglevel === null || loglevel === "") {
       loglevel = "off";
   }

   wingS.util.setCookie("DEBUG", "javascript;loglevel="+loglevel,365,"/");

   window.location.reload();
};

//**************************************************************************************************

/**
 * Enables Firebug API support for Safari
 */
if (YAHOO.env.ua.webkit) {
    var wc = window.console;
    if (wc) {
        wc.debug = wc.log;
        wc.info = wc.log
        wc.warn = wc.log;
        wc.error = wc.log;
    }
}

/**
 * Moves the execution context of the function used upon to the given object. Useful when using
 * setTimeout or event handling, e.g.: setTimeout(func1.bind(someObject), 1); The function func1
 * will be called within the context of someObject. NB: Function object is extended by bind()!
 *
 * @param {Object} obj new execution context
 */
Function.prototype.bind = function(obj) {
    var method = this;
    temp = function() {
        return method.apply(obj, arguments);
    };

    return temp;
};<commit_msg>o patch provided by erikh:   submit page to retain form contents prio to reloading frame for relayouting the screen layout<commit_after>/***************************************************************************************************
 * WINGS.GLOBAL  --  contains: global variables and functions, function extensions, etc.
 **************************************************************************************************/

// Create module namespace
wingS.namespace("global");

/**
 * Global variables
 */
wingS.global.debugMode = false;      // This flag might be set in order to control debug outputs
wingS.global.asyncHeaderCount = 0;   // Count of headers which are currently loaded asynchronously
wingS.global.asyncHeaderQueue = [];  // Queue of functions each of which downloads an async header
wingS.global.asyncHeaderCalls = [];  // Callbacks which are invoked when all headers are available

/**
 * Callback method which initializes the current frame. This method is called upon each reload.
 * @param {Object} configObject - an object representing the desired initial configuration, i.e:
 *  - {String} eventEpoch - keeps the event epoch of this frame (needed for all events)
 *  - {String} reloadResource - stores the URI of the ReloadResource (without the event epoch)
 *  - {String} updateResource - stores the URI of the UpdateResource (without the event epoch)
 *  - {boolean} updateEnabled - a flag indicating if this frame allows incremental updates
 *  - {Object} updateCursor - update cursor configuration (enabled, image, width, height, dx, dy)
 *  - {Object} autoAdjustLayout - configuration for automatic layout adjustments (enabled, delay)
 */
wingS.global.init =  function(configObject) {
    // Initialize -wingS.global-
    wingS.global.eventEpoch = configObject.eventEpoch;
    wingS.global.reloadResource = configObject.reloadResource;
    wingS.global.updateResource = configObject.updateResource;
    wingS.global.updateEnabled = configObject.updateEnabled;
    wingS.global.updateCursor = configObject.updateCursor;
    wingS.global.autoAdjustLayout = configObject.autoAdjustLayout;

    // Initialize -wingS.ajax-
    wingS.ajax.requestIsActive = false;
    wingS.ajax.requestQueue = new Array();
    if (wingS.global.updateCursor.enabled) {
        wingS.ajax.activityCursor = new wingS.ajax.ActivityCursor();
    }

    wingS.ajax.callbackObject = {
        success : function(request) { wingS.ajax.processRequestSuccess(request); },
        failure : function(request) { wingS.ajax.processRequestFailure(request); },
        upload  : function(request) { wingS.ajax.processRequestSuccess(request); }
    };
    wingS.ajax.setActivityIndicatorsVisible(false);

    // Initialize -wingS.layout-
    if (wingS.global.autoAdjustLayout.enabled) {
        wingS.layout.callbackObject = {
            _tOutId : 0,
            _adjust : function () {
                var currentSize = wingS.global.windowSize();
                var lastSize = window.lastSize;
                if (currentSize[0] != lastSize[0] || currentSize[1] != lastSize[1]) {
                    wingS.request.sendEvent(null,true,false);
                    wingS.request.reloadFrame();
                }
            },
            adjust : function () {
                clearTimeout(this._tOutId);
                var layout = this;
                this._tOutId = setTimeout(
                    function() { layout._adjust(); },
                    wingS.global.autoAdjustLayout.delay);
            }
        };
        var layout = wingS.layout.callbackObject;
        YAHOO.util.Event.addListener(window, 'resize', layout.adjust, layout, true);
        window.lastSize = wingS.global.windowSize();
    }

    // Try to set loglevel in firebug/lite
    if ("console" in window) {
        var loglevel = configObject.loglevel;
        if (loglevel) {
            switch (loglevel) {
            case "off":
                console.error = function(){};
                // fall-through
            case "error":
                console.warn = function(){};
                // fall-through
            case "warn":
                console.info = function(){};
                // fall-through
            case "info":
                console.debug = function(){};
                // fall-through
            case "debug":
                break;
            }
        }
    }
};

wingS.global.windowSize =  function() {
    var size = [];
    if (self.innerHeight) // all except Explorer
    {
        size[0] = self.innerWidth;
        size[1] = self.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight)
    // Explorer 6 Strict Mode
    {
        size[0] = document.documentElement.clientWidth;
        size[1] = document.documentElement.clientHeight;
    }
    else if (document.body) // other Explorers
    {
        size[0] = document.body.clientWidth;
        size[1] = document.body.clientHeight;
    }
    return size;
}

/**
 * Adds a callback function which is invoked when all (asynchronously loaded) headers are available.
 * @param {Function} callback - the callback function to invoke
 */
wingS.global.onHeadersLoaded = function(callback) {
    if (wingS.global.asyncHeaderCount == 0 &&
        wingS.global.asyncHeaderQueue.length == 0) {
        // If there is no header download going on we
        // are free to invoke this callback directly.
        callback();
    } else {
        // Otherwise we have to enqueue this callback
        wingS.global.asyncHeaderCalls.push(callback);
    }
};

/**
 * Increases a counter which indicates the number of headers (asynchronously) loaded at the moment.
 */
wingS.global.startLoadingHeader = function() {
    wingS.global.asyncHeaderCount++;
};

/**
 * Decreases a counter which indicates the number of headers (asynchronously) loaded at the moment.
 */
wingS.global.finishedLoadingHeader = function() {
    if (wingS.global.asyncHeaderCount > 0) {
        // Only if something is going on
        wingS.global.asyncHeaderCount--;
        wingS.global.dequeueNextHeader();
    }
};

/**
 * Enqueues the given header download if another one is still in action.
 * @param {Function} load - the function to load the header with
 * @param {Array} args - the arguments needed by the load function
 * @return {boolean} true, if header was enqueued, false otherwise
 */
wingS.global.enqueueThisHeader = function(load, args) {
    if (wingS.global.asyncHeaderCount > 0) { // Load one header after another
        // This is because header 2 might require header 1 to be fully loaded
        wingS.global.asyncHeaderQueue.push( {"load" : load, "args" : args} );
        return true;
    }
    return false;
};

/**
 * Grabs the next available header download from the queue and starts it.
 */
wingS.global.dequeueNextHeader = function() {
    if (wingS.global.asyncHeaderQueue.length > 0) {
        // Remove and start first enqueued header download
        var header = wingS.global.asyncHeaderQueue.shift();
        var args = header.args;
        header.load(args[0], args[1], args[2], args[3]);
    } else {
        // Invoke all callback methods which have registered interest
        for (var i = 0; i < wingS.global.asyncHeaderCalls.length; i++) {
            wingS.global.asyncHeaderCalls[i]();
        }
        // Clear all callbacks upon each new request
        wingS.global.asyncHeaderCalls = new Array();

        // Reset activity indicators and active flag
        wingS.ajax.setActivityIndicatorsVisible(false);
        wingS.ajax.requestIsActive = false;

        // Send the next enqueued request
        wingS.ajax.dequeueNextRequest();
    }
};

/**
 * Enables client debugging at a certain level
 */
wingS.global.setClientDebug = function(loglevel) {
   if (loglevel === undefined || loglevel === null || loglevel === "") {
       loglevel = "off";
   }

   wingS.util.setCookie("DEBUG", "javascript;loglevel="+loglevel,365,"/");

   window.location.reload();
};

//**************************************************************************************************

/**
 * Enables Firebug API support for Safari
 */
if (YAHOO.env.ua.webkit) {
    var wc = window.console;
    if (wc) {
        wc.debug = wc.log;
        wc.info = wc.log
        wc.warn = wc.log;
        wc.error = wc.log;
    }
}

/**
 * Moves the execution context of the function used upon to the given object. Useful when using
 * setTimeout or event handling, e.g.: setTimeout(func1.bind(someObject), 1); The function func1
 * will be called within the context of someObject. NB: Function object is extended by bind()!
 *
 * @param {Object} obj new execution context
 */
Function.prototype.bind = function(obj) {
    var method = this;
    temp = function() {
        return method.apply(obj, arguments);
    };

    return temp;
};
<|endoftext|>


<commit_before>var spawn = require('child_process').spawn;
var path = require('path');

var _ = require('underscore');

var child = spawn('REG', ['QUERY', path.normalize('HKLM/SOFTWARE/JavaSoft')]);

child.on('close', function(err) {
	if (err) {
		console.log('Error comand !' + err);
		console.log(child.output);
	} else {}
});

child.stdout.on('data', function(data) {
	//console.log('STDOUT:' + data);
	parseKey(data.toString('utf8'), 'JavaHome');
});
child.stderr.on('data', function(data) {
	console.log('STDERR:' + data);
});

function parseKey(data, searched, callBack) {
	//console.dir(data.split('\r\n'));
	var items = data.split('\r\n');
	for (var i = 0; i < items.length; ++i) {
		var keys = items[i].split('    ');
		if (keys.length === 4) {
			if (keys[1] === searched) {
				console.log(keys[1]);
				return keys;
			}
		}
	}

}<commit_msg>searching path implemented.<commit_after>var spawn = require('child_process').spawn;
var path = require('path');

var _ = require('underscore');

var child = spawn('reg', ['QUERY', 'HKLM']);

var child = spawn('REG', ['QUERY', path.normalize('HKLM/SOFTWARE/')]);

child.on('close', function(err) {
	if (err) {
		console.log('Error comand !' + err);

	} else {}
});

function parseKey(data, searched) {
	//console.dir(data.split('\r\n'));
	var items = data.split('\r\n');
	//console.log(data);
	if (data.search(new RegExp(searched, 'gmi')) !== -1) {
		for (var i = 0; i < items.length; ++i) {
			var keys = items[i].split('    ');
			if (keys.length === 4) {
				if (keys[1] === searched) {
					return {
						name: keys[1],
						type: keys[2],
						value: keys[3]
					};
				}
			}
		}
	}
	return null;
}

function searchPaths(firstPath, searched, callBack) {
	// recursively search.
	var activeChild = 0;
	var closedChild = 0;
	var dataFounded = [];
	var errorFounded = [];

	function searchPath(firstPath, searched) {

		if (firstPath && firstPath.split('    ').length === 1 && firstPath !== '') {
			var child = spawn('reg', ['QUERY', firstPath.replace(/\//gm, path.sep)]);
			++activeChild;
			var bufferStdOut = new Buffer('');
			var bufferStdErr = new Buffer('');
			child.stdout.on('data', function(data) {
				bufferStdOut += data;
			});
			child.on('close', function(code) {
				++closedChild;
				if (code === 0) {
					var dataStr = bufferStdOut.toString('utf8');
					var splitData = dataStr.split('\r\n');
					var res = parseKey(dataStr, searched);
					if (res === null) {
						_.each(splitData, function(item) {
							if (item !== firstPath) {
								searchPath(item, searched);
							}
						});

					} else {
						dataFounded.push(res);
					}
				} else {
					errorFounded.push({
						err: 'REG Error !',
						msg: bufferStdErr.toString('utf8')
					});
				}
				if (activeChild === closedChild) {
					if (errorFounded.length === 0) {
						callBack(null, dataFounded);
					} else {

						callBack(errorFounded, dataFounded);
					}
				}
			});

			child.stderr.on('data', function(data) {
				bufferStdErr += data
			});
		}
	}

	searchPath(firstPath, searched);
}

searchPaths('HKLM/SOFTWARE/Wow6432Node/JavaSoft', 'JavaHome', function(err, data) {
	if (err) {
		console.dir(err.msg);
	} else {
		if (data) {
			console.dir(data);
			process.exit();
		}
	}
});<|endoftext|>