<commit_before>var Util, DOM;

(function (Util, DOMTree) {
    'use strict';

    var Loader      = Util.extendProto(LoaderProto),
        DOMProto    = Object.getPrototypeOf(DOMTree);

    Util.extend(DOMProto, Loader);

    function LoaderProto() {
        var Images  = DOM.Images,
            Events  = DOM.Events,
            Loader  = this;

        /**
         * Function gets id by src
         * @param pSrc
         *
         * Example: http://domain.com/1.js -> 1_js
         */
        this.getIdBySrc             = function(pSrc) {
            var lRet    = Util.isString(pSrc);

            if (lRet) {
                var lNum    = pSrc.lastIndexOf('/') + 1,
                    lSub    = pSrc.substr(pSrc, lNum),
                    lID     = Util.removeStrOneTime(pSrc, lSub );

                /* убираем точки */
                while (lID.indexOf('.') > 0)
                    lID = lID.replace('.', '_');

                lRet = lID;
            }

            return lRet;
        };

        /**
         * load file countent thrue ajax
         *
         * @param pParams
         */
        this.ajax                    = function(pParams) {
            var xhr, p, lType,
                lRet        = Util.checkObjTrue(pParams, ['url', 'success']);

            if (lRet) {
                p           = pParams,
                lType       = p.type || p.method || 'GET';
                xhr         = new XMLHttpRequest();

                xhr.open(lType, pParams.url, true);

                if (p.responseType)
                    xhr.responseType = p.responseType;

                Events.add('progress', function(event) {
                    var percent, count, msg;

                    if (event.lengthComputable) {
                        percent = (event.loaded / event.total) * 100,
                        count   = Math.round(percent),
                        msg     = lType + ' ' + p.url + ': ' + count + '%';
                        Util.log(msg);
                    }

                  }, xhr.upload);

                Events.add('readystatechange', function(pEvent) {
                    if (xhr.readyState === 4 /* Complete */) {
                        var lJqXHR      = pEvent.target,
                            TYPE_JSON   = 'application/json',
                            lType       = xhr.getResponseHeader('content-type');

                        if (xhr.status === 200 /* OK */) {
                            var lData = lJqXHR.response;

                            if (p.dataType !== 'text')
                                /* If it's json - parse it as json */
                                if (lType && Util.isContainStr(lType, TYPE_JSON))
                                    lData = Util.parseJSON(lJqXHR.response) || lJqXHR.response;

                                Util.exec(p.success, lData, lJqXHR.statusText, lJqXHR);
                        }
                        /* file not found or connection lost */
                        else {
                            /* if html given or something like thet
                             * getBack just status of result
                             */
                            if (lType && lType.indexOf('text/plain') !== 0)
                                lJqXHR.responseText = lJqXHR.statusText;

                            Util.exec(p.error, lJqXHR);
                        }
                    }
                }, xhr);

                xhr.send(p.data);
            }

            return lRet;
        };

        /**
         * create elements and load them to DOM-tree
         * one-by-one
         *
         * @param params
         * @param callback - onload function
         */
        this.anyLoadOnLoad          = function(params, callback) {
            if (Util.isArray(params)) {
                var param   = params.shift(),
                    func    = function() {
                        Loader.anyLoadOnLoad(params, callback);
                    };

                if (Util.isString(param))
                    param = {
                        src : param
                    };
                else if (Util.isArray(param))
                    Loader.anyLoadInParallel(param, callback);

                if (param && !param.func) {
                    param.func = func;

                    Loader.anyload(param);

                } else
                    Util.exec(callback);
            }

            return Loader;
        };

        /**
         * improve callback of funcs so
         * we pop number of function and
         * if it's last we call pCallBack
         *
         * @param pParams_a
         * @param pFunc - onload function
         */
        this.anyLoadInParallel        = function(pParams_a, pFunc) {
            var lDone = [],

                lDoneFunc = function (pCallBack) {
                    Util.exec(pCallBack);

                    if (!lDone.pop())
                        Util.exec(pFunc);
                };

            if (!Util.isArray(pParams_a)) {
                pParams_a = [pParams_a];
            }

            for(var i = 0, n = pParams_a.length; i < n; i++) {
                var lParam = pParams_a.pop();

                if (lParam) {
                    lDone.push(i);

                    if (Util.isString(lParam))
                        lParam = { src : lParam };

                    var lFunc = lParam.func;
                    lParam.func = Util.retExec(lDoneFunc, lFunc);

                    Loader.anyload(lParam);
                }
            }

            return Loader;
        };

        /**
         * Функция создаёт элемент и загружает файл с src.
         *
         * @param pParams_o = {
         * name, - название тэга
         * src', - путь к файлу
         * func, - обьект, содержаий одну из функций
         *          или сразу две onload и onerror
         *          {onload: function() {}, onerror: function();}
         * style,
         * id,
         * element,
         * async, - true by default
         * inner: 'id{color:red, },
         * class,
         * not_append - false by default
         * }
         */
        this.anyload                 = function(pParams_o) {
            var i, n, lElements_a;

            if (!pParams_o ) return;

            /* if a couple of params was
             * processing every of params
             * and quit
             */
            if (Util.isArray(pParams_o)) {
                lElements_a = [];
                for(i = 0, n = pParams_o.length; i < n ; i++)
                    lElements_a[i] = this.anyload(pParams_o[i]);

                return lElements_a;
            }

            var lName       = pParams_o.name,
                lAttr       = pParams_o.attribute,
                lID         = pParams_o.id,
                lClass      = pParams_o.className,
                lSrc        = pParams_o.src,
                lFunc       = pParams_o.func,
                lOnError,
                lAsync      = pParams_o.async,
                lParent     = pParams_o.parent || document.body,
                lInner      = pParams_o.inner,
                lStyle      = pParams_o.style,
                lNotAppend  = pParams_o.not_append;

            if (Util.isObject(lFunc)) {
                lOnError = lFunc.onerror;
                lFunc  = lFunc.onload;
            }
            /* убираем путь к файлу, оставляя только название файла */
            if (!lID && lSrc)
                lID = DOM.getIdBySrc(lSrc);

            var lElement = DOMTree.getById(lID);

            /* если скрипт еще не загружен */
            if (!lElement) {
                if (!lName && lSrc) {

                    var lDot = lSrc.lastIndexOf('.'),
                        lExt =  lSrc.substr(lDot);
                    switch(lExt) {
                        case '.js':
                            lName = 'script';
                            break;
                        case '.css':
                            lName = 'link';
                            lParent = document.head;
                            break;
                        default:
                            return {code: -1, text: 'name can not be empty'};
                    }
                }
                lElement                = document.createElement(lName);

                if (lID)
                    lElement.id         = lID;

                if (lClass)
                    lElement.className  = lClass;

                if (lSrc) {
                    /* if work with css use href */
                    if (lName === 'link') {
                        lElement.href = lSrc;
                        lElement.rel = 'stylesheet';
                    } else
                        lElement.src  = lSrc;

                    /*
                     * if passed arguments function
                     * then it's onload by default
                     *
                     * if object - then onload and onerror
                     */
                    var lLoad     = function(pEvent) {
                            Events.remove('load', lLoad, lElement);
                            Events.remove('error', lError, lElement);

                            Util.exec(lFunc, pEvent);
                        },

                        lError    = function() {
                            lParent.removeChild(lElement);

                            Images.showError({
                                responseText: 'file ' +
                                lSrc                  +
                                ' could not be loaded',
                                status : 404
                            });

                            Util.exec(lOnError);
                        };

                    Events.add('load', lLoad, lElement);
                    Events.addError(lError, lElement);
                }

                if (lAttr)
                    for(i in lAttr)
                        lElement.setAttribute(i, lAttr[i]);

                if (lStyle)
                    lElement.style.cssText = lStyle;

                if (lAsync || lAsync === undefined)
                    lElement.async = true;

                if (!lNotAppend)
                    lParent.appendChild(lElement);

                if (lInner)
                    lElement.innerHTML = lInner;
            }
            /* если js-файл уже загружен
             * запускаем функцию onload
             */
            else
                Util.exec(lFunc);

            return lElement;
        },

        /**
         * Функция загружает js-файл
         *
         * @param pSrc
         * @param pFunc
         */
        this.jsload                  = function(pSrc, pFunc) {
            var lRet = Loader.anyload({
                name : 'script',
                src  : pSrc,
                func : pFunc
            });

            return lRet;
        },

        /**
         * returns jsload functions
         */
        this.retJSLoad               = function(pSrc, pFunc) {
            var lRet = function() {
                return Loader.jsload(pSrc, pFunc);
            };

            return lRet;
        },

        /**
         * Функция создаёт елемент style и записывает туда стили
         * @param pParams_o - структура параметров, заполняеться таким
         * образом: {src: ' ',func: '', id: '', element: '', inner: ''}
         * все параметры опциональны
         */
        this.cssSet                  = function(pParams_o) {
            pParams_o.name      = 'style';
            pParams_o.parent    = pParams_o.parent || document.head;

            return Loader.anyload(pParams_o);
        },

        /**
         * Function loads external css files
         * @pParams_o - структура параметров, заполняеться таким
         * образом: {src: ' ',func: '', id: '', element: '', inner: ''}
         * все параметры опциональны
         */
        this.cssLoad                 = function(pParams_o) {
             if (Util.isArray(pParams_o)) {
                for(var i = 0, n = pParams_o.length; i < n; i++) {
                    pParams_o[i].name = 'link';
                    pParams_o[i].parent   = pParams_o.parent || document.head;
                }

                return Loader.anyload(pParams_o);
            }

            else if (Util.isString(pParams_o))
                pParams_o = { src: pParams_o };

            pParams_o.name      = 'link';
            pParams_o.parent    = pParams_o.parent || document.head;

            return Loader.anyload(pParams_o);
        };

        /**
         * load jquery from google cdn or local copy
         * @param pParams
         */
        this.jquery                     = function(pParams) {
            if (!pParams)
                pParams = {};
            /* загружаем jquery: */
            Loader.jsload('//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',{
                onload  : pParams.onload,
                onerror : pParams.onerror
            });
        };
    }
})(Util, DOM);
<commit_msg>refactor(loader) anyLoadOnLoad<commit_after>var Util, DOM;

(function (Util, DOMTree) {
    'use strict';

    var Loader      = Util.extendProto(LoaderProto),
        DOMProto    = Object.getPrototypeOf(DOMTree);

    Util.extend(DOMProto, Loader);

    function LoaderProto() {
        var Images  = DOM.Images,
            Events  = DOM.Events,
            Loader  = this;

        /**
         * Function gets id by src
         * @param pSrc
         *
         * Example: http://domain.com/1.js -> 1_js
         */
        this.getIdBySrc             = function(pSrc) {
            var lRet    = Util.isString(pSrc);

            if (lRet) {
                var lNum    = pSrc.lastIndexOf('/') + 1,
                    lSub    = pSrc.substr(pSrc, lNum),
                    lID     = Util.removeStrOneTime(pSrc, lSub );

                /* убираем точки */
                while (lID.indexOf('.') > 0)
                    lID = lID.replace('.', '_');

                lRet = lID;
            }

            return lRet;
        };

        /**
         * load file countent thrue ajax
         *
         * @param pParams
         */
        this.ajax                    = function(pParams) {
            var xhr, p, lType,
                lRet        = Util.checkObjTrue(pParams, ['url', 'success']);

            if (lRet) {
                p           = pParams,
                lType       = p.type || p.method || 'GET';
                xhr         = new XMLHttpRequest();

                xhr.open(lType, pParams.url, true);

                if (p.responseType)
                    xhr.responseType = p.responseType;

                Events.add('progress', function(event) {
                    var percent, count, msg;

                    if (event.lengthComputable) {
                        percent = (event.loaded / event.total) * 100,
                        count   = Math.round(percent),
                        msg     = lType + ' ' + p.url + ': ' + count + '%';
                        Util.log(msg);
                    }

                  }, xhr.upload);

                Events.add('readystatechange', function(pEvent) {
                    if (xhr.readyState === 4 /* Complete */) {
                        var lJqXHR      = pEvent.target,
                            TYPE_JSON   = 'application/json',
                            lType       = xhr.getResponseHeader('content-type');

                        if (xhr.status === 200 /* OK */) {
                            var lData = lJqXHR.response;

                            if (p.dataType !== 'text')
                                /* If it's json - parse it as json */
                                if (lType && Util.isContainStr(lType, TYPE_JSON))
                                    lData = Util.parseJSON(lJqXHR.response) || lJqXHR.response;

                                Util.exec(p.success, lData, lJqXHR.statusText, lJqXHR);
                        }
                        /* file not found or connection lost */
                        else {
                            /* if html given or something like thet
                             * getBack just status of result
                             */
                            if (lType && lType.indexOf('text/plain') !== 0)
                                lJqXHR.responseText = lJqXHR.statusText;

                            Util.exec(p.error, lJqXHR);
                        }
                    }
                }, xhr);

                xhr.send(p.data);
            }

            return lRet;
        };

        /**
         * create elements and load them to DOM-tree
         * one-by-one
         *
         * @param params
         * @param callback - onload function
         */
        this.anyLoadOnLoad          = function(params, callback) {
            if (Util.isArray(params)) {
                var param   = params.shift(),
                    func    = function() {
                        Loader.anyLoadOnLoad(params, callback);
                    };

                if (!param)
                    Util.exec(callback);

                else if (Util.isArray(param))
                    Loader.anyLoadInParallel(param, callback);

                else {
                    if (Util.isString(param))
                        param = {
                            src : param
                        };

                    if (!param.func)
                        param.func = func;

                    Loader.anyload(param);
                }
            }

            return Loader;
        };

        /**
         * improve callback of funcs so
         * we pop number of function and
         * if it's last we call pCallBack
         *
         * @param pParams_a
         * @param pFunc - onload function
         */
        this.anyLoadInParallel        = function(pParams_a, pFunc) {
            var lDone = [],

                lDoneFunc = function (pCallBack) {
                    Util.exec(pCallBack);

                    if (!lDone.pop())
                        Util.exec(pFunc);
                };

            if (!Util.isArray(pParams_a)) {
                pParams_a = [pParams_a];
            }

            for(var i = 0, n = pParams_a.length; i < n; i++) {
                var lParam = pParams_a.pop();

                if (lParam) {
                    lDone.push(i);

                    if (Util.isString(lParam))
                        lParam = { src : lParam };

                    var lFunc = lParam.func;
                    lParam.func = Util.retExec(lDoneFunc, lFunc);

                    Loader.anyload(lParam);
                }
            }

            return Loader;
        };

        /**
         * Функция создаёт элемент и загружает файл с src.
         *
         * @param pParams_o = {
         * name, - название тэга
         * src', - путь к файлу
         * func, - обьект, содержаий одну из функций
         *          или сразу две onload и onerror
         *          {onload: function() {}, onerror: function();}
         * style,
         * id,
         * element,
         * async, - true by default
         * inner: 'id{color:red, },
         * class,
         * not_append - false by default
         * }
         */
        this.anyload                 = function(pParams_o) {
            var i, n, lElements_a;

            if (!pParams_o ) return;

            /* if a couple of params was
             * processing every of params
             * and quit
             */
            if (Util.isArray(pParams_o)) {
                lElements_a = [];
                for(i = 0, n = pParams_o.length; i < n ; i++)
                    lElements_a[i] = this.anyload(pParams_o[i]);

                return lElements_a;
            }

            var lName       = pParams_o.name,
                lAttr       = pParams_o.attribute,
                lID         = pParams_o.id,
                lClass      = pParams_o.className,
                lSrc        = pParams_o.src,
                lFunc       = pParams_o.func,
                lOnError,
                lAsync      = pParams_o.async,
                lParent     = pParams_o.parent || document.body,
                lInner      = pParams_o.inner,
                lStyle      = pParams_o.style,
                lNotAppend  = pParams_o.not_append;

            if (Util.isObject(lFunc)) {
                lOnError = lFunc.onerror;
                lFunc  = lFunc.onload;
            }
            /* убираем путь к файлу, оставляя только название файла */
            if (!lID && lSrc)
                lID = DOM.getIdBySrc(lSrc);

            var lElement = DOMTree.getById(lID);

            /* если скрипт еще не загружен */
            if (!lElement) {
                if (!lName && lSrc) {

                    var lDot = lSrc.lastIndexOf('.'),
                        lExt =  lSrc.substr(lDot);
                    switch(lExt) {
                        case '.js':
                            lName = 'script';
                            break;
                        case '.css':
                            lName = 'link';
                            lParent = document.head;
                            break;
                        default:
                            return {code: -1, text: 'name can not be empty'};
                    }
                }
                lElement                = document.createElement(lName);

                if (lID)
                    lElement.id         = lID;

                if (lClass)
                    lElement.className  = lClass;

                if (lSrc) {
                    /* if work with css use href */
                    if (lName === 'link') {
                        lElement.href = lSrc;
                        lElement.rel = 'stylesheet';
                    } else
                        lElement.src  = lSrc;

                    /*
                     * if passed arguments function
                     * then it's onload by default
                     *
                     * if object - then onload and onerror
                     */
                    var lLoad     = function(pEvent) {
                            Events.remove('load', lLoad, lElement);
                            Events.remove('error', lError, lElement);

                            Util.exec(lFunc, pEvent);
                        },

                        lError    = function() {
                            lParent.removeChild(lElement);

                            Images.showError({
                                responseText: 'file ' +
                                lSrc                  +
                                ' could not be loaded',
                                status : 404
                            });

                            Util.exec(lOnError);
                        };

                    Events.add('load', lLoad, lElement);
                    Events.addError(lError, lElement);
                }

                if (lAttr)
                    for(i in lAttr)
                        lElement.setAttribute(i, lAttr[i]);

                if (lStyle)
                    lElement.style.cssText = lStyle;

                if (lAsync || lAsync === undefined)
                    lElement.async = true;

                if (!lNotAppend)
                    lParent.appendChild(lElement);

                if (lInner)
                    lElement.innerHTML = lInner;
            }
            /* если js-файл уже загружен
             * запускаем функцию onload
             */
            else
                Util.exec(lFunc);

            return lElement;
        },

        /**
         * Функция загружает js-файл
         *
         * @param pSrc
         * @param pFunc
         */
        this.jsload                  = function(pSrc, pFunc) {
            var lRet = Loader.anyload({
                name : 'script',
                src  : pSrc,
                func : pFunc
            });

            return lRet;
        },

        /**
         * returns jsload functions
         */
        this.retJSLoad               = function(pSrc, pFunc) {
            var lRet = function() {
                return Loader.jsload(pSrc, pFunc);
            };

            return lRet;
        },

        /**
         * Функция создаёт елемент style и записывает туда стили
         * @param pParams_o - структура параметров, заполняеться таким
         * образом: {src: ' ',func: '', id: '', element: '', inner: ''}
         * все параметры опциональны
         */
        this.cssSet                  = function(pParams_o) {
            pParams_o.name      = 'style';
            pParams_o.parent    = pParams_o.parent || document.head;

            return Loader.anyload(pParams_o);
        },

        /**
         * Function loads external css files
         * @pParams_o - структура параметров, заполняеться таким
         * образом: {src: ' ',func: '', id: '', element: '', inner: ''}
         * все параметры опциональны
         */
        this.cssLoad                 = function(pParams_o) {
             if (Util.isArray(pParams_o)) {
                for(var i = 0, n = pParams_o.length; i < n; i++) {
                    pParams_o[i].name = 'link';
                    pParams_o[i].parent   = pParams_o.parent || document.head;
                }

                return Loader.anyload(pParams_o);
            }

            else if (Util.isString(pParams_o))
                pParams_o = { src: pParams_o };

            pParams_o.name      = 'link';
            pParams_o.parent    = pParams_o.parent || document.head;

            return Loader.anyload(pParams_o);
        };

        /**
         * load jquery from google cdn or local copy
         * @param pParams
         */
        this.jquery                     = function(pParams) {
            if (!pParams)
                pParams = {};
            /* загружаем jquery: */
            Loader.jsload('//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js',{
                onload  : pParams.onload,
                onerror : pParams.onerror
            });
        };
    }
})(Util, DOM);
<|endoftext|>


<commit_before>/**
 * Author: Umayr Shahid <umayrr@hotmail.com>,
 * Created: 20:56, 06/09/15.
 */

'use strict';

const TYPES = {
  DATE: ['before', 'after'],
  NUMBER: ['greater', 'smaller', 'min', 'max', 'divisible'],
  STRING: ['contains', 'alphanumeric', 'equals', 'alpha', 'len', 'length', 'lowercase', 'uppercase'],
  STANDALONE: ['email', 'regex', 'url', 'json', 'ip', 'ipv4', 'ipv6', 'uuid', 'uuidv3', 'uuidv4', 'uuidv5', 'array', 'creditcard', 'int', 'float', 'decimal', 'date', 'hexadecimal', 'hexacolor'],
  BOOL: ['boolean'],
  ARRAY: ['in'],
  NONE: ['empty']
};

const STANDALONE = {
  EMAIL: 'email address',
  CREDITCARD: 'credit card number',
  INT: 'integer value',
  FLOAT: 'float value',
  DECIMAL: 'decimal value',
  IP: 'ip address',
  IPV4: 'ipv4 address',
  IPV6: 'ipv6 address',
  JSON: 'json string'
};

const STRING = {
  LOWERCASE: 'consist of lowercase letters',
  UPPERCASE: 'consist of uppercase letters',
  ALPHA: 'consist of only letters',
  ALPHANUMERIC: 'consist of only letters & numbers',
  EQUALS: 'equal to %s',
  CONTAINS: 'contains %s in it',
  LEN: 'between %s to %s characters',
  LENGTH: 'between %s to %s characters',
  ATLEAST: 'at least %s characters long'
};

const NUMBER = {
  GREATER: 'greater than %s',
  SMALLER: 'smaller than %s',
  MIN: 'minimum %s',
  MAX: 'maximum %s',
  DIVISIBLE: 'divisible by %s'
};

const BOOL = {
  BOOLEAN: 'either %s or %s'
};

const ARRAY = {
  BINARY: 'either %s or %s',
  N: 'one of these values (%s)',
  ONE: 'equal to %s'
};

import { format } from 'util';

import { humanize, flatten } from '../utils';

export default class Parser {

  /**
   * Static method to parse operator.
   *
   * Possible inputs can be:
   * - Positives: empty, isEmpty, !notEmpty, !isNotEmpty
   * - Negatives: !empty, !isEmpty, notEmpty
   * @param operator
   * @returns {*[]}
   */
  static operator(operator) {
    let _count = 0;
    let _not = false;
    let _operator;
    let _type;

    if (operator.includes('!')) {
      _not = !_not;
      _count++;
    }
    if (operator.substr(0, 3).toLowerCase().includes('is')) _count += 2;
    if (operator.includes('not')) {
      _not = !_not;
      _count += 3;
    }

    _operator = operator.substr(_count, operator.length).toLowerCase();
    _type = Parser.type(_operator);

    return [_not, _operator, _type];
  }

  /**
   * Static method to get the type of the operator.
   *
   * @param operator
   * @returns {string}
   */
  static type(operator) {
    if (!Parser.isSupported(operator)) throw new Error(`Provided operator \`${operator}\` is not supported.`);
    for (let type of Object.keys(TYPES)) {
      if (TYPES[type].includes(operator)) return String(type).toLowerCase();
    }
  }

  /**
   * Static method that wraps all type wise operations.
   *
   * @returns {*}
   */
  static get methods() {
    return {
      date() {
        let [_operator, _args] = Array.from(arguments);
        return `${_operator} than ${ humanize(_args) }`;
      },
      number() {
        let [_operator, _args] = Array.from(arguments);
        return `${format(NUMBER[_operator.toUpperCase()], _args) || _operator }`;
      },
      string() {
        let [_operator, _args] = Array.from(arguments);
        let _msg;

        if (_operator === 'len' || _operator === 'length' || _operator === 'equals' || _operator === 'contains') {
          if ((_operator === 'len' || _operator === 'length') && _args.length === 1) _operator = 'atleast';
          _msg = format(STRING[_operator.toUpperCase()], ..._args);
        }
        else _msg = `${ STRING[_operator.toUpperCase()] || _operator }`;

        return _msg;
      },
      standalone() {
        let [_operator] = Array.from(arguments);
        return `a valid ${ STANDALONE[_operator.toUpperCase()] || _operator }`;
      },
      bool() {
        let [_operator, _args] = Array.from(arguments);
        return `${format(BOOL[_operator.toUpperCase()], ..._args) || _operator }`;
      },
      array() {
        let [, _args] = Array.from(arguments);
        let _msg;

        if (Array.isArray(_args)) _args = flatten(_args);

        if (_args.length === 2) _msg = `${ format(ARRAY['BINARY'], ..._args) }`;
        else if (_args.length > 2) _msg = `${ format(ARRAY['N'], _args.join(', ')) }`;
        else _msg = `${ format(ARRAY['ONE'], typeof _args === 'object' ? JSON.stringify(_args[0]) : _args[0]) }`;

        return _msg;
      },
      none(operator) {
        return operator;
      }
    };
  }

  /**
   * Return true if provided operator is valid.
   *
   * @param operator
   * @returns {*}
   */
  static isSupported(operator) {
    let _all = [];
    for (let type of Object.keys(TYPES)) {
      _all.push(...TYPES[type]);
    }
    return Parser._containsAny(operator.toLowerCase(), _all);
  }

  /**
   * Search through an array and returns true if any value of array matches the provided needle.
   *
   * @param needle
   * @param haystack
   * @returns {boolean}
   * @private
   */
  static _containsAny(needle, haystack) {
    for (let straw of haystack) {
      if (needle.includes(straw)) return true;
    }
    return false;
  }

  /**
   * Parse arguments.
   *
   * @returns {*[]}
   */
  static args() {
    let [_first, _second, _third] = Array.from(arguments);
    return Parser.isSupported(_first) ? [_third, _first, _second] : [_first, _second, _third];
  }
}
<commit_msg>Fix #6<commit_after>/**
 * Author: Umayr Shahid <umayrr@hotmail.com>,
 * Created: 20:56, 06/09/15.
 */

'use strict';

const TYPES = {
  DATE: ['before', 'after'],
  NUMBER: ['greater', 'smaller', 'min', 'max', 'divisible'],
  STRING: ['contains', 'alphanumeric', 'numeric', 'equals', 'alpha', 'len', 'length', 'lowercase', 'uppercase'],
  STANDALONE: ['email', 'regex', 'url', 'json', 'ip', 'ipv4', 'ipv6', 'uuid', 'uuidv3', 'uuidv4', 'uuidv5', 'array', 'creditcard', 'int', 'float', 'decimal', 'date', 'hexadecimal', 'hexacolor'],
  BOOL: ['boolean'],
  ARRAY: ['in'],
  NONE: ['empty']
};

const STANDALONE = {
  EMAIL: 'email address',
  CREDITCARD: 'credit card number',
  INT: 'integer value',
  FLOAT: 'float value',
  DECIMAL: 'decimal value',
  IP: 'ip address',
  IPV4: 'ipv4 address',
  IPV6: 'ipv6 address',
  JSON: 'json string'
};

const STRING = {
  LOWERCASE: 'consist of lowercase letters',
  UPPERCASE: 'consist of uppercase letters',
  ALPHA: 'consist of only letters',
  ALPHANUMERIC: 'consist of only letters & numbers',
  EQUALS: 'equal to %s',
  CONTAINS: 'contains %s in it',
  LEN: 'between %s to %s characters',
  LENGTH: 'between %s to %s characters',
  ATLEAST: 'at least %s characters long',
  NUMERIC: 'consist of only numbers'
};

const NUMBER = {
  GREATER: 'greater than %s',
  SMALLER: 'smaller than %s',
  MIN: 'minimum %s',
  MAX: 'maximum %s',
  DIVISIBLE: 'divisible by %s'
};

const BOOL = {
  BOOLEAN: 'either %s or %s'
};

const ARRAY = {
  BINARY: 'either %s or %s',
  N: 'one of these values (%s)',
  ONE: 'equal to %s'
};

import { format } from 'util';

import { humanize, flatten } from '../utils';

export default class Parser {

  /**
   * Static method to parse operator.
   *
   * Possible inputs can be:
   * - Positives: empty, isEmpty, !notEmpty, !isNotEmpty
   * - Negatives: !empty, !isEmpty, notEmpty
   * @param operator
   * @returns {*[]}
   */
  static operator(operator) {
    let _count = 0;
    let _not = false;
    let _operator;
    let _type;

    if (operator.includes('!')) {
      _not = !_not;
      _count++;
    }
    if (operator.substr(0, 3).toLowerCase().includes('is')) _count += 2;
    if (operator.includes('not')) {
      _not = !_not;
      _count += 3;
    }

    _operator = operator.substr(_count, operator.length).toLowerCase();
    _type = Parser.type(_operator);

    return [_not, _operator, _type];
  }

  /**
   * Static method to get the type of the operator.
   *
   * @param operator
   * @returns {string}
   */
  static type(operator) {
    if (!Parser.isSupported(operator)) throw new Error(`Provided operator \`${operator}\` is not supported.`);
    for (let type of Object.keys(TYPES)) {
      if (TYPES[type].includes(operator)) return String(type).toLowerCase();
    }
  }

  /**
   * Static method that wraps all type wise operations.
   *
   * @returns {*}
   */
  static get methods() {
    return {
      date() {
        let [_operator, _args] = Array.from(arguments);
        return `${_operator} than ${ humanize(_args) }`;
      },
      number() {
        let [_operator, _args] = Array.from(arguments);
        return `${format(NUMBER[_operator.toUpperCase()], _args) || _operator }`;
      },
      string() {
        let [_operator, _args] = Array.from(arguments);
        let _msg;

        if (_operator === 'len' || _operator === 'length' || _operator === 'equals' || _operator === 'contains') {
          if ((_operator === 'len' || _operator === 'length') && _args.length === 1) _operator = 'atleast';
          _msg = format(STRING[_operator.toUpperCase()], ..._args);
        }
        else _msg = `${ STRING[_operator.toUpperCase()] || _operator }`;

        return _msg;
      },
      standalone() {
        let [_operator] = Array.from(arguments);
        return `a valid ${ STANDALONE[_operator.toUpperCase()] || _operator }`;
      },
      bool() {
        let [_operator, _args] = Array.from(arguments);
        return `${format(BOOL[_operator.toUpperCase()], ..._args) || _operator }`;
      },
      array() {
        let [, _args] = Array.from(arguments);
        let _msg;

        if (Array.isArray(_args)) _args = flatten(_args);

        if (_args.length === 2) _msg = `${ format(ARRAY['BINARY'], ..._args) }`;
        else if (_args.length > 2) _msg = `${ format(ARRAY['N'], _args.join(', ')) }`;
        else _msg = `${ format(ARRAY['ONE'], typeof _args === 'object' ? JSON.stringify(_args[0]) : _args[0]) }`;

        return _msg;
      },
      none(operator) {
        return operator;
      }
    };
  }

  /**
   * Return true if provided operator is valid.
   *
   * @param operator
   * @returns {*}
   */
  static isSupported(operator) {
    let _all = [];
    for (let type of Object.keys(TYPES)) {
      _all.push(...TYPES[type]);
    }
    return Parser._containsAny(operator.toLowerCase(), _all);
  }

  /**
   * Search through an array and returns true if any value of array matches the provided needle.
   *
   * @param needle
   * @param haystack
   * @returns {boolean}
   * @private
   */
  static _containsAny(needle, haystack) {
    for (let straw of haystack) {
      if (needle.includes(straw)) return true;
    }
    return false;
  }

  /**
   * Parse arguments.
   *
   * @returns {*[]}
   */
  static args() {
    let [_first, _second, _third] = Array.from(arguments);
    return Parser.isSupported(_first) ? [_third, _first, _second] : [_first, _second, _third];
  }
}
<|endoftext|>


<commit_before>'use strict';

var gulp           = require('gulp'),
	  runSequence    = require('run-sequence'),
    browserifyTask = require('./browserify');

gulp.task('build', ['clean', 'test'], function() {
  global.runmode = 'prod';
  global.location = undefined;
  runSequence(
    ['sass', 'images'],
    ['browserify', 'concatEncryption'],
    'modernizr',
    'version',
    'zip'
  );
});
<commit_msg>[fixed] svg missing for production build<commit_after>'use strict';

var gulp           = require('gulp'),
	  runSequence    = require('run-sequence'),
    browserifyTask = require('./browserify');

gulp.task('build', ['clean', 'test'], function() {
  global.runmode = 'prod';
  global.location = undefined;
  runSequence(
    ['sass', 'images', 'svg'],
    ['browserify', 'concatEncryption'],
    'modernizr',
    'version',
    'zip'
  );
});
<|endoftext|>


<commit_before>import React, { Component } from 'react'
import { autobind } from 'core-decorators'

const BrowserSpeechRecognition =
  window.SpeechRecognition ||
  window.webkitSpeechRecognition ||
  window.mozSpeechRecognition ||
  window.msSpeechRecognition ||
  window.oSpeechRecognition
const recognition = BrowserSpeechRecognition
  ? new BrowserSpeechRecognition()
  : null

export default function SpeechRecognition(WrappedComponent) {
  return class SpeechRecognitionContainer extends Component {
    constructor(props) {
      super(props)

      this.state = {
        interimTranscript: '',
        finalTranscript: '',
        recognition: null,
        browserSupportsSpeechRecognition: true
      }
    }

    componentWillMount() {
      if (recognition) {
        recognition.continuous = true
        recognition.interimResults = true
        recognition.onresult = this.updateTranscript.bind(this)
        recognition.start()
        this.setState({ recognition })
      } else {
        this.setState({ browserSupportsSpeechRecognition: false })
      }
    }

    componentWillUnmount() {
      if (this.state.recognition) {
        this.state.recognition.abort()
      }
    }

    updateTranscript(event) {
      const { finalTranscript, interimTranscript } = this.getNewTranscript(
        event
      )

      this.setState({ finalTranscript, interimTranscript })
    }

    getNewTranscript(event) {
      let finalTranscript = this.state.finalTranscript
      let interimTranscript = ''
      for (let i = event.resultIndex; i < event.results.length; ++i) {
        if (event.results[i].isFinal) {
          finalTranscript = this.concatTranscripts(
            finalTranscript,
            event.results[i][0].transcript
          )
        } else {
          interimTranscript = this.concatTranscripts(
            interimTranscript,
            event.results[i][0].transcript
          )
        }
      }
      return { finalTranscript, interimTranscript }
    }

    concatTranscripts(...transcriptParts) {
      return transcriptParts.map(t => t.trim()).join(' ').trim()
    }

    @autobind
    resetTranscript() {
      this.setState({ interimTranscript: '', finalTranscript: '' })
      if (this.state.recognition) {
        this.state.recognition.abort()
      }
    }

    render() {
      const { finalTranscript, interimTranscript } = this.state
      const transcript = this.concatTranscripts(
        finalTranscript,
        interimTranscript
      )

      return (
        <WrappedComponent
          resetTranscript={this.resetTranscript}
          transcript={transcript}
          {...this.state}
          {...this.props} />
      )
    }
  }
}
<commit_msg>Add listening prop so user can detect when recognition has disconnected<commit_after>import React, { Component } from 'react'
import { autobind } from 'core-decorators'

const BrowserSpeechRecognition =
  window.SpeechRecognition ||
  window.webkitSpeechRecognition ||
  window.mozSpeechRecognition ||
  window.msSpeechRecognition ||
  window.oSpeechRecognition
const recognition = BrowserSpeechRecognition
  ? new BrowserSpeechRecognition()
  : null

export default function SpeechRecognition(WrappedComponent) {
  return class SpeechRecognitionContainer extends Component {
    constructor(props) {
      super(props)

      this.state = {
        interimTranscript: '',
        finalTranscript: '',
        recognition: null,
        browserSupportsSpeechRecognition: true,
        listening: false
      }
    }

    componentWillMount() {
      if (recognition) {
        recognition.continuous = true
        recognition.interimResults = true
        recognition.onresult = this.updateTranscript.bind(this)
        recognition.onend = this.onRecognitionDisconnect.bind(this)
        recognition.start()
        this.setState({ recognition, listening: true })
      } else {
        this.setState({ browserSupportsSpeechRecognition: false })
      }
    }

    componentWillUnmount() {
      if (this.state.recognition) {
        this.state.recognition.abort()
      }
    }

    onRecognitionDisconnect() {
      this.setState({ listening: false })
    }

    updateTranscript(event) {
      const { finalTranscript, interimTranscript } = this.getNewTranscript(
        event
      )

      this.setState({ finalTranscript, interimTranscript })
    }

    getNewTranscript(event) {
      let finalTranscript = this.state.finalTranscript
      let interimTranscript = ''
      for (let i = event.resultIndex; i < event.results.length; ++i) {
        if (event.results[i].isFinal) {
          finalTranscript = this.concatTranscripts(
            finalTranscript,
            event.results[i][0].transcript
          )
        } else {
          interimTranscript = this.concatTranscripts(
            interimTranscript,
            event.results[i][0].transcript
          )
        }
      }
      return { finalTranscript, interimTranscript }
    }

    concatTranscripts(...transcriptParts) {
      return transcriptParts.map(t => t.trim()).join(' ').trim()
    }

    @autobind
    resetTranscript() {
      this.setState({ interimTranscript: '', finalTranscript: '' })
      if (this.state.recognition) {
        this.state.recognition.abort()
      }
    }

    render() {
      const { finalTranscript, interimTranscript } = this.state
      const transcript = this.concatTranscripts(
        finalTranscript,
        interimTranscript
      )

      return (
        <WrappedComponent
          resetTranscript={this.resetTranscript}
          transcript={transcript}
          {...this.state}
          {...this.props} />
      )
    }
  }
}
<|endoftext|>


<commit_before>var collection1 = new Meteor.Collection('estestCollection');

collection1.allow({
    'insert' : function () { return true; }
});

if (Meteor.isServer) {
    collection1.remove({ });

    Meteor.publish('testCollection', function () { return collection1.find(); });
} else if (Meteor.isClient) {
    Meteor.subscribe('testCollection');

    // fixture data
    collection1.insert({ 'name' : 'Super Pomodoro' });
    collection1.insert({ 'name' : 'Awesome Testsauce' });
    collection1.insert({ 'name' : 'David Rails' });
}

collection1.initEasySearch('name');

// Tests
Tinytest.add('EasySearch - createSearchIndex, getIndex, getIndexes', function (test) {
    test.throws(function () { EasySearch.createSearchIndex({}, {}); });
    test.throws(function () { EasySearch.createSearchIndex(10, {}); });
    test.throws(function () { EasySearch.createSearchIndex('validName', 10); });
    test.throws(function () { EasySearch.createSearchIndex(function () { }, {}); });

    if (Meteor.isServer) {
        test.expect_fail(function () { EasySearch.createSearchIndex('test', { 'field' : 'a', 'use' : 'doesntExist' }); });
    }

    EasySearch.createSearchIndex('testIndex', {
        'field' : 'testField',
        'customField' : [0, 1, 2]
    });

    test.equal(EasySearch.getIndex('testIndex').customField, [0, 1, 2]);
    test.equal(EasySearch.getIndex('testIndex').field, ['testField']);

    test.instanceOf(EasySearch.getIndexes(), Object);
    test.equal(EasySearch.getIndexes()['testIndex'].field, ['testField']);
    test.isUndefined(EasySearch.getIndexes()['indexThatDoesntExist']);
});

if (Meteor.isClient) {
    Tinytest.add('EasySearch - Client - changeProperty', function (test) {
        EasySearch.createSearchIndex('testIndex2', {
            'field' : 'testField',
            'customField' : 'isAString'
        });

        test.throws(function () { EasySearch.changeProperty('testIndex2', {}, {}); });
        test.throws(function () { EasySearch.changeProperty({}, 'validKey', {}); });

        test.equal(EasySearch.getIndex('testIndex2').customField, 'isAString');
        EasySearch.changeProperty('testIndex2', 'customField', 'isAnotherString');
        test.equal(EasySearch.getIndex('testIndex2').customField, 'isAnotherString');
    });

    Tinytest.addAsync('EasySearch - Client - search #1', function (test, completed) {
        EasySearch.search('estestCollection', 'er Po', function (err, data) {
            test.equal(data.total, 1);
            test.equal(data.results[0].name, "Super Pomodoro");
            completed();
        });
    });

    Tinytest.addAsync('EasySearch - Client - search #2', function (test, completed) {
        EasySearch.searchMultiple(['estestCollection'], 'id R', function (err, data) {
            debugger;
            test.equal(data.total, 1);
            test.equal(data.results[0].name, "David Rails");
            completed();
        });
    });
} else if (Meteor.isServer) {
    Tinytest.add('EasySearch - Server - config', function (test) {
        test.equal(EasySearch.config().host, 'localhost:9200');

        EasySearch.config({
            'host' : 'localhost:8000'
        });

        test.equal(EasySearch.config().host, 'localhost:8000');
    });

    Tinytest.add('EasySearch - Server - search #1', function (test) {
        var data = EasySearch.search('estestCollection', 'sauCE', { 'limit' : 10 });
        test.equal(data.results[0].name, "Awesome Testsauce");
    });

    Tinytest.add('EasySearch - Server - search #2', function (test) {
        var data = EasySearch.search('estestCollection', 'Super duper', { });
        test.equal(data.results.length, 0);
    });

    Tinytest.add('EasySearch - Server - extendSearch', function (test) {
        // No solr implementation
        test.expect_fail(function () { EasySearch.createSearchIndex('test', { 'field' : 'a', 'use' : 'solr' }); });

        EasySearch.extendSearch('solr', {
            'createSearchIndex' : function () {},
            'search' : function () {}
        });

        // Now it has one
        test.isUndefined(EasySearch.createSearchIndex('test', { 'field' : 'a', 'use' : 'solr' }));

        test.expect_fail(function () {
            EasySearch.extendSearch(10, {
                'createSearchIndex' : function () {},
                'search' : function () {}
            });
        });

        test.expect_fail(function () {
            EasySearch.extendSearch('lucene', {});
        });
    });
}
<commit_msg>Removed debugger statement + add documents on the server<commit_after>var collection1 = new Meteor.Collection('estestCollection');

collection1.allow({
    'insert' : function () { return true; },
    'remove' : function () { return true; }
});

if (Meteor.isServer) {
    collection1.remove({ });

    // fixture data
    collection1.insert({ 'name' : 'Super Pomodoro' });
    collection1.insert({ 'name' : 'Awesome Testsauce' });
    collection1.insert({ 'name' : 'David Rails' });

    Meteor.publish('testCollection', function () { return collection1.find(); });
} else if (Meteor.isClient) {
    Meteor.subscribe('testCollection');
}

collection1.initEasySearch('name');

// Tests
Tinytest.add('EasySearch - createSearchIndex, getIndex, getIndexes', function (test) {
    test.throws(function () { EasySearch.createSearchIndex({}, {}); });
    test.throws(function () { EasySearch.createSearchIndex(10, {}); });
    test.throws(function () { EasySearch.createSearchIndex('validName', 10); });
    test.throws(function () { EasySearch.createSearchIndex(function () { }, {}); });

    if (Meteor.isServer) {
        test.expect_fail(function () { EasySearch.createSearchIndex('test', { 'field' : 'a', 'use' : 'doesntExist' }); });
    }

    EasySearch.createSearchIndex('testIndex', {
        'field' : 'testField',
        'customField' : [0, 1, 2]
    });

    test.equal(EasySearch.getIndex('testIndex').customField, [0, 1, 2]);
    test.equal(EasySearch.getIndex('testIndex').field, ['testField']);

    test.instanceOf(EasySearch.getIndexes(), Object);
    test.equal(EasySearch.getIndexes()['testIndex'].field, ['testField']);
    test.isUndefined(EasySearch.getIndexes()['indexThatDoesntExist']);
});

if (Meteor.isClient) {
    Tinytest.add('EasySearch - Client - changeProperty', function (test) {
        EasySearch.createSearchIndex('testIndex2', {
            'field' : 'testField',
            'customField' : 'isAString'
        });

        test.throws(function () { EasySearch.changeProperty('testIndex2', {}, {}); });
        test.throws(function () { EasySearch.changeProperty({}, 'validKey', {}); });

        test.equal(EasySearch.getIndex('testIndex2').customField, 'isAString');
        EasySearch.changeProperty('testIndex2', 'customField', 'isAnotherString');
        test.equal(EasySearch.getIndex('testIndex2').customField, 'isAnotherString');
    });

    Tinytest.addAsync('EasySearch - Client - search #1', function (test, completed) {
        EasySearch.search('estestCollection', 'er Po', function (err, data) {
            test.equal(data.total, 1);
            test.equal(data.results[0].name, "Super Pomodoro");
            completed();
        });
    });

    Tinytest.addAsync('EasySearch - Client - search #2', function (test, completed) {
        EasySearch.searchMultiple(['estestCollection'], 'id R', function (err, data) {
            test.equal(data.total, 1);
            test.equal(data.results[0].name, "David Rails");
            completed();
        });
    });
} else if (Meteor.isServer) {
    Tinytest.add('EasySearch - Server - config', function (test) {
        test.equal(EasySearch.config().host, 'localhost:9200');

        EasySearch.config({
            'host' : 'localhost:8000'
        });

        test.equal(EasySearch.config().host, 'localhost:8000');
    });

    Tinytest.add('EasySearch - Server - search #1', function (test) {
        var data = EasySearch.search('estestCollection', 'sauCE', { 'limit' : 10 });
        test.equal(data.results[0].name, "Awesome Testsauce");
    });

    Tinytest.add('EasySearch - Server - search #2', function (test) {
        var data = EasySearch.search('estestCollection', 'Super duper', { });
        test.equal(data.results.length, 0);
    });

    Tinytest.add('EasySearch - Server - extendSearch', function (test) {
        // No solr implementation
        test.expect_fail(function () { EasySearch.createSearchIndex('test', { 'field' : 'a', 'use' : 'solr' }); });

        EasySearch.extendSearch('solr', {
            'createSearchIndex' : function () {},
            'search' : function () {}
        });

        // Now it has one
        test.isUndefined(EasySearch.createSearchIndex('test', { 'field' : 'a', 'use' : 'solr' }));

        test.expect_fail(function () {
            EasySearch.extendSearch(10, {
                'createSearchIndex' : function () {},
                'search' : function () {}
            });
        });

        test.expect_fail(function () {
            EasySearch.extendSearch('lucene', {});
        });
    });
}
<|endoftext|>


<commit_before>var gulp = require("gulp"),
    gutil = require('gulp-util'),
    fs = require('fs'),
    gprint = require('gulp-print'),
    path = require('path'),
    changed = require('gulp-changed'),
    clean = require('gulp-clean'),
    concat = require('gulp-concat'),
    frontMatter = require('gulp-front-matter'),
    marked = require('gulp-marked'),
    imagemin = require('gulp-imagemin'),
    svgmin = require('gulp-svgmin'),
    minifyCSS = require('gulp-minify-css'),
    uglify = require('gulp-uglify'),
    source = require('vinyl-source-stream'),
    stylus = require('gulp-stylus'),
    jade = require('gulp-jade'),
    replace = require('gulp-replace-task'),
    connect = require('gulp-connect'),
    open = require('gulp-open'),
    browserify = require('browserify'),
    notify = require("gulp-notify");

// Global Config
var config = {
    root: path.resolve('./'),
    content: 'haikus/**/*.md',
    images: ['./img/**/*.png', './img/**/*.jpg'],
    illustrations: './img/**/*.svg',
    templates: './**/*.jade',
    styles: './css/**/*.styl',
    scripts: './js/**/*.js',
    publish: './site',
    publish_img: './site/img',
    publish_fonts: './site/fonts',
    port: 8000
};

gulp.task('init', function() {
    fs.mkdirSync(config.publish);
    fs.mkdirSync(config.publish + "/fonts");
    fs.mkdirSync(config.publish + "/img");
});

gulp.task('clean', function() {
    var files = [
        config.publish + '/*.js',
        config.publish + '/*.css',
        config.publish + '/fonts/*.*',
        config.publish + '/*.html',
    ];
    return gulp.src(files, {
        read: false
    })
        .pipe(gprint())
        .pipe(clean({
            force: true
        }));
});

gulp.task('transform-text', function() {
    gulp.src('./index.html')
        .pipe(replace({
            patterns: [{
                match: 'foo',
                replacement: 'bar'
            }]
        }))
        .pipe(gulp.dest(config.publish));
});

// TODO
gulp.task('build-content', function() {
    gulp.src(config.content)
        .pipe(frontMatter({
            property: 'frontMatter',
            remove: true
        }))
        .pipe(marked({
            gfm: true,
            tables: false,
            breaks: true,
            pedantic: false,
            sanitize: true,
            smartLists: true,
            smartypants: false
        }))
        .pipe(concat('haiper.content.json'))
        .pipe(gulp.dest(config.publish));
});

// TODO
gulp.task('build-data', function() {
    gulp.src(config.content)
        .pipe(frontMatter({
            property: 'frontMatter',
        }))
        .pipe(concat('haiper.data.json'))
        .pipe(gulp.dest(config.publish));
});

gulp.task('build-templates', function() {
    var data = {}; // TODO: get front matter

    gulp.src(config.templates)
        .pipe(frontMatter({
            property: 'frontMatter',
        }))
        .pipe(jade({
            locals: data
        }))
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-styles', function() {
    gulp.src(config.styles)
        .pipe(stylus({
            errors: true
        }))
        .pipe(minifyCSS({
            keepBreaks: true
        }))
        .pipe(concat('haiper.min.css'))
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-scripts', function() {
    return gulp.src(config.scripts)
        .pipe(changed(config.publish))
        .pipe(uglify())
        .pipe(concat('haiper.min.js'))
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-images', function() {
    return gulp.src(config.images)
        .pipe(changed(config.publish_img))
        .pipe(imagemin())
        .pipe(gulp.dest(config.publish_img));
});

gulp.task('build-illustrations', function() {
    return gulp.src(config.illustrations)
        .pipe(changed(config.publish_img))
        .pipe(svgmin())
        .pipe(gulp.dest(config.publish_img));
});

gulp.task('start-server', function() {
    connect.server({
        root: config.publish,
        port: config.port,
        livereload: true
    });
});

gulp.task('open', function() {
    var options = {
        url: "http://localhost:" + config.port,
        app: "google chrome"
    };
    return gulp.src(config.publish + "/index.html").pipe(open("", options));
});

gulp.task('watch', function() {
    gulp.watch(config.templates, ['build-templates']);
    gulp.watch(config.styles, ['build-styles']);
    gulp.watch(config.scripts, ['build-scripts']);
});

gulp.task('browserify', function() {
    return browserify({
        entries: ['./js/design.js'],
        extensions: ['.js']
    })
        .bundle({
            debug: true
        })
        .on('error', function() {
            var args = Array.prototype.slice.call(arguments);

            // Send error to notification center
            notify.onError({
                title: "Compile Error",
                message: "<%= error.message %>"
            }).apply(this, args);

            // Keep gulp from hanging on this task
            this.emit('end');
        })
        .pipe(source('design.js'))
        .pipe(gulp.dest(haiper.siteDir));
});

gulp.task('build', ['build-content', 'build-templates', 'build-styles', 'build-scripts', 'build-images']);

gulp.task('default', ['start-server', 'build', 'watch']);
<commit_msg>fixed issues, jade builds not working<commit_after>var gulp = require("gulp"),
    gutil = require('gulp-util'),
    gprint = require('gulp-print'),
    fs = require('fs'),
    path = require('path'),
    changed = require('gulp-changed'),
    clean = require('gulp-clean'),
    concat = require('gulp-concat'),
    frontMatter = require('gulp-front-matter'),
    marked = require('gulp-marked'),
    imagemin = require('gulp-imagemin'),
    svgmin = require('gulp-svgmin'),
    minifyCSS = require('gulp-minify-css'),
    uglify = require('gulp-uglify'),
    source = require('vinyl-source-stream'),
    stylus = require('gulp-stylus'),
    jade = require('gulp-jade'),
    replace = require('gulp-replace-task'),
    connect = require('gulp-connect'),
    open = require('gulp-open'),
    browserify = require('browserify'),
    notify = require("gulp-notify");

// Global Config
var config = {
    root: path.resolve('./'),
    content: './haikus/**/*.txt',
    images: ['./img/**/*.png', './img/**/*.jpg'],
    illustrations: './img/**/*.svg',
    templates: './**/*.jade',
    styles: './css/**/*.styl',
    lib_styles: './css/lib/**/*.css',
    scripts: './js/**/*.js',
    publish: './site',
    publish_img: './site/img',
    publish_fonts: './site/fonts',
    port: 8000
};

gulp.task('init', function() {
    fs.mkdirSync(config.publish);
    fs.mkdirSync(config.publish + "/fonts");
    fs.mkdirSync(config.publish + "/img");
});

gulp.task('clean', function() {
    var files = [
        config.publish + '/*.js',
        config.publish + '/*.css',
        config.publish + '/fonts/*.*',
        config.publish + '/*.html',
    ];
    return gulp.src(files, {
        read: false
    })
        .pipe(gprint())
        .pipe(clean({
            force: true
        }));
});

// TODO
gulp.task('transform-text', function() {
    gulp.src('./index.html')
        .pipe(replace({
            patterns: [{
                match: 'foo',
                replacement: 'bar'
            }]
        }))
        .pipe(gulp.dest(config.publish));
});

gulp.task('build-content', function() {
    gulp.src(config.content)
        .pipe(frontMatter({
            property: 'frontMatter',
            remove: true
        }))
        .pipe(marked({
            gfm: true,
            tables: false,
            breaks: true,
            pedantic: false,
            sanitize: true,
            smartLists: true,
            smartypants: false
        }))
        .pipe(concat('haiper.haiku.html'))
        .pipe(gulp.dest(config.publish));
});

gulp.task('build-templates', function() {
    gulp.src(config.templates)
        .pipe(jade())
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-styles', function() {
    gulp.src(config.styles)
        .pipe(stylus({
            errors: true
        }))
        .pipe(minifyCSS({
            keepBreaks: true
        }))
        .pipe(concat('haiper.min.css'))
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-lib-styles', function() {
    gulp.src(config.lib_styles)
        .pipe(stylus({
            errors: true
        }))
        .pipe(minifyCSS({
            keepBreaks: true
        }))
        .pipe(concat('haiper.vendors.min.css'))
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-scripts', function() {
    return gulp.src(config.scripts)
        .pipe(changed(config.publish))
        .pipe(uglify())
        .pipe(concat('haiper.min.js'))
        .pipe(gulp.dest(config.publish))
        .pipe(connect.reload());
});

gulp.task('build-images', function() {
    return gulp.src(config.images)
        .pipe(changed(config.publish_img))
        .pipe(imagemin())
        .pipe(gulp.dest(config.publish_img));
});

gulp.task('build-illustrations', function() {
    return gulp.src(config.illustrations)
        .pipe(changed(config.publish_img))
        .pipe(svgmin())
        .pipe(gulp.dest(config.publish_img));
});

gulp.task('start-server', function() {
    connect.server({
        root: config.publish,
        port: config.port,
        livereload: true
    });
});

gulp.task('open', function() {
    var options = {
        url: "http://localhost:" + config.port,
        app: "google chrome"
    };
    return gulp.src(config.publish + "/index.html").pipe(open("", options));
});

gulp.task('watch', function() {
    gulp.watch(config.templates, ['build-templates']);
    gulp.watch(config.styles, ['build-styles']);
    gulp.watch(config.scripts, ['build-scripts']);
});

gulp.task('browserify', function() {
    return browserify({
        entries: ['./js/design.js'],
        extensions: ['.js']
    })
        .bundle({
            debug: true
        })
        .on('error', function() {
            var args = Array.prototype.slice.call(arguments);

            // Send error to notification center
            notify.onError({
                title: "Compile Error",
                message: "<%= error.message %>"
            }).apply(this, args);

            // Keep gulp from hanging on this task
            this.emit('end');
        })
        .pipe(source('design.js'))
        .pipe(gulp.dest(haiper.siteDir));
});

gulp.task('build', ['build-content', 'build-templates', 'build-styles', 'build-lib-styles', 'build-scripts', 'build-images', 'build-illustrations']);

gulp.task('default', ['start-server', 'build', 'watch', 'open']);
<|endoftext|>


<commit_before>/*
Copyright 2007-2009 WebDriver committers
Copyright 2007-2009 Google Inc.
Portions copyright 2007 ThoughtWorks, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var driver = false;
var domMessenger = null;

// This will configure a FirefoxDriver and DomMessenger for each
// _browser window_ (not chrome window). Multiple tabs in the same window will
// share a FirefoxDriver and DomMessenger instance.
window.addEventListener("load", function(e) {
    try{
        handle = Components.classes["@googlecode.com/webdriver/fxdriver;1"].
        createInstance();
    } catch (e){
        dump("Error: " + e);
    }
    var server = handle.wrappedJSObject;

  if (!domMessenger) {
    var appcontent = document.getElementById('appcontent');
    if (appcontent) {
      try {
        var commandProcessor = Components.
            classes['@googlecode.com/webdriver/command-processor;1'].
            getService(Components.interfaces.nsICommandProcessor);
        domMessenger = new DomMessenger(commandProcessor);
        appcontent.addEventListener('DOMContentLoaded',
            function(e) {
              domMessenger.onPageLoad(e);
            }, true);
        appcontent.addEventListener('pagehide',
            function(e) {
              domMessenger.onPageUnload(e);
            }, true);
      } catch (ex) {
        // Not catching this can really mess things up and lead to inexplicable
        // and hard to debug behavior.
        Components.utils.reportError(ex);
      }
    }
  }

    if (!driver) {
        driver = server.newDriver(window);
    }

    server.startListening();

}, true);

//window.addEventListener("focus", function(e) {
//    var active = e.originalTarget;
//    var doc = gBrowser.selectedBrowser.contentDocument;
//    if (active.ownerDocument == doc) {
//        driver.activeElement = active;
//    }
//}, true);
<commit_msg>SimonStewart: Formatting clean up in the server.js file<commit_after>/*
Copyright 2007-2009 WebDriver committers
Copyright 2007-2009 Google Inc.
Portions copyright 2007 ThoughtWorks, Inc

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var driver = false;
var domMessenger = null;

// This will configure a FirefoxDriver and DomMessenger for each
// _browser window_ (not chrome window). Multiple tabs in the same window will
// share a FirefoxDriver and DomMessenger instance.
window.addEventListener("load", function(e) {
  handle = Components.classes["@googlecode.com/webdriver/fxdriver;1"].createInstance();
  var server = handle.wrappedJSObject;

  if (!domMessenger) {
    var appcontent = document.getElementById('appcontent');
    if (appcontent) {
      try {
        var commandProcessor = Components.
            classes['@googlecode.com/webdriver/command-processor;1'].
            getService(Components.interfaces.nsICommandProcessor);
        domMessenger = new DomMessenger(commandProcessor);
        appcontent.addEventListener('DOMContentLoaded',
            function(e) {
              domMessenger.onPageLoad(e);
            }, true);
        appcontent.addEventListener('pagehide',
            function(e) {
              domMessenger.onPageUnload(e);
            }, true);
      } catch (ex) {
        // Not catching this can really mess things up and lead to inexplicable
        // and hard to debug behavior.
        Components.utils.reportError(ex);
      }
    }
  }

  if (!driver) {
    driver = server.newDriver(window);
  }

  server.startListening();
}, true);
<|endoftext|>


<commit_before>const db = require('../../../../src/learn/db');
const helper = require('../../../../src/learn/math/drill/helper');
const constants = require('../../../../src/learn/common/constants');

const {
  // RECORD_NEW,
  // RECORD_EQUAL,
  // RECORD_MISS,
  RECORD_NOT_EXIST,
  // BADGE_BOUNDARIES: badgeBoundaries,
  // COLOR_HTML,
} = constants;

describe('Helper', () => {
  test('should get a pair of numbers from level #1 plus', () => {
    const pair = helper.getLowerUpper(0, [0]);
    expect(pair[0] === 1 || pair[1] === 1).toBe(true);
  });

  test('should get a random pair of numbers', () => {
    const pair = helper.getLowerUpper(4, [0]);
    expect(pair[0]).toBeLessThan(8);
    expect(pair[1]).toBeLessThan(8);
  });

  test('should getScoreBarTimes() for zero items', () => {
    const scores = [];

    const actual = helper.getScoreBarTimes(0, [0], scores);

    const expected = [];

    expect(actual).toEqual(expected);
  });

  test('should getScoreBarTimes() for single item', () => {
    const scores = [{
      key: '00',
      correctCount: 10,
      date: 1,
      timePerQuestion: 1.3,
    }];

    const actual = helper.getScoreBarTimes(0, [0], scores);

    const expected = [{
      date: 1,
      timePerQuestion: 1.3,
    }];

    expect(actual).toEqual(expected);
  });

  test('should sort getScoreBarTimes() for two items', () => {
    const scores = [{
      key: '00',
      correctCount: 22,
      date: 2,
      timePerQuestion: 2.2,
    }, {
      key: '00',
      correctCount: 11,
      date: 1,
      timePerQuestion: 1.1,
    }];

    const actual = helper.getScoreBarTimes(0, [0], scores);

    const expected = [{
      date: 1,
      timePerQuestion: 1.1,
    }, {
      date: 2,
      timePerQuestion: 2.2,
    }];

    expect(actual).toEqual(expected);
  });

  test(
    'should not return more than 5 items getScoreBarTimes() for six items',
    () => {
      const scores = [{
        key: '00',
        correctCount: 66,
        date: 6,
        timePerQuestion: 6.6,
      }, {
        key: '00',
        correctCount: 55,
        date: 5,
        timePerQuestion: 5.5,
      }, {
        key: '00',
        correctCount: 44,
        date: 4,
        timePerQuestion: 4.4,
      }, {
        key: '00',
        correctCount: 33,
        date: 3,
        timePerQuestion: 3.3,
      }, {
        key: '00',
        correctCount: 22,
        date: 2,
        timePerQuestion: 2.2,
      }, {
        key: '00',
        correctCount: 11,
        date: 1,
        timePerQuestion: 1.1,
      }];

      const actual = helper.getScoreBarTimes(0, [0], scores);

      const expected = [{
        date: 2,
        timePerQuestion: 2.2,
      }, {
        date: 3,
        timePerQuestion: 3.3,
      }, {
        date: 4,
        timePerQuestion: 4.4,
      }, {
        date: 5,
        timePerQuestion: 5.5,
      }, {
        date: 6,
        timePerQuestion: 6.6,
      }];

      expect(actual).toEqual(expected);
    },
  );

  test('should calculate all Answer operators', () => {
    const { calculateAnswer } = helper;
    const inputs = [
      [[6, 3], 0, 9], // 6 + 3 = 9
      [[6, 3], 1, 3], // 6 - 3 = 3
      [[6, 3], 2, 18], // 6 x 3 = 18
      [[6, 3], 3, 2], // 6 / 3 = 2
      [[6, 3], 4, 0], // Unknown operator returns 0
    ];

    inputs.forEach((input) => {
      const [pair, operator, expected] = input;
      const actual = calculateAnswer(pair, operator);
      expect(actual).toBe(expected);
    });
  });

  test('should get current record if data exists', () => {
    db.getScores = jest.fn();
    db.getScores.mockReturnValueOnce([{
      key: '001',
      timePerQuestion: 2,
    }, {
      key: '002',
      timePerQuestion: 0.5,
    }, {
      key: '001',
      timePerQuestion: 1,
    }]);
    const { getCurrentRecord } = helper;

    const actual = getCurrentRecord(0, [0, 1]);
    expect(actual).toEqual({
      key: '001',
      timePerQuestion: 1,
    });

    db.getScores.mockClear();
  });

  test('should get undefined for current record if no data exists', () => {
    db.getScores = jest.fn();
    db.getScores.mockReturnValueOnce(undefined);
    const { getCurrentRecord } = helper;

    const actual = getCurrentRecord(0, [0, 1]);
    expect(actual).toBeUndefined();

    db.getScores.mockClear();
  });

  test('should append score with no existing record', () => {
    db.getScores = jest.fn();
    db.appendScore = jest.fn();
    db.getScores.mockReturnValueOnce(undefined);
    const { appendScore } = helper;
    const results = {
      correctCount: 10,
      levelIndex: 0,
      minutes: 10, // in minutes
      opIndexes: [0],
      previousResults: [], // TODO: A test where this is undefined
      questionsRemaining: 0,
      timeLeft: 540, // in seconds
      totalProblems: 10,
    };

    const actual = appendScore(results);
    expect(actual).toEqual({
      // eslint-disable-next-line no-multi-str
      text: 'This is the first time you\'ve done this problem. You took \
6 seconds per question. Do this test again to see if you can \
beat this score. Good luck!',
      newRecordInfo: RECORD_NOT_EXIST,
    });
    expect(db.getScores).toBeCalled();
    expect(db.appendScore).toBeCalled();

    db.getScores.mockClear();
    db.appendScore.mockClear();
  });
});
<commit_msg>Add zero correct append test. Issue #223<commit_after>const db = require('../../../../src/learn/db');
const helper = require('../../../../src/learn/math/drill/helper');
const constants = require('../../../../src/learn/common/constants');

const {
  // RECORD_NEW,
  // RECORD_EQUAL,
  RECORD_MISS,
  RECORD_NOT_EXIST,
  // BADGE_BOUNDARIES: badgeBoundaries,
  // COLOR_HTML,
} = constants;

describe('Helper', () => {
  beforeEach(() => {
    db.getScores = jest.fn();
    db.appendScore = jest.fn();
  });

  afterEach(() => {
    db.getScores.mockClear();
    db.appendScore.mockClear();
  });

  test('should get a pair of numbers from level #1 plus', () => {
    const pair = helper.getLowerUpper(0, [0]);
    expect(pair[0] === 1 || pair[1] === 1).toBe(true);
  });

  test('should get a random pair of numbers', () => {
    const pair = helper.getLowerUpper(4, [0]);
    expect(pair[0]).toBeLessThan(8);
    expect(pair[1]).toBeLessThan(8);
  });

  test('should getScoreBarTimes() for zero items', () => {
    const scores = [];

    const actual = helper.getScoreBarTimes(0, [0], scores);

    const expected = [];

    expect(actual).toEqual(expected);
  });

  test('should getScoreBarTimes() for single item', () => {
    const scores = [{
      key: '00',
      correctCount: 10,
      date: 1,
      timePerQuestion: 1.3,
    }];

    const actual = helper.getScoreBarTimes(0, [0], scores);

    const expected = [{
      date: 1,
      timePerQuestion: 1.3,
    }];

    expect(actual).toEqual(expected);
  });

  test('should sort getScoreBarTimes() for two items', () => {
    const scores = [{
      key: '00',
      correctCount: 22,
      date: 2,
      timePerQuestion: 2.2,
    }, {
      key: '00',
      correctCount: 11,
      date: 1,
      timePerQuestion: 1.1,
    }];

    const actual = helper.getScoreBarTimes(0, [0], scores);

    const expected = [{
      date: 1,
      timePerQuestion: 1.1,
    }, {
      date: 2,
      timePerQuestion: 2.2,
    }];

    expect(actual).toEqual(expected);
  });

  test(
    'should not return more than 5 items getScoreBarTimes() for six items',
    () => {
      const scores = [{
        key: '00',
        correctCount: 66,
        date: 6,
        timePerQuestion: 6.6,
      }, {
        key: '00',
        correctCount: 55,
        date: 5,
        timePerQuestion: 5.5,
      }, {
        key: '00',
        correctCount: 44,
        date: 4,
        timePerQuestion: 4.4,
      }, {
        key: '00',
        correctCount: 33,
        date: 3,
        timePerQuestion: 3.3,
      }, {
        key: '00',
        correctCount: 22,
        date: 2,
        timePerQuestion: 2.2,
      }, {
        key: '00',
        correctCount: 11,
        date: 1,
        timePerQuestion: 1.1,
      }];

      const actual = helper.getScoreBarTimes(0, [0], scores);

      const expected = [{
        date: 2,
        timePerQuestion: 2.2,
      }, {
        date: 3,
        timePerQuestion: 3.3,
      }, {
        date: 4,
        timePerQuestion: 4.4,
      }, {
        date: 5,
        timePerQuestion: 5.5,
      }, {
        date: 6,
        timePerQuestion: 6.6,
      }];

      expect(actual).toEqual(expected);
    },
  );

  test('should calculate all Answer operators', () => {
    const { calculateAnswer } = helper;
    const inputs = [
      [[6, 3], 0, 9], // 6 + 3 = 9
      [[6, 3], 1, 3], // 6 - 3 = 3
      [[6, 3], 2, 18], // 6 x 3 = 18
      [[6, 3], 3, 2], // 6 / 3 = 2
      [[6, 3], 4, 0], // Unknown operator returns 0
    ];

    inputs.forEach((input) => {
      const [pair, operator, expected] = input;
      const actual = calculateAnswer(pair, operator);
      expect(actual).toBe(expected);
    });
  });

  test('should get current record if data exists', () => {
    db.getScores.mockReturnValueOnce([{
      key: '001',
      timePerQuestion: 2,
    }, {
      key: '002',
      timePerQuestion: 0.5,
    }, {
      key: '001',
      timePerQuestion: 1,
    }]);
    const { getCurrentRecord } = helper;

    const actual = getCurrentRecord(0, [0, 1]);
    expect(actual).toEqual({
      key: '001',
      timePerQuestion: 1,
    });
  });

  test('should get undefined for current record if no data exists', () => {
    db.getScores.mockReturnValueOnce(undefined);
    const { getCurrentRecord } = helper;

    const actual = getCurrentRecord(0, [0, 1]);
    expect(actual).toBeUndefined();
  });

  test('should append score with no existing record', () => {
    db.getScores.mockReturnValueOnce(undefined);
    const { appendScore } = helper;
    const results = {
      correctCount: 10,
      levelIndex: 0,
      minutes: 10, // in minutes
      opIndexes: [0],
      previousResults: [], // TODO: A test where this is undefined
      questionsRemaining: 0,
      timeLeft: 540, // in seconds
      totalProblems: 10,
    };

    const actual = appendScore(results);
    expect(actual).toEqual({
      // eslint-disable-next-line no-multi-str
      text: 'This is the first time you\'ve done this problem. You took \
6 seconds per question. Do this test again to see if you can \
beat this score. Good luck!',
      newRecordInfo: RECORD_NOT_EXIST,
    });
    expect(db.getScores).toHaveBeenCalled();
    expect(db.appendScore).toHaveBeenCalled();
  });

  test('should not append score if no correct answers', () => {
    db.getScores.mockReturnValueOnce(undefined);
    const { appendScore } = helper;
    const results = {
      correctCount: 0,
      levelIndex: 0,
      minutes: 10, // in minutes
      opIndexes: [0],
      previousResults: [], // TODO: A test where this is undefined
      questionsRemaining: 0,
      timeLeft: 540, // in seconds
      totalProblems: 10,
    };

    const actual = appendScore(results);
    expect(actual).toEqual({
      // eslint-disable-next-line no-multi-str
      text: 'You didn\'t answer any questions correctly so we are not going to use this score \
as part of your high scores. If you are struggling with these problems then try an \
easier level or an easier operator.',
      newRecordInfo: RECORD_MISS,
    });
    expect(db.getScores).toHaveBeenCalled();
    expect(db.appendScore).not.toHaveBeenCalled();
  });
});
<|endoftext|>


<commit_before>export default async function(data, metadata, done) {
    const keys = Object.getOwnPropertyNames(data);

    for (const key of keys) {
        await unwrap(metadata, key, data[key]);
    }

    done();
}

async function unwrap(metadata, key, dataProvider) {
    /* eslint-disable no-param-reassign */
    if (typeof dataProvider === 'function') {
        try {
            metadata[key] = await dataProvider(metadata);
        } catch (e) {
            // error in async function, leave this key
        }
        return;
    }
    metadata[key] = dataProvider;
    /* eslint-enable */
}
<commit_msg>Fixes problem when data is missing in template<commit_after>export default async function(data = {}, metadata, done) {
    const keys = Object.getOwnPropertyNames(data);

    for (const key of keys) {
        await unwrap(metadata, key, data[key]);
    }

    done();
}

async function unwrap(metadata, key, dataProvider) {
    /* eslint-disable no-param-reassign */
    if (typeof dataProvider === 'function') {
        try {
            metadata[key] = await dataProvider(metadata);
        } catch (e) {
            // error in async function, leave this key
        }
        return;
    }
    metadata[key] = dataProvider;
    /* eslint-enable */
}
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react';
import classNames from 'classnames';
import Exclamation from './Exclamation';
import WixComponent from '../WixComponent';

import styles from './InputArea.scss';

class InputArea extends WixComponent {

  constructor(props) {
    super(props);
    this._onKeyDown = this._onKeyDown.bind(this);
    this._onFocus = this._onFocus.bind(this);
    this._onBlur = this._onBlur.bind(this);
    this.focus = this.focus.bind(this);
    this.blur = this.blur.bind(this);
    this.select = this.select.bind(this);
  }

  state = {
    focus: false
  };

  componentDidMount() {
    super.componentDidMount();
    this.props.autoFocus && this._onFocus();
  }

  render() {
    const {
      autoFocus,
      defaultValue,
      error,
      forceFocus,
      forceHover,
      id,
      onChange,
      onKeyUp,
      placeholder,
      readOnly,
      tabIndex,
      rows,
      value,
      minHeight,
      maxHeight,
      resizable,
      theme,
      errorMessage
    } = this.props;

    const inlineStyle = {};

    if (minHeight) {
      inlineStyle.minHeight = minHeight;
    }

    if (maxHeight) {
      inlineStyle.maxHeight = maxHeight;
    }

    const classes = classNames({
      [styles.root]: true,
      [styles[`theme-${theme}`]]: true,
      [styles.hasError]: !!error,
      [styles.hasHover]: forceHover,
      [styles.hasFocus]: forceFocus || this.state.focus,
      [styles.resizable]: !!resizable,
      [styles.nonResizable]: !resizable
    });

    return (

        <textarea
          rows={rows}
          ref={ref => this.textArea = ref}
          className={styles.inputArea}
          id={id}
          style={inlineStyle}
          defaultValue={defaultValue}
          value={value}
          onChange={onChange}
          onFocus={this._onFocus}
          onBlur={this._onBlur}
          onKeyDown={this._onKeyDown}
          onDoubleClick={this._onDoubleClick}
          placeholder={placeholder}
          tabIndex={tabIndex}
          autoFocus={autoFocus}
          onKeyUp={onKeyUp}
          readOnly={readOnly}
          />
        {error && <Exclamation errorMessage={errorMessage}/>}
        {theme === 'material' &&
}

    );
  }

  focus() {
    this.textArea && this.textArea.focus();
  }

  blur() {
    this.textArea && this.textArea.blur();
  }

  select() {
    this.textArea && this.textArea.select();
  }

  _onFocus() {
    this.setState({focus: true});
    this.props.onFocus && this.props.onFocus();

    if (this.props.autoSelect) {
      // Set timeout is needed here since onFocus is called before react
      // gets the reference for the input (specifically when autoFocus
      // is on. So setTimeout ensures we have the ref.input needed in select)
      setTimeout(() => this.select(), 0);
    }
  }

  _onBlur(e) {
    this.setState({focus: false});
    this.props.onBlur && this.props.onBlur(e);
  }

  _onKeyDown(e) {
    this.props.onKeyDown && this.props.onKeyDown(e);

    if (e.key === 'Enter') {
      this.props.onEnterPressed && this.props.onEnterPressed();
    } else if (e.key === 'Escape') {
      this.props.onEscapePressed && this.props.onEscapePressed();
    }
  }
}

InputArea.displayName = 'InputArea';

InputArea.defaultProps = {
  theme: 'amaterial',
};

InputArea.propTypes = {
  id: PropTypes.string,
  value: PropTypes.string,
  style: PropTypes.oneOf(['normal', 'paneltitle', 'material', 'amaterial']),
  theme: PropTypes.oneOf(['normal', 'paneltitle', 'material', 'amaterial']),
  forceHover: PropTypes.bool,
  forceFocus: PropTypes.bool,
  placeholder: PropTypes.string,
  error: PropTypes.bool,
  defaultValue: PropTypes.string,
  tabIndex: PropTypes.number,
  menuArrow: PropTypes.bool,
  autoFocus: PropTypes.bool,
  autoSelect: PropTypes.bool,
  onChange: PropTypes.func,
  onClear: PropTypes.func,
  onBlur: PropTypes.func,
  onFocus: PropTypes.func,
  onEscapePressed: PropTypes.func,
  onEnterPressed: PropTypes.func,
  onKeyDown: PropTypes.func,
  onKeyUp: PropTypes.func,
  iconLeft: PropTypes.object,
  readOnly: PropTypes.bool,
  rows: PropTypes.number,
  minHeight: PropTypes.string,
  maxHeight: PropTypes.string,
  resizable: PropTypes.bool,
  errorMessage: PropTypes.string
};

export default InputArea;
<commit_msg>reverted theme change<commit_after>import React, {PropTypes} from 'react';
import classNames from 'classnames';
import Exclamation from './Exclamation';
import WixComponent from '../WixComponent';

import styles from './InputArea.scss';

class InputArea extends WixComponent {

  constructor(props) {
    super(props);
    this._onKeyDown = this._onKeyDown.bind(this);
    this._onFocus = this._onFocus.bind(this);
    this._onBlur = this._onBlur.bind(this);
    this.focus = this.focus.bind(this);
    this.blur = this.blur.bind(this);
    this.select = this.select.bind(this);
  }

  state = {
    focus: false
  };

  componentDidMount() {
    super.componentDidMount();
    this.props.autoFocus && this._onFocus();
  }

  render() {
    const {
      autoFocus,
      defaultValue,
      error,
      forceFocus,
      forceHover,
      id,
      onChange,
      onKeyUp,
      placeholder,
      readOnly,
      tabIndex,
      rows,
      value,
      minHeight,
      maxHeight,
      resizable,
      theme,
      errorMessage
    } = this.props;

    const inlineStyle = {};

    if (minHeight) {
      inlineStyle.minHeight = minHeight;
    }

    if (maxHeight) {
      inlineStyle.maxHeight = maxHeight;
    }

    const classes = classNames({
      [styles.root]: true,
      [styles[`theme-${theme}`]]: true,
      [styles.hasError]: !!error,
      [styles.hasHover]: forceHover,
      [styles.hasFocus]: forceFocus || this.state.focus,
      [styles.resizable]: !!resizable,
      [styles.nonResizable]: !resizable
    });

    return (

        <textarea
          rows={rows}
          ref={ref => this.textArea = ref}
          className={styles.inputArea}
          id={id}
          style={inlineStyle}
          defaultValue={defaultValue}
          value={value}
          onChange={onChange}
          onFocus={this._onFocus}
          onBlur={this._onBlur}
          onKeyDown={this._onKeyDown}
          onDoubleClick={this._onDoubleClick}
          placeholder={placeholder}
          tabIndex={tabIndex}
          autoFocus={autoFocus}
          onKeyUp={onKeyUp}
          readOnly={readOnly}
          />
        {error && <Exclamation errorMessage={errorMessage}/>}
        {theme === 'material' &&
}

    );
  }

  focus() {
    this.textArea && this.textArea.focus();
  }

  blur() {
    this.textArea && this.textArea.blur();
  }

  select() {
    this.textArea && this.textArea.select();
  }

  _onFocus() {
    this.setState({focus: true});
    this.props.onFocus && this.props.onFocus();

    if (this.props.autoSelect) {
      // Set timeout is needed here since onFocus is called before react
      // gets the reference for the input (specifically when autoFocus
      // is on. So setTimeout ensures we have the ref.input needed in select)
      setTimeout(() => this.select(), 0);
    }
  }

  _onBlur(e) {
    this.setState({focus: false});
    this.props.onBlur && this.props.onBlur(e);
  }

  _onKeyDown(e) {
    this.props.onKeyDown && this.props.onKeyDown(e);

    if (e.key === 'Enter') {
      this.props.onEnterPressed && this.props.onEnterPressed();
    } else if (e.key === 'Escape') {
      this.props.onEscapePressed && this.props.onEscapePressed();
    }
  }
}

InputArea.displayName = 'InputArea';

InputArea.defaultProps = {
  theme: 'normal',
};

InputArea.propTypes = {
  id: PropTypes.string,
  value: PropTypes.string,
  style: PropTypes.oneOf(['normal', 'paneltitle', 'material', 'amaterial']),
  theme: PropTypes.oneOf(['normal', 'paneltitle', 'material', 'amaterial']),
  forceHover: PropTypes.bool,
  forceFocus: PropTypes.bool,
  placeholder: PropTypes.string,
  error: PropTypes.bool,
  defaultValue: PropTypes.string,
  tabIndex: PropTypes.number,
  menuArrow: PropTypes.bool,
  autoFocus: PropTypes.bool,
  autoSelect: PropTypes.bool,
  onChange: PropTypes.func,
  onClear: PropTypes.func,
  onBlur: PropTypes.func,
  onFocus: PropTypes.func,
  onEscapePressed: PropTypes.func,
  onEnterPressed: PropTypes.func,
  onKeyDown: PropTypes.func,
  onKeyUp: PropTypes.func,
  iconLeft: PropTypes.object,
  readOnly: PropTypes.bool,
  rows: PropTypes.number,
  minHeight: PropTypes.string,
  maxHeight: PropTypes.string,
  resizable: PropTypes.bool,
  errorMessage: PropTypes.string
};

export default InputArea;
<|endoftext|>


<commit_before>function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map(child =>
        typeof child === "object"
          ? child
          : createTextElement(child)
      ),
    },
  }
}

function createTextElement(text) {
  return {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: text,
      children: [],
    },
  }
}

function createDom(fiber) {
  const dom =
    fiber.type == "TEXT_ELEMENT"
      ? document.createTextNode("")
      : document.createElement(fiber.type)

  const isProperty = key => key !== "children"
  Object.keys(fiber.props)
    .filter(isProperty)
    .forEach(name => {
      dom[name] = fiber.props[name]
    })

  return dom
}

function commitRoot() {
  commitWork(wipRoot.child)
  currentRoot = wipRoot
  wipRoot = null
}

function commitWork(fiber) {
  if (!fiber) {
    return
  }
  const domParent = fiber.parent.dom
  domParent.appendChild(fiber.dom)
  commitWork(fiber.child)
  commitWork(fiber.sibling)
}

function render(element, container) {
  wipRoot = {
    dom: container,
    props: {
      children: [element],
    },
    alternate: currentRoot,
  }
  nextUnitOfWork = wipRoot
}

let nextUnitOfWork = null
let currentRoot = null
let wipRoot = null

function workLoop(deadline) {
  let shouldYield = false
  while (nextUnitOfWork && !shouldYield) {
    nextUnitOfWork = performUnitOfWork(
      nextUnitOfWork
    )
    shouldYield = deadline.timeRemaining() < 1
  }

  if (!nextUnitOfWork && wipRoot) {
    commitRoot()
  }

  requestIdleCallback(workLoop)
}

requestIdleCallback(workLoop)

function performUnitOfWork(fiber) {
  if (!fiber.dom) {
    fiber.dom = createDom(fiber)
  }

  const elements = fiber.props.children
  reconcileChildren(fiber, elements)

  if (fiber.child) {
    return fiber.child
  }
  let nextFiber = fiber
  while (nextFiber) {
    if (nextFiber.sibling) {
      return nextFiber.sibling
    }
    nextFiber = nextFiber.parent
  }
}

function reconcileChildren(wipFiber, elements) {
  let index = 0
  let oldFiber =
    wipFiber.alternate && wipFiber.alternate.child
  let prevSibling = null

  while (
    index < elements.length ||
    oldFiber != null
  ) {
    const element = elements[index]
    let newFiber = null

    // TODO compare oldFiber to element

    if (oldFiber) {
      oldFiber = oldFiber.sibling
    }

    if (index === 0) {
      wipFiber.child = newFiber
    } else if (element) {
      prevSibling.sibling = newFiber
    }

    prevSibling = newFiber
    index++
  }
}

const Didact = {
  createElement,
  render,
}

/** @jsx Didact.createElement */
const element = (

    bar

)
const container = document.getElementById("root")
Didact.render(element, container)
<commit_msg>List reconciliation cases<commit_after>function createElement(type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map(child =>
        typeof child === "object"
          ? child
          : createTextElement(child)
      ),
    },
  }
}

function createTextElement(text) {
  return {
    type: "TEXT_ELEMENT",
    props: {
      nodeValue: text,
      children: [],
    },
  }
}

function createDom(fiber) {
  const dom =
    fiber.type == "TEXT_ELEMENT"
      ? document.createTextNode("")
      : document.createElement(fiber.type)

  const isProperty = key => key !== "children"
  Object.keys(fiber.props)
    .filter(isProperty)
    .forEach(name => {
      dom[name] = fiber.props[name]
    })

  return dom
}

function commitRoot() {
  commitWork(wipRoot.child)
  currentRoot = wipRoot
  wipRoot = null
}

function commitWork(fiber) {
  if (!fiber) {
    return
  }
  const domParent = fiber.parent.dom
  domParent.appendChild(fiber.dom)
  commitWork(fiber.child)
  commitWork(fiber.sibling)
}

function render(element, container) {
  wipRoot = {
    dom: container,
    props: {
      children: [element],
    },
    alternate: currentRoot,
  }
  nextUnitOfWork = wipRoot
}

let nextUnitOfWork = null
let currentRoot = null
let wipRoot = null

function workLoop(deadline) {
  let shouldYield = false
  while (nextUnitOfWork && !shouldYield) {
    nextUnitOfWork = performUnitOfWork(
      nextUnitOfWork
    )
    shouldYield = deadline.timeRemaining() < 1
  }

  if (!nextUnitOfWork && wipRoot) {
    commitRoot()
  }

  requestIdleCallback(workLoop)
}

requestIdleCallback(workLoop)

function performUnitOfWork(fiber) {
  if (!fiber.dom) {
    fiber.dom = createDom(fiber)
  }

  const elements = fiber.props.children
  reconcileChildren(fiber, elements)

  if (fiber.child) {
    return fiber.child
  }
  let nextFiber = fiber
  while (nextFiber) {
    if (nextFiber.sibling) {
      return nextFiber.sibling
    }
    nextFiber = nextFiber.parent
  }
}

function reconcileChildren(wipFiber, elements) {
  let index = 0
  let oldFiber =
    wipFiber.alternate && wipFiber.alternate.child
  let prevSibling = null

  while (
    index < elements.length ||
    oldFiber != null
  ) {
    const element = elements[index]
    let newFiber = null

    const sameType =
      oldFiber &&
      element &&
      element.type == oldFiber.type

    if (sameType) {
      // TODO update the node
    }
    if (element && !sameType) {
      // TODO add this node
    }
    if (oldFiber && !sameType) {
      // TODO delete the oldFiber's node
    }

    if (oldFiber) {
      oldFiber = oldFiber.sibling
    }

    if (index === 0) {
      wipFiber.child = newFiber
    } else if (element) {
      prevSibling.sibling = newFiber
    }

    prevSibling = newFiber
    index++
  }
}

const Didact = {
  createElement,
  render,
}

/** @jsx Didact.createElement */
const element = (

    bar

)
const container = document.getElementById("root")
Didact.render(element, container)
<|endoftext|>