<commit_before>(function() {
    'use strict';

    /* Global var accessible from any loaded module */
    global.cloudcmd     = {};

    var DIR, LIBDIR, SRVDIR, JSONDIR, HTMLDIR,
        Util,
        UTIL = 'util',

        SLASH,
        ISWIN32,
        ext,
        path, fs, zlib, url, pipe, CloudFunc, diffPatch,

        OK, FILE_NOT_FOUND, MOVED_PERMANENTLY,
        REQUEST, RESPONSE,

        Config = {
            server  : true,
            socket  : true,
            port    : 80
        };

    /* Consts */

    exports.OK                  = OK                = 200;
                                  MOVED_PERMANENTLY = 301;
    exports.FILE_NOT_FOUND      = FILE_NOT_FOUND    = 404;

    exports.REQUEST     = REQUEST           = 'request';
    exports.RESPONSE    = RESPONSE          = 'response';

    /* Native Modules*/
    exports.crypto                          = require('crypto'),
    exports.child_process                   = require('child_process'),
    exports.fs          = fs                = require('fs'),
    exports.http                            = require('http'),
    exports.https                           = require('https'),
    exports.path        = path              = require('path'),
    exports.url         = url               = require('url'),
    exports.querystring                     = require('querystring'),

    /* Constants */
    /* current dir + 2 levels up */
    exports.WIN32       = ISWIN32           = isWin32();
    exports.SLASH       = SLASH             = '/',

    exports.SRVDIR      = SRVDIR            = __dirname + SLASH,
    exports.LIBDIR      = LIBDIR            = path.normalize(SRVDIR + '../'),
    exports.DIR         = DIR               = path.normalize(LIBDIR + '../'),
    exports.HTMLDIR     = HTMLDIR           = DIR + 'html' + SLASH,
    exports.JSONDIR     = JSONDIR           = DIR + 'json' + SLASH,

    /* Functions */
    exports.require                         = mrequire,
    exports.librequire                      = librequire,
    exports.srvrequire                      = srvrequire,
    exports.rootrequire                     = rootrequire,
    exports.quietrequire                    = quietrequire,

    exports.generateHeaders                 = generateHeaders,
    exports.getQuery                        = getQuery,
    exports.isGZIP                          = isGZIP,
    exports.mainSetHeader                   = mainSetHeader,

    exports.sendFile                        = sendFile,
    exports.sendResponse                    = sendResponse,
    exports.sendError                       = sendError,
    exports.redirect                        = redirect,

    exports.checkParams                     = checkParams,
    exports.checkCallBackParams             = checkCallBackParams,

    /* compitability with old versions of node */
    exports.fs.exists                       = exports.fs.exists || exports.path.exists,

    /* Needed Modules */

    /* we can not use librequare here */
    exports.util        = Util              = require(LIBDIR + UTIL),

    exports.zlib        = zlib              = mrequire('zlib'),

    /* Main Information */
    exports.modules                         = jsonrequire('modules');
    exports.ext         = ext               = jsonrequire('ext');
    exports.mainpackage                     = rootrequire('package');
    /* base configuration */
    exports.config                          = Config,

    /*
     * Any of loaded below modules could work with global var so
     * it should be initialized first. Becouse of almost any of
     * moudles do not depends on each other all needed information
     * for all modules is initialized hear.
     */
    global.cloudcmd.main                    = exports;

    exports.VOLUMES                         = getVolumes(),

    /* Additional Modules */
    exports.cloudfunc   = CloudFunc         = librequire('cloudfunc'),
    exports.pipe        = pipe              = srvrequire('pipe'),
    exports.socket                          = srvrequire('socket'),
    exports.console                         = srvrequire('console'),
    exports.terminal                        = srvrequire('terminal'),
    exports.express                         = srvrequire('express'),
    exports.auth                            = srvrequire('auth').auth,
    exports.appcache                        = srvrequire('appcache'),
    exports.dir                             = srvrequire('dir'),
    exports.hash                            = srvrequire('hash'),
    diffPatch                               = librequire('diff/diff-match-patch').diff_match_patch,
    exports.diff                            = new (librequire('diff').DiffProto)(diffPatch),
    exports.time                            = srvrequire('time');
    exports.users                           = srvrequire('users');
    exports.rest                            = srvrequire('rest').api,
    exports.update                          = srvrequire('update'),
    exports.ischanged                       = srvrequire('ischanged');
    exports.commander                       = srvrequire('commander');
    exports.files                           = srvrequire('files');

    exports.minify                          = srvrequire('minify').Minify;

    /* second initializing after all modules load, so global var is   *
     * totally filled of all information that should know all modules */
    global.cloudcmd.main            = exports;

    /**
     * function do safe require of needed module
     * @param {Strin} pSrc
     */
    function mrequire(pSrc) {
        var lModule, msg,
            lError = Util.tryCatch(function() {
                lModule = require(pSrc);
            });

        if (lError && lError.code === 'MODULE_NOT_FOUND')
            msg = CloudFunc.formatMsg('require', pSrc, 'no');
        else
            Util.log(lError);

        Util.log(msg);

        return lModule;
    }

    function quietrequire(pSrc) {
        var lModule;

        Util.tryCatch(function() {
            lModule = require(pSrc);
        });

        return lModule;
    }

    function rootrequire(pSrc) { return mrequire(DIR + pSrc); }

    function librequire(pSrc) { return mrequire(LIBDIR + pSrc); }

    function srvrequire(pSrc) { return mrequire(SRVDIR + pSrc); }

    function jsonrequire(pSrc) { return mrequire(JSONDIR + pSrc);}

    /**
     * function check is current platform is win32
     */
    function isWin32() { return process.platform === 'win32'; }

    /**
     * get volumes if win32 or get nothing if nix
     */
    function getVolumes() {
        var lRet = ISWIN32 ? [] : '/';

        if (ISWIN32)
            srvrequire('win').getVolumes(function(pVolumes) {
                Util.log(pVolumes);
                exports.VOLUMES = pVolumes;
            });

        return lRet;
    }

    /**
     * Функция создаёт заголовки файлов
     * в зависимости от расширения файла
     * перед отправкой их клиенту
     * @param pParams
     *  name - имя файла
     * gzip - данные сжаты gzip'ом
     * query
     * https://developers.google.com/speed/docs/best-practices/caching?hl=ru#LeverageProxyCaching
     */
    function generateHeaders(pParams) {
        var lRet    = Util.checkObjTrue(pParams, ['name']);

        if (lRet) {
            var p                   = pParams,
                lExt                = Util.getExtension(p.name),
                lType               = ext[lExt] || 'text/plain',
                lContentEncoding    = '';

            /* if type of file any, but img - then we shoud specify charset */
            if (!Util.isContainStr(lType, 'img'))
                lContentEncoding = '; charset=UTF-8';

            if (Util.isContainStr(p.query, 'download'))
                lType = 'application/octet-stream';

            lRet = {
                'Access-Control-Allow-Origin'   : '*',
                'Content-Type'                  : lType + lContentEncoding,
                'last-modified'                 : new Date().toString(),
                'Vary'                          : 'Accept-Encoding'
            };

            if (!Util.strCmp(lExt, '.appcache') && p.cache)
                lRet['cache-control']       = 'max-age=' + 31337 * 21;

            if (p.gzip)
                lRet['content-encoding']    = 'gzip';
        }

        return lRet;
    }

    function mainSetHeader(pParams) {
        var p, header, lGzip,
            lRet = checkParams(pParams);

        if (lRet) {
            p       = pParams;
            lGzip   = isGZIP(p.request) && p.gzip;

            header  = generateHeaders({
                name    : p.name,
                cache   : p.cache,
                gzip    : lGzip,
                query   : getQuery(p.request)
            });

            setHeader(header, p.response);
            p.response.statusCode = p.status || OK;
        }
    }

    /**
     * send file to client thru pipe
     * and gzip it if client support
     *
     * @param pName - имя файла
     * @param pGzip - данные сжаты gzip'ом
     */
    function sendFile(pParams) {
        var header, lRet = checkParams(pParams);

        if (lRet) {
            var p       = pParams,
                lGzip   = isGZIP(p.request) && p.gzip;

            mainSetHeader(pParams);

            pipe.create({
                from    : p.name,
                write   : p.response,
                gzip    : lGzip,
                callback: function(error) {
                    if (error)
                        sendError(pParams, error);
                }
            });
        }

        return lRet;
    }

    /**
     * Функция высылает ответ серверу
     * @param pHead     - заголовок
     * @param Data      - данные
     * @param pName     - имя отсылаемого файла
     */
    function sendResponse(pParams, pData, pNotLog) {
        var p, lQuery, lGzip, lHead, data,
            lRet = checkParams(pParams);

        if (lRet) {
            p           = pParams;
            data        = p.data || pData;
            lGzip       = isGZIP(p.request);

            lHead       = generateHeaders({
                name    : p.name,
                cache   : p.cache,
                gzip    : lGzip,
                query   : lQuery
            });

            setHeader(lHead, p.response);

            if (!pNotLog)
                Util.log(data);

            /* если браузер поддерживает gzip-сжатие - сжимаем данные*/
            Util.ifExec(!lGzip,
                function(pParams) {
                    var lRet = Util.checkObj(pParams, ['data']);

                    if (lRet) {
                        p.status    = pParams.status || p.status;
                        p.data      = pParams.data;
                    }

                    p.response.statusCode = p.status || OK;
                    p.response.end(p.data);
                },

                function(pCallBack) {
                    zlib.gzip (data, Util.call(gzipData, {
                        callback    : pCallBack
                    }));
                });
        }
    }

    /**
     * redirect to another URL
     */
    function redirect(pParams) {
        var p, header,
            lRet    = Util.checkObjTrue(pParams, [RESPONSE]);

        if (lRet) {
            p       = pParams;

            header  = {
                'Location': p.url
            };

            setHeader(header, p.response);
            p.response.statusCode = MOVED_PERMANENTLY;
            p.response.end();
        }
    }

    /**
     * send error response
     */
    function sendError(pParams, pError) {
        var p, lRet     = checkParams(pParams);

        if (lRet) {
            p           = pParams;
            p.status    = FILE_NOT_FOUND;

            if (!p.data && pError)
              p.data    = pError.toString();

            sendResponse(p);
        }
    }

    /**
     * Функция получает сжатые данные
     * @param pHeader - заголовок файла
     * @pName
     */
    function gzipData(pParams) {
        var lRet    = checkCallBackParams(pParams),
            p       = pParams;

        if (lRet)
            lRet = Util.checkObj(pParams.params, ['callback']);

        if (lRet) {
            var lCallBack   = p.params.callback,
                lParams       = {};

            if (!p.error)
                lParams.data      = p.data;
            else {
                lParams.status    = FILE_NOT_FOUND;
                lParams.data      = p.error.toString();
            }

            Util.exec(lCallBack, lParams);
        }
    }

    function checkCallBackParams(pParams) {
        return Util.checkObj(pParams, ['error', 'data', 'params']);
    }

    function checkParams(pParams, pAdditional) {
        var lRet = Util.checkObjTrue( pParams, ['name', REQUEST, RESPONSE] );

        if (lRet && pAdditional)
            lRet = Util.checkObjTrue( pParams, pAdditional);

        return lRet;
    }

    function getQuery(pReq) {
        var lQuery, lParsedUrl;

        if (pReq) {
            lParsedUrl  = url.parse(pReq.url);
            lQuery      = lParsedUrl.query;
        }

        return lQuery;
    }

    function isGZIP(pReq) {
        var lEnc, lGZIP;
        if (pReq) {
            lEnc        = pReq.headers['accept-encoding'] || '';
            lGZIP       = lEnc.match(/\bgzip\b/);
        }

        return lGZIP;
    }

    function setHeader(header, response) {
        var name;

        if (!response.headersSent && Util.isObject(header))
            for (name in header)
                response.setHeader(name, header[name]);
    }

})();
<commit_msg>chore(main) pSrc -> src<commit_after>(function() {
    'use strict';

    /* Global var accessible from any loaded module */
    global.cloudcmd     = {};

    var DIR, LIBDIR, SRVDIR, JSONDIR, HTMLDIR,
        Util,
        UTIL = 'util',

        SLASH,
        ISWIN32,
        ext,
        path, fs, zlib, url, pipe, CloudFunc, diffPatch,

        OK, FILE_NOT_FOUND, MOVED_PERMANENTLY,
        REQUEST, RESPONSE,

        Config = {
            server  : true,
            socket  : true,
            port    : 80
        };

    /* Consts */

    exports.OK                  = OK                = 200;
                                  MOVED_PERMANENTLY = 301;
    exports.FILE_NOT_FOUND      = FILE_NOT_FOUND    = 404;

    exports.REQUEST     = REQUEST           = 'request';
    exports.RESPONSE    = RESPONSE          = 'response';

    /* Native Modules*/
    exports.crypto                          = require('crypto'),
    exports.child_process                   = require('child_process'),
    exports.fs          = fs                = require('fs'),
    exports.http                            = require('http'),
    exports.https                           = require('https'),
    exports.path        = path              = require('path'),
    exports.url         = url               = require('url'),
    exports.querystring                     = require('querystring'),

    /* Constants */
    /* current dir + 2 levels up */
    exports.WIN32       = ISWIN32           = isWin32();
    exports.SLASH       = SLASH             = '/',

    exports.SRVDIR      = SRVDIR            = __dirname + SLASH,
    exports.LIBDIR      = LIBDIR            = path.normalize(SRVDIR + '../'),
    exports.DIR         = DIR               = path.normalize(LIBDIR + '../'),
    exports.HTMLDIR     = HTMLDIR           = DIR + 'html' + SLASH,
    exports.JSONDIR     = JSONDIR           = DIR + 'json' + SLASH,

    /* Functions */
    exports.require                         = mrequire,
    exports.librequire                      = librequire,
    exports.srvrequire                      = srvrequire,
    exports.rootrequire                     = rootrequire,
    exports.quietrequire                    = quietrequire,

    exports.generateHeaders                 = generateHeaders,
    exports.getQuery                        = getQuery,
    exports.isGZIP                          = isGZIP,
    exports.mainSetHeader                   = mainSetHeader,

    exports.sendFile                        = sendFile,
    exports.sendResponse                    = sendResponse,
    exports.sendError                       = sendError,
    exports.redirect                        = redirect,

    exports.checkParams                     = checkParams,
    exports.checkCallBackParams             = checkCallBackParams,

    /* compitability with old versions of node */
    exports.fs.exists                       = exports.fs.exists || exports.path.exists,

    /* Needed Modules */

    /* we can not use librequare here */
    exports.util        = Util              = require(LIBDIR + UTIL),

    exports.zlib        = zlib              = mrequire('zlib'),

    /* Main Information */
    exports.modules                         = jsonrequire('modules');
    exports.ext         = ext               = jsonrequire('ext');
    exports.mainpackage                     = rootrequire('package');
    /* base configuration */
    exports.config                          = Config,

    /*
     * Any of loaded below modules could work with global var so
     * it should be initialized first. Becouse of almost any of
     * moudles do not depends on each other all needed information
     * for all modules is initialized hear.
     */
    global.cloudcmd.main                    = exports;

    exports.VOLUMES                         = getVolumes(),

    /* Additional Modules */
    exports.cloudfunc   = CloudFunc         = librequire('cloudfunc'),
    exports.pipe        = pipe              = srvrequire('pipe'),
    exports.socket                          = srvrequire('socket'),
    exports.console                         = srvrequire('console'),
    exports.terminal                        = srvrequire('terminal'),
    exports.express                         = srvrequire('express'),
    exports.auth                            = srvrequire('auth').auth,
    exports.appcache                        = srvrequire('appcache'),
    exports.dir                             = srvrequire('dir'),
    exports.hash                            = srvrequire('hash'),
    diffPatch                               = librequire('diff/diff-match-patch').diff_match_patch,
    exports.diff                            = new (librequire('diff').DiffProto)(diffPatch),
    exports.time                            = srvrequire('time');
    exports.users                           = srvrequire('users');
    exports.rest                            = srvrequire('rest').api,
    exports.update                          = srvrequire('update'),
    exports.ischanged                       = srvrequire('ischanged');
    exports.commander                       = srvrequire('commander');
    exports.files                           = srvrequire('files');

    exports.minify                          = srvrequire('minify').Minify;

    /* second initializing after all modules load, so global var is   *
     * totally filled of all information that should know all modules */
    global.cloudcmd.main            = exports;

    /**
     * function do safe require of needed module
     * @param {Strin} src
     */
    function mrequire(src) {
        var module, msg,
            error = Util.tryCatch(function() {
                module = require(src);
            });

        if (error)
            if (error.code === 'MODULE_NOT_FOUND')
                msg = CloudFunc.formatMsg('require', src, 'no');
            else
                Util.log(error);

        Util.log(msg);

        return module;
    }

    function quietrequire(src) {
        var module;

        Util.tryCatch(function() {
            module = require(src);
        });

        return module;
    }

    function rootrequire(src) { return mrequire(DIR + src); }

    function librequire(src) { return mrequire(LIBDIR + src); }

    function srvrequire(src) { return mrequire(SRVDIR + src); }

    function jsonrequire(src) { return mrequire(JSONDIR + src);}

    /**
     * function check is current platform is win32
     */
    function isWin32() { return process.platform === 'win32'; }

    /**
     * get volumes if win32 or get nothing if nix
     */
    function getVolumes() {
        var lRet = ISWIN32 ? [] : '/';

        if (ISWIN32)
            srvrequire('win').getVolumes(function(pVolumes) {
                Util.log(pVolumes);
                exports.VOLUMES = pVolumes;
            });

        return lRet;
    }

    /**
     * Функция создаёт заголовки файлов
     * в зависимости от расширения файла
     * перед отправкой их клиенту
     * @param pParams
     *  name - имя файла
     * gzip - данные сжаты gzip'ом
     * query
     * https://developers.google.com/speed/docs/best-practices/caching?hl=ru#LeverageProxyCaching
     */
    function generateHeaders(pParams) {
        var lRet    = Util.checkObjTrue(pParams, ['name']);

        if (lRet) {
            var p                   = pParams,
                lExt                = Util.getExtension(p.name),
                lType               = ext[lExt] || 'text/plain',
                lContentEncoding    = '';

            /* if type of file any, but img - then we shoud specify charset */
            if (!Util.isContainStr(lType, 'img'))
                lContentEncoding = '; charset=UTF-8';

            if (Util.isContainStr(p.query, 'download'))
                lType = 'application/octet-stream';

            lRet = {
                'Access-Control-Allow-Origin'   : '*',
                'Content-Type'                  : lType + lContentEncoding,
                'last-modified'                 : new Date().toString(),
                'Vary'                          : 'Accept-Encoding'
            };

            if (!Util.strCmp(lExt, '.appcache') && p.cache)
                lRet['cache-control']       = 'max-age=' + 31337 * 21;

            if (p.gzip)
                lRet['content-encoding']    = 'gzip';
        }

        return lRet;
    }

    function mainSetHeader(pParams) {
        var p, header, lGzip,
            lRet = checkParams(pParams);

        if (lRet) {
            p       = pParams;
            lGzip   = isGZIP(p.request) && p.gzip;

            header  = generateHeaders({
                name    : p.name,
                cache   : p.cache,
                gzip    : lGzip,
                query   : getQuery(p.request)
            });

            setHeader(header, p.response);
            p.response.statusCode = p.status || OK;
        }
    }

    /**
     * send file to client thru pipe
     * and gzip it if client support
     *
     * @param pName - имя файла
     * @param pGzip - данные сжаты gzip'ом
     */
    function sendFile(pParams) {
        var header, lRet = checkParams(pParams);

        if (lRet) {
            var p       = pParams,
                lGzip   = isGZIP(p.request) && p.gzip;

            mainSetHeader(pParams);

            pipe.create({
                from    : p.name,
                write   : p.response,
                gzip    : lGzip,
                callback: function(error) {
                    if (error)
                        sendError(pParams, error);
                }
            });
        }

        return lRet;
    }

    /**
     * Функция высылает ответ серверу
     * @param pHead     - заголовок
     * @param Data      - данные
     * @param pName     - имя отсылаемого файла
     */
    function sendResponse(pParams, pData, pNotLog) {
        var p, lQuery, lGzip, lHead, data,
            lRet = checkParams(pParams);

        if (lRet) {
            p           = pParams;
            data        = p.data || pData;
            lGzip       = isGZIP(p.request);

            lHead       = generateHeaders({
                name    : p.name,
                cache   : p.cache,
                gzip    : lGzip,
                query   : lQuery
            });

            setHeader(lHead, p.response);

            if (!pNotLog)
                Util.log(data);

            /* если браузер поддерживает gzip-сжатие - сжимаем данные*/
            Util.ifExec(!lGzip,
                function(pParams) {
                    var lRet = Util.checkObj(pParams, ['data']);

                    if (lRet) {
                        p.status    = pParams.status || p.status;
                        p.data      = pParams.data;
                    }

                    p.response.statusCode = p.status || OK;
                    p.response.end(p.data);
                },

                function(pCallBack) {
                    zlib.gzip (data, Util.call(gzipData, {
                        callback    : pCallBack
                    }));
                });
        }
    }

    /**
     * redirect to another URL
     */
    function redirect(pParams) {
        var p, header,
            lRet    = Util.checkObjTrue(pParams, [RESPONSE]);

        if (lRet) {
            p       = pParams;

            header  = {
                'Location': p.url
            };

            setHeader(header, p.response);
            p.response.statusCode = MOVED_PERMANENTLY;
            p.response.end();
        }
    }

    /**
     * send error response
     */
    function sendError(pParams, pError) {
        var p, lRet     = checkParams(pParams);

        if (lRet) {
            p           = pParams;
            p.status    = FILE_NOT_FOUND;

            if (!p.data && pError)
              p.data    = pError.toString();

            sendResponse(p);
        }
    }

    /**
     * Функция получает сжатые данные
     * @param pHeader - заголовок файла
     * @pName
     */
    function gzipData(pParams) {
        var lRet    = checkCallBackParams(pParams),
            p       = pParams;

        if (lRet)
            lRet = Util.checkObj(pParams.params, ['callback']);

        if (lRet) {
            var lCallBack   = p.params.callback,
                lParams       = {};

            if (!p.error)
                lParams.data      = p.data;
            else {
                lParams.status    = FILE_NOT_FOUND;
                lParams.data      = p.error.toString();
            }

            Util.exec(lCallBack, lParams);
        }
    }

    function checkCallBackParams(pParams) {
        return Util.checkObj(pParams, ['error', 'data', 'params']);
    }

    function checkParams(pParams, pAdditional) {
        var lRet = Util.checkObjTrue( pParams, ['name', REQUEST, RESPONSE] );

        if (lRet && pAdditional)
            lRet = Util.checkObjTrue( pParams, pAdditional);

        return lRet;
    }

    function getQuery(pReq) {
        var lQuery, lParsedUrl;

        if (pReq) {
            lParsedUrl  = url.parse(pReq.url);
            lQuery      = lParsedUrl.query;
        }

        return lQuery;
    }

    function isGZIP(pReq) {
        var lEnc, lGZIP;
        if (pReq) {
            lEnc        = pReq.headers['accept-encoding'] || '';
            lGZIP       = lEnc.match(/\bgzip\b/);
        }

        return lGZIP;
    }

    function setHeader(header, response) {
        var name;

        if (!response.headersSent && Util.isObject(header))
            for (name in header)
                response.setHeader(name, header[name]);
    }

})();
<|endoftext|>


<commit_before>var colors = {
    0: "lightgray",
    1: "#edc240",
    2: "#afd8f8",
    3: "#cb4b4b",
    4: "#4da74d",
    5: "#9440ed",
    6: "rgb(189, 155, 51)",
    7: "rgb(140,172,198)"
};

var target = $('#target');
var spinner = $('#spinner');
$(document)
    .ajaxStart(function () {
        $('html, body').css('cursor', 'wait');
        target.overlay();
    })
    .ajaxStop(function () {
        $('html, body').css('cursor', 'auto');
        target.overlayout();
    });

$(function () {

    initLegend();

    // Load the last 14 days
    getFortnight(function (rawdata) {
        render(rawdata)
    });
});

function initLegend() {
    $('#detail-legend').append('

');
};

function render(rawdata) {

    if (!rawdata) {
        // TODO Show error message
        console.log('Sorry, no data found.');
        return;
    }

    var data = convertDataForFlot(rawdata);

    // Legend -------------------------------------------------------------
    var legendContainer = $('#detail-legend');
    var legendHasNoData = legendContainer.find('.table-row-data').length === 0;
    if (legendHasNoData) {
        $.each(data, function (key, val) {
            var tablerow = '
' +
                '
<input type="checkbox" name="' + key + '" checked="checked" id="id' + key + '"></input>
' +
                '

' +
                '
' + val.label + '
' +
                '

' +
                '
';
            legendContainer.find('.div-table').append(tablerow);
        });
    }
    legendContainer.find("input").click(updatePlot);

    var currentSelection = {
        min: undefined,
        max: undefined
    };

    // Main plotting function ---------------------------------------------
    function updatePlot() {

        var plotdata = [];

        legendContainer.find('input:checked').each(function () {
            var key = $(this).attr('name');
            if (key && data[key]) {
                plotdata.push(data[key])
            }
        });

        var rangeselectionCallback = function (o) {
            var xaxis = detailPlot.getAxes().xaxis;

            if (o.start <= xaxis.datamin) {
                loadAnotherFortnight(xaxis.datamin, xaxis.datamax);
            } else {
                xaxis.options.min = o.start;
                xaxis.options.max = o.end;
                detailPlot.setupGrid();
                detailPlot.draw();

                currentSelection.min = o.start;
                currentSelection.max = o.end;
            }
        };

        var detailPlaceholder = $('#detail-placeholder');
        var detailPlot = $.plot(detailPlaceholder, plotdata, {
            xaxis: {
                mode: 'time'
            },
            yaxis: {
                panRange: false
            },
            series: {
                lines: {
                    show: true
                },
                points: {
                    show: false
                }
            },
            legend: {
                show: false // Note: The legend is configured manually (see legendContainer)
            },
            grid: {
                hoverable: true,
                clickable: true,
                autoHighlight: false,
                borderWidth: 0
            },
            crosshair: {
                mode: 'x'
            },
            pan: {
                interactive: true
            }
        });

        var overviewPlaceholder = $('#overview-placeholder');
        var overviewData = $.extend(true, [], plotdata);
        for (var i = 0; i < overviewData.length; i++) {
            overviewData[i].color = '#ccc';
            overviewData[i].label = undefined;
        }

        var overviewPlot = $.plot(overviewPlaceholder, overviewData, {
            series: {
                lines: {
                    show: true,
                    lineWidth: 1
                },
                shadowSize: 0,
                points: {
                    show: false
                }
            },
            xaxis: {
                mode: "time"
            },
            yaxis: {
                labelWidth: 16,
                reserveSpace: true,
                show: false
            },
            legend: {
                show: false
            },
            grid: {
                hoverable: false,
                borderWidth: {
                    'top': 1,
                    'right': 1,
                    'left': 1,
                    'bottom': 1
                },
                borderColor: 'darkgray'
            },
            rangeselection: {
                color: '#999',
                enabled: true,
                start: detailPlot.getData()[0].data[0][0],
                end: detailPlot.getData()[0].data[detailPlot.getData()[0].data.length - 1][0],
                callback: rangeselectionCallback
            }
        });

        // Since the canvas is redrawn after every interaction, we have to manually set the selection range (if it exists)
        if (currentSelection.min !== undefined && currentSelection.max !== undefined) {
            var xaxis = detailPlot.getAxes().xaxis;
            xaxis.options.min = currentSelection.min;
            xaxis.options.max = currentSelection.max;
            detailPlot.setupGrid();
            detailPlot.draw();

            overviewPlot.getOptions().rangeselection.start = currentSelection.min;
            overviewPlot.getOptions().rangeselection.end = currentSelection.max;
            overviewPlot.setupGrid();
            overviewPlot.draw();
        }

        // PLOTHOVER: UPDATE VALUE IN LEGEND
        detailPlaceholder.bind('plothover', function (event, pos, item) {
            var updateDetailSelectionTimeout = null;
            var latestPosition = null;

            function updateDetailSelection() {
                updateDetailSelectionTimeout = null;
                var pos = latestPosition;
                var axes = detailPlot.getAxes();
                if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
                    pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) {
                    //tooltipContainer.hide('slow');
                    return;
                }

                var seriesIndex, dataPointInSeries, dataset = plotdata;

                // Iterate of each time series ('seriesIndex')
                var yMax;
                for (seriesIndex = 0; seriesIndex < dataset.length; ++seriesIndex) {
                    var series = dataset[seriesIndex];

                    // Find the nearest points, x-wise
                    for (dataPointInSeries = 0; series.data.length; ++dataPointInSeries) {
                        if (series.data[dataPointInSeries][0] > pos.x) {
                            break;
                        }
                    }

                    // Now interpolate
                    var y,
                        p1 = series.data[dataPointInSeries - 1],
                        p2 = series.data[dataPointInSeries];

                    if (p1 == null) {
                        y = p2[1];
                    } else if (p2 == null) {
                        y = p1[1];
                    } else {
                        y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);
                    }

                    // Set the correct value for the current sensor
                    if ($.isNumeric(y)) {
                        var temperatureValueContainer = legendContainer.find('#temperature-value' + series.id);
                        if (temperatureValueContainer) {
                            temperatureValueContainer.text(y.toFixed(1));
                        }
                    }

                    if (y > yMax) {
                        yMax = y;
                    }
                }

                // Current time
                var m = moment(pos.x);
                m.add(-2, 'hours'); // fucking time stuff
                $('#detail-selection-header').text(m.format('YYYY-MM-DD HH:mm (dd)'));
            };

            latestPosition = pos;
            if (!updateDetailSelectionTimeout) {
                updateDetailSelectionTimeout = setTimeout(updateDetailSelection, 400);
            }
        });

        // PLOTPAN: UPDATE OVERVIEW PLOT
        detailPlaceholder.bind('plotpan', function (event, plot) {
            if (detailPlot.getAxes().xaxis.datamin <= overviewPlot.getAxes().xaxis.datamin) {
                loadAnotherFortnight(overviewPlot.getAxes().xaxis.datamin, overviewPlot.getAxes().xaxis.datamax);
            } else {
                function clamp(min, value, max) {
                    return value < min ? min : (value > max ? max : value);
                };

                function clampOverViewPlot(value) {
                    overviewMin = overviewPlot.getAxes().xaxis.min;
                    overviewMax = overviewPlot.getAxes().xaxis.max;
                    return clamp(overviewMin, value, overviewMax);
                };

                currentSelection.min = clampOverViewPlot(detailPlot.getAxes().xaxis.min);
                currentSelection.max = clampOverViewPlot(detailPlot.getAxes().xaxis.max);
                overviewPlot.setSelection(currentSelection.min, currentSelection.max);
            }
        });
    };

    updatePlot();
};

function loadAnotherFortnight(oldMin, max) {
    console.log('Reloading with oldMin value: ' + new Date(oldMin));
    console.log('Reloading with max value: ' + new Date(max));

    getByFilter(oldMin, max, function (rawdata) {
        console.log('call getByFilter is done.');
        render(rawdata);
    });
};

// Prepare data -------------------------------------------------------------------------------------------
var formatDate = function (date) {
    // requires moment.js
    return moment.utc(new Date(date)).format('ddd, YYYY MMM DD HH:mm');
};

var convertDataForFlot = function (data) {
    var flotdata = [];
    flotdata.push(mapTimeSeries(data, 'WA', 'outside', colors[0]));
    flotdata.push(mapTimeSeries(data, 'Z2', '2nd floor', colors[1]));
    flotdata.push(mapTimeSeries(data, 'Z3', '1st floor (work)', colors[2]));
    flotdata.push(mapTimeSeries(data, 'Z4', '1st floor (bathroom)', colors[3]));
    flotdata.push(mapTimeSeries(data, 'Z5', '1st floor (bedroom)', colors[4]));
    flotdata.push(mapTimeSeries(data, 'Z6', 'ground floor', colors[5]));
    return flotdata;
};

var mapTimeSeries = function (data, sensorName, label, col) {
    var series = [];
    for (var i = 0; i < data.length; i++) {
        if (data[i].sensorName === sensorName) {
            var mDate = moment(data[i].timestamp + ' +02:00', 'YYYY-MM-DD HH:mm:ss ZZ');
            mDate.add(2, 'hours'); // still don't understand why this is really necessary.
            var millis = new Date(mDate.unix()) * 1000;
            series.push([millis, data[i].degreeCelsius]);
        }
    }

    // Note: Add an 'id' property (because the label property is a descriptive string)
    return {
        data: series,
        label: label,
        color: col,
        id: sensorName
    };
};
<commit_msg>Minor improvement to panning in detailPlot.<commit_after>var colors = {
    0: "lightgray",
    1: "#edc240",
    2: "#afd8f8",
    3: "#cb4b4b",
    4: "#4da74d",
    5: "#9440ed",
    6: "rgb(189, 155, 51)",
    7: "rgb(140,172,198)"
};

var target = $('#target');
var spinner = $('#spinner');
$(document)
    .ajaxStart(function () {
        $('html, body').css('cursor', 'wait');
        target.overlay();
    })
    .ajaxStop(function () {
        $('html, body').css('cursor', 'auto');
        target.overlayout();
    });

$(function () {

    initLegend();

    // Load the last 14 days
    getFortnight(function (rawdata) {
        render(rawdata)
    });
});

function initLegend() {
    $('#detail-legend').append('

');
};

function render(rawdata) {

    if (!rawdata) {
        // TODO Show error message
        console.log('Sorry, no data found.');
        return;
    }

    var data = convertDataForFlot(rawdata);

    // Legend -------------------------------------------------------------
    var legendContainer = $('#detail-legend');
    var legendHasNoData = legendContainer.find('.table-row-data').length === 0;
    if (legendHasNoData) {
        $.each(data, function (key, val) {
            var tablerow = '
' +
                '
<input type="checkbox" name="' + key + '" checked="checked" id="id' + key + '"></input>
' +
                '

' +
                '
' + val.label + '
' +
                '

' +
                '
';
            legendContainer.find('.div-table').append(tablerow);
        });
    }
    legendContainer.find("input").click(updatePlot);

    var currentSelection = {
        min: undefined,
        max: undefined
    };

    // Main plotting function ---------------------------------------------
    function updatePlot() {

        var plotdata = [];

        legendContainer.find('input:checked').each(function () {
            var key = $(this).attr('name');
            if (key && data[key]) {
                plotdata.push(data[key])
            }
        });

        var rangeselectionCallback = function (o) {
            console.log('rangeselectionCallback invoked...');
            var xaxis = detailPlot.getAxes().xaxis;

            if (o.start <= xaxis.datamin) {
                loadAnotherFortnight(xaxis.datamin, xaxis.datamax);
            } else {
                xaxis.options.min = o.start;
                xaxis.options.max = o.end;
                detailPlot.setupGrid();
                detailPlot.draw();

                currentSelection.min = o.start;
                currentSelection.max = o.end;
            }
        };

        var detailPlaceholder = $('#detail-placeholder');
        var detailPlot = $.plot(detailPlaceholder, plotdata, {
            xaxis: {
                mode: 'time'
            },
            yaxis: {
                panRange: false
            },
            series: {
                lines: {
                    show: true
                },
                points: {
                    show: false
                }
            },
            legend: {
                show: false // Note: The legend is configured manually (see legendContainer)
            },
            grid: {
                hoverable: true,
                clickable: true,
                autoHighlight: false,
                borderWidth: 0
            },
            crosshair: {
                mode: 'x'
            },
            pan: {
                interactive: true
            }
        });

        var overviewPlaceholder = $('#overview-placeholder');
        var overviewData = $.extend(true, [], plotdata);
        for (var i = 0; i < overviewData.length; i++) {
            overviewData[i].color = '#ccc';
            overviewData[i].label = undefined;
        }

        var overviewPlot = $.plot(overviewPlaceholder, overviewData, {
            series: {
                lines: {
                    show: true,
                    lineWidth: 1
                },
                shadowSize: 0,
                points: {
                    show: false
                }
            },
            xaxis: {
                mode: "time"
            },
            yaxis: {
                labelWidth: 16,
                reserveSpace: true,
                show: false
            },
            legend: {
                show: false
            },
            grid: {
                hoverable: false,
                borderWidth: {
                    'top': 1,
                    'right': 1,
                    'left': 1,
                    'bottom': 1
                },
                borderColor: 'darkgray'
            },
            rangeselection: {
                color: '#999',
                enabled: true,
                start: detailPlot.getData()[0].data[0][0],
                end: detailPlot.getData()[0].data[detailPlot.getData()[0].data.length - 1][0],
                callback: rangeselectionCallback
            }
        });

        // Since the canvas is redrawn after every interaction, we have to manually set the selection range (if it exists)
        if (currentSelection.min !== undefined && currentSelection.max !== undefined) {
            var xaxis = detailPlot.getAxes().xaxis;
            xaxis.options.min = currentSelection.min;
            xaxis.options.max = currentSelection.max;
            detailPlot.setupGrid();
            detailPlot.draw();

            overviewPlot.getOptions().rangeselection.start = currentSelection.min;
            overviewPlot.getOptions().rangeselection.end = currentSelection.max;
            overviewPlot.setupGrid();
            overviewPlot.draw();
        }

        // PLOTHOVER: UPDATE VALUE IN LEGEND
        detailPlaceholder.bind('plothover', function (event, pos, item) {
            var updateDetailSelectionTimeout = null;
            var latestPosition = null;

            function updateDetailSelection() {
                updateDetailSelectionTimeout = null;
                var pos = latestPosition;
                var axes = detailPlot.getAxes();
                if (pos.x < axes.xaxis.min || pos.x > axes.xaxis.max ||
                    pos.y < axes.yaxis.min || pos.y > axes.yaxis.max) {
                    //tooltipContainer.hide('slow');
                    return;
                }

                var seriesIndex, dataPointInSeries, dataset = plotdata;

                // Iterate of each time series ('seriesIndex')
                var yMax;
                for (seriesIndex = 0; seriesIndex < dataset.length; ++seriesIndex) {
                    var series = dataset[seriesIndex];

                    // Find the nearest points, x-wise
                    for (dataPointInSeries = 0; series.data.length; ++dataPointInSeries) {
                        if (series.data[dataPointInSeries][0] > pos.x) {
                            break;
                        }
                    }

                    // Now interpolate
                    var y,
                        p1 = series.data[dataPointInSeries - 1],
                        p2 = series.data[dataPointInSeries];

                    if (p1 == null) {
                        y = p2[1];
                    } else if (p2 == null) {
                        y = p1[1];
                    } else {
                        y = p1[1] + (p2[1] - p1[1]) * (pos.x - p1[0]) / (p2[0] - p1[0]);
                    }

                    // Set the correct value for the current sensor
                    if ($.isNumeric(y)) {
                        var temperatureValueContainer = legendContainer.find('#temperature-value' + series.id);
                        if (temperatureValueContainer) {
                            temperatureValueContainer.text(y.toFixed(1));
                        }
                    }

                    if (y > yMax) {
                        yMax = y;
                    }
                }

                // Current time
                var m = moment(pos.x);
                m.add(-2, 'hours'); // fucking time stuff
                $('#detail-selection-header').text(m.format('YYYY-MM-DD HH:mm (dd)'));
            };

            latestPosition = pos;
            if (!updateDetailSelectionTimeout) {
                updateDetailSelectionTimeout = setTimeout(updateDetailSelection, 400);
            }
        });

        // PLOTPAN: UPDATE OVERVIEW PLOT
        detailPlaceholder.bind('plotpan', function (event, plot) {
            var currentMin = plot.getXAxes()[0].min;
            var dataMin = plot.getXAxes()[0].datamin;
            //            console.log('-------')
            //            console.log(new Date(currentMin));
            //            console.log(new Date(dataMin));
            if (currentMin <= dataMin) {
                loadAnotherFortnight(dataMin, overviewPlot.getAxes().xaxis.datamax);
                return;
            } else {
                function clamp(min, value, max) {
                    return value < min ? min : (value > max ? max : value);
                };

                function clampOverViewPlot(value) {
                    overviewMin = overviewPlot.getAxes().xaxis.min;
                    overviewMax = overviewPlot.getAxes().xaxis.max;
                    return clamp(overviewMin, value, overviewMax);
                };

                currentSelection.min = clampOverViewPlot(detailPlot.getAxes().xaxis.min);
                currentSelection.max = clampOverViewPlot(detailPlot.getAxes().xaxis.max);
                overviewPlot.setSelection(currentSelection.min, currentSelection.max);
            }
        });
    };

    updatePlot();
};

function loadAnotherFortnight(oldMin, max) {
    console.log('Reloading with oldMin value: ' + new Date(oldMin));
    console.log('Reloading with max value: ' + new Date(max));

    getByFilter(oldMin, max, function (rawdata) {
        console.log('call getByFilter is done.');
        render(rawdata);
    });
};

// Prepare data -------------------------------------------------------------------------------------------
var formatDate = function (date) {
    // requires moment.js
    return moment.utc(new Date(date)).format('ddd, YYYY MMM DD HH:mm');
};

var convertDataForFlot = function (data) {
    var flotdata = [];
    flotdata.push(mapTimeSeries(data, 'WA', 'outside', colors[0]));
    flotdata.push(mapTimeSeries(data, 'Z2', '2nd floor', colors[1]));
    flotdata.push(mapTimeSeries(data, 'Z3', '1st floor (work)', colors[2]));
    flotdata.push(mapTimeSeries(data, 'Z4', '1st floor (bathroom)', colors[3]));
    flotdata.push(mapTimeSeries(data, 'Z5', '1st floor (bedroom)', colors[4]));
    flotdata.push(mapTimeSeries(data, 'Z6', 'ground floor', colors[5]));
    return flotdata;
};

var mapTimeSeries = function (data, sensorName, label, col) {
    var series = [];
    for (var i = 0; i < data.length; i++) {
        if (data[i].sensorName === sensorName) {
            var mDate = moment(data[i].timestamp + ' +02:00', 'YYYY-MM-DD HH:mm:ss ZZ');
            mDate.add(2, 'hours'); // still don't understand why this is really necessary.
            var millis = new Date(mDate.unix()) * 1000;
            series.push([millis, data[i].degreeCelsius]);
        }
    }

    // Note: Add an 'id' property (because the label property is a descriptive string)
    return {
        data: series,
        label: label,
        color: col,
        id: sensorName
    };
};
<|endoftext|>


<commit_before>/**
 * index.js - Main library for index page/view.
 * Authors: Ian McGaunn; Dave Zimmelman
 * Modified: 09 Mar 15
 */
(function (window, $) {
    'use strict';

    /**
     * Populate results table with search data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function searchResults(results) {
        console.log(results);
        var podcast, row, count;
        // Update table title with result count.
        count = (results.length > 0) ? "" + results.length : "No";
        $('#right-col > h3').html(count + " Results");
        // Remove existing results.
        $('#results-table tbody > tr').remove();
        // Add entry for each podcast.
        for (podcast in results) {
            row = $('
');
            row.append($('').html(''));
            row.append($('').text(results[podcast].title));
            row.append($('').text(results[podcast].genre));
            $('#results-table').append(row);
        }
        // Temporary system for getting to feed pages
        $('.feed-row').click(function () {
            var id = $(this).data('id');
            window.location = '/podcast/' + id;
        });
    }

    /**
     * Populate results table with browse data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function browseResults(data) {
        var results = data.feed.entry, podcast, row, count;
        // Update table title with result count.
        count = (results.length > 0) ? "" + results.length : "No";
        $('#right-col > h3').html(count + " Results");
        // Remove existing results.
        $('#results-table tbody > tr').remove();
        // Add entry for each podcast.
        for (podcast in results) {
            row = $('
');
            row.append($('').html(''));
            row.append($('').text(results[podcast]['im:name'].label));
            row.append($('').text(results[podcast].category.attributes.label));
            $('#results-table').append(row);
        }
        // Temporary system for getting to feed pages
        $('.feed-row').click(function () {
            var id = $(this).data('id');
            window.location = '/podcast/' + id;
        });
    }

    /* When document is finished loading, execute following code: */
    $().ready(function () {
        // Check for search or browse data passed from server.
        //  This is for cached data only.
        if (typeof(presearch) !== "undefined") {
            searchResults(presearch);
        }
        else if (typeof(prebrowse) !== "undefined") {
            browseResults(prebrowse);
        }
        // Search box change
        var quicksearch = function () {
            var s = $('#podcast-search-input').text().trim();
            console.log('qs: ' + s);
            if (s != "") {
                $.get('/api/quicksearch/?term=' + s, function (data) {
                    searchResults(data);
                });
            }
        };
        var searchBoxTH = null;
        $('#podcast-search-input').change(function () {
            if (!searchBoxTH) {
                quicksearch();
                searchBoxTH = setInterval(quicksearch, 1000);
            }
        });
        // Search submission
        $('#podcast-search').submit(function () {
            clearInterval(searchBoxTH);
            searchBoxTH = null;
            var searchTerm = $('#podcast-search-input').val();
            // Get search data from API.
            $.get('/api/search/?term=' + searchTerm, function (data) {
                // Parse results and add to table.
                searchResults(data);
                // Push new URL state.
                window.history.pushState({}, document.title, '/search/' + searchTerm);
            });
        });

        // Browse submission
        $('#podcast-browse').submit(function () {
            var genre = $('#podcast-browse-cat').val();
            // Get browse data from API.
            $.get('/api/browse/?limit=10&genre=' + genre, function (data) {
                // Parse results and add to table.
                browseResults(JSON.parse(data));
                // Push new URL state.
                window.history.pushState({}, document.title, '/browse/' + genre);
            });
        });

        // Reload page when user goes forward or back to process cached search or browse results.
        window.onpopstate = function(event) {
            window.location = document.location;
        };

    });
}(window, jQuery));
<commit_msg>[Fix] Wrong jquery method<commit_after>/**
 * index.js - Main library for index page/view.
 * Authors: Ian McGaunn; Dave Zimmelman
 * Modified: 09 Mar 15
 */
(function (window, $) {
    'use strict';

    /**
     * Populate results table with search data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function searchResults(results) {
        console.log(results);
        var podcast, row, count;
        // Update table title with result count.
        count = (results.length > 0) ? "" + results.length : "No";
        $('#right-col > h3').html(count + " Results");
        // Remove existing results.
        $('#results-table tbody > tr').remove();
        // Add entry for each podcast.
        for (podcast in results) {
            row = $('
');
            row.append($('').html(''));
            row.append($('').text(results[podcast].title));
            row.append($('').text(results[podcast].genre));
            $('#results-table').append(row);
        }
        // Temporary system for getting to feed pages
        $('.feed-row').click(function () {
            var id = $(this).data('id');
            window.location = '/podcast/' + id;
        });
    }

    /**
     * Populate results table with browse data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function browseResults(data) {
        var results = data.feed.entry, podcast, row, count;
        // Update table title with result count.
        count = (results.length > 0) ? "" + results.length : "No";
        $('#right-col > h3').html(count + " Results");
        // Remove existing results.
        $('#results-table tbody > tr').remove();
        // Add entry for each podcast.
        for (podcast in results) {
            row = $('
');
            row.append($('').html(''));
            row.append($('').text(results[podcast]['im:name'].label));
            row.append($('').text(results[podcast].category.attributes.label));
            $('#results-table').append(row);
        }
        // Temporary system for getting to feed pages
        $('.feed-row').click(function () {
            var id = $(this).data('id');
            window.location = '/podcast/' + id;
        });
    }

    /* When document is finished loading, execute following code: */
    $().ready(function () {
        // Check for search or browse data passed from server.
        //  This is for cached data only.
        if (typeof(presearch) !== "undefined") {
            searchResults(presearch);
        }
        else if (typeof(prebrowse) !== "undefined") {
            browseResults(prebrowse);
        }
        // Search box change
        var quicksearch = function () {
            var s = $('#podcast-search-input').val().trim();
            console.log('qs: ' + s);
            if (s != "") {
                $.get('/api/quicksearch/?term=' + s, function (data) {
                    searchResults(data);
                });
            }
        };
        var searchBoxTH = null;
        $('#podcast-search-input').change(function () {
            if (!searchBoxTH) {
                quicksearch();
                searchBoxTH = setInterval(quicksearch, 1000);
            }
        });
        // Search submission
        $('#podcast-search').submit(function () {
            clearInterval(searchBoxTH);
            searchBoxTH = null;
            var searchTerm = $('#podcast-search-input').val();
            // Get search data from API.
            $.get('/api/search/?term=' + searchTerm, function (data) {
                // Parse results and add to table.
                searchResults(data);
                // Push new URL state.
                window.history.pushState({}, document.title, '/search/' + searchTerm);
            });
        });

        // Browse submission
        $('#podcast-browse').submit(function () {
            var genre = $('#podcast-browse-cat').val();
            // Get browse data from API.
            $.get('/api/browse/?limit=10&genre=' + genre, function (data) {
                // Parse results and add to table.
                browseResults(JSON.parse(data));
                // Push new URL state.
                window.history.pushState({}, document.title, '/browse/' + genre);
            });
        });

        // Reload page when user goes forward or back to process cached search or browse results.
        window.onpopstate = function(event) {
            window.location = document.location;
        };

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


<commit_before>
var events = require('events');

function Topology(spouts, bolts, outputs)
{
    this.spouts = spouts;
    this.bolts = bolts;
    this.outputs = outputs;
}

Topology.prototype.start = function()
{
    for (var n in this.spouts) {
        var spout = this.spouts[n];
        spout.start(this.outputs[n]);
    }
}

Topology.prototype.stop = function()
{
}

function OutputCollector()
{
    var stream = new events.EventEmitter();

    this.emit = function(msg) {
        stream.emit('data', msg);
    }

    this.addListener = function(receiver, output) {
        stream.on('data', function(msg) {
            receiver.process(msg, output);
        });
    }
}

function InputDeclarer()
{
    var groupings = [];

    this.shuffleGrouping = function(name) {
        groupings.push(name);
        return this;
    }

    this.getGroupings = function() {
        return groupings;
    }
}

function TopologyBuilder()
{
    var spouts = {};
    var bolts = {};
    var inputDeclarers = {};

    this.setSpout = function(name, spout) {
        spouts[name] = spout;
    }

    this.getSpout = function(name) {
        return spouts[name];
    }

    this.setBolt = function(name, bolt) {
        bolts[name] = bolt;
        var declarer = new InputDeclarer(bolt);
        inputDeclarers[name] = declarer;
        return declarer;
    }

    this.getBolt = function(name) {
        return bolts[name];
    }

    this.createTopology = function() {
        var outputs = {};

        for (var name in spouts) {
            var collector = new OutputCollector();
            outputs[name] = collector;
        }

        for (var name in bolts) {
            var collector = new OutputCollector();
            outputs[name] = collector;
        }

        for (var name in inputDeclarers)
        {
            var inputDeclarer = inputDeclarers[name];
            var bolt = bolts[name];
            var output = outputs[name];
            inputDeclarer.getGroupings().forEach(function(groupname) {
                outputs[groupname].addListener(bolt, output);
            });
        }

        return new Topology(spouts, bolts, outputs);
    }
}

exports.createTopologyBuilder = function() { return new TopologyBuilder(); }

<commit_msg>Internal refactor: InputCollector<commit_after>
var events = require('events');

function Topology(spouts, bolts, outputs)
{
    this.spouts = spouts;
    this.bolts = bolts;
    this.outputs = outputs;
}

Topology.prototype.start = function()
{
    for (var n in this.spouts) {
        var spout = this.spouts[n];
        spout.start(this.outputs[n]);
    }
}

Topology.prototype.stop = function()
{
}

function OutputCollector()
{
    var stream = new events.EventEmitter();

    this.emit = function(msg) {
        stream.emit('data', msg);
    }

    this.addListener = function(listener) {
        stream.on('data', function(msg) {
            listener.process(msg);
        });
    }
}

function InputCollector(task, output)
{
    this.process = function (msg) {
        task.process(msg, output);
    }
}

function InputDeclarer()
{
    var groupings = [];

    this.shuffleGrouping = function(name) {
        groupings.push(name);
        return this;
    }

    this.getGroupings = function() {
        return groupings;
    }
}

function TopologyBuilder()
{
    var spouts = {};
    var bolts = {};
    var inputDeclarers = {};

    this.setSpout = function(name, spout) {
        spouts[name] = spout;
    }

    this.getSpout = function(name) {
        return spouts[name];
    }

    this.setBolt = function(name, bolt) {
        bolts[name] = bolt;
        var declarer = new InputDeclarer(bolt);
        inputDeclarers[name] = declarer;
        return declarer;
    }

    this.getBolt = function(name) {
        return bolts[name];
    }

    this.createTopology = function() {
        var outputs = {};

        for (var name in spouts) {
            var collector = new OutputCollector();
            outputs[name] = collector;
        }

        for (var name in bolts) {
            var collector = new OutputCollector();
            outputs[name] = collector;
        }

        for (var name in inputDeclarers)
        {
            var inputDeclarer = inputDeclarers[name];
            var bolt = bolts[name];
            var output = outputs[name];
            var inputCollector = new InputCollector(bolt, output);
            inputDeclarer.getGroupings().forEach(function(groupname) {
                outputs[groupname].addListener(inputCollector);
            });
        }

        return new Topology(spouts, bolts, outputs);
    }
}

exports.createTopologyBuilder = function() { return new TopologyBuilder(); }

<|endoftext|>


<commit_before>/**
 * index.js - Main library for index page/view.
 * Authors: Ian McGaunn; Dave Zimmelman
 * Modified: 09 Mar 15
 */
(function (window, $) {
    'use strict';

    window.load_splash_view = function () {
        $.get('/api/view/splash', function (data) {

            $('#left-col').html(data);

            $.get('/api/castcat/0', function (data) {
                insertPodcasts(data.podcasts, '#pc-0 > .panel-body', false, false);
            });

            $('#left-col .genre-panel').each(function () {
                var i, el = $(this).find('.panel-body'), gid = $(this).data('genreid');
                $.get('/api/castcat/' + gid, function (data) {
                    el.html('');
                    if (data.favorites) {
                        insertPodcasts(data.favorites, el, false, true);
                    }
                    insertPodcasts(data.podcasts, el, false, false);
                });
            });

            $('#podcast-search-input').on('change keyup paste', function (e) {
                if (e.type == "keyup" && e.which == 13) {
                    // Enter key pressed
                    submitSearch();
                }
                else if ($(this).val().trim() !== "" &&
                         $(this).val().trim() !== lastTickSearch &&
                         searchBoxTH === null) {
                    quicksearch();
                    searchBoxTH = setInterval(quicksearch, 250);
                }
                else if ($(this).val().trim() === "") {
                    clearInterval(searchBoxTH);
                    searchBoxTH = null;
                    searchResults({});
                }
            });
            // Search button press
            $('#podcast-search-button').click(function () {
                submitSearch();
            });
        });
    };

    window.load_podcast_view = function (id) {
        $.get('/podcast/'+ id, function (data) {
            $('#left-col').html(data);

            // Reformat URL to reflect appropriate title.
            window.history.replaceState({}, document.title, '/podcast/' + window.safetitle);
        });
    };

    function insertPodcasts(pcasts, selector, append, fav) {
        var i;
        if (!append) $(selector).html('');
        for (i in pcasts) {
            var classes = (fav) ? "castnail favorite" : "castnail";
            $(selector).append('

');
        }
    }

    /**
     * Populate results table with search data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function searchResults(results) {
        var podcast, row, count;
        // Update table title with result count.
        if (results.length > 0) {
            $('#result-counter').html(results.length + " Results");
            $('#search-results').css('height', '120px');
            $('#search-results').css('padding', '10px');
        } else {
            $('#result-counter').html("No Results");
            $('#search-results').css('height', '0px');
            $('#search-results').css('padding', '0px');
        }
        insertPodcasts(results, '#search-results');
    }

    /* When document is finished loading, execute following code: */
    $().ready(function () {

        var searchBoxTH = null;
        var lastTickSearch = "";
        // Submit search query
        var submitSearch = function () {
            clearInterval(searchBoxTH);
            searchBoxTH = null;
            var searchTerm = $('#podcast-search-input').val();
            // Get search data from API.
            $.get('/api/search/?term=' + searchTerm, function (data) {
                // Parse results and add to table.
                searchResults(data);
                // Push new URL state.
                //window.history.pushState({}, document.title, '/search/' + searchTerm);
            });
        };
        // Search box change
        var quicksearch = function () {
            var s = $('#podcast-search-input').val().trim();
            if (s == lastTickSearch) {
                clearInterval(searchBoxTH);
                searchBoxTH = null;
                return;
            }
            if (s != "") {
                lastTickSearch = s;
                $.get('/api/quicksearch/?term=' + s, function (data) {
                    searchResults(data);
                });
            }
        };
        if (preload_cast !== undefined) {
            window.load_podcast_view(preload_cast);
        }
        else {
            window.load_splash_view();
        }

    });
}(window, jQuery));
<commit_msg>[Fix] bad template loop<commit_after>/**
 * index.js - Main library for index page/view.
 * Authors: Ian McGaunn; Dave Zimmelman
 * Modified: 09 Mar 15
 */
(function (window, $) {
    'use strict';

    window.load_splash_view = function () {
        $.get('/api/view/splash', function (data) {

            $('#left-col').html(data);

            $.get('/api/castcat/0', function (data) {
                insertPodcasts(data.podcasts, '#pc-0 > .panel-body', false, false);
            });

            $('#left-col .genre-panel').each(function () {
                var i, el = $(this).find('.panel-body'), gid = $(this).data('genreid');
                $.get('/api/castcat/' + gid, function (data) {
                    el.html('');
                    if (data.favorites) {
                        insertPodcasts(data.favorites, el, false, true);
                    }
                    insertPodcasts(data.podcasts, el, false, false);
                });
            });

            $('#podcast-search-input').on('change keyup paste', function (e) {
                if (e.type == "keyup" && e.which == 13) {
                    // Enter key pressed
                    submitSearch();
                }
                else if ($(this).val().trim() !== "" &&
                         $(this).val().trim() !== lastTickSearch &&
                         searchBoxTH === null) {
                    quicksearch();
                    searchBoxTH = setInterval(quicksearch, 250);
                }
                else if ($(this).val().trim() === "") {
                    clearInterval(searchBoxTH);
                    searchBoxTH = null;
                    searchResults({});
                }
            });
            // Search button press
            $('#podcast-search-button').click(function () {
                submitSearch();
            });
        });
    };

    window.load_podcast_view = function (id) {
        $.get('/api/view/podcast/'+ id, function (data) {
            $('#left-col').html(data);

            // Reformat URL to reflect appropriate title.
            window.history.replaceState({}, document.title, '/podcast/' + window.safetitle);
        });
    };

    function insertPodcasts(pcasts, selector, append, fav) {
        var i;
        if (!append) $(selector).html('');
        for (i in pcasts) {
            var classes = (fav) ? "castnail favorite" : "castnail";
            $(selector).append('

');
        }
    }

    /**
     * Populate results table with search data.
     * @param {Object} data - The JSON object returned from iTunes query.
     */
    function searchResults(results) {
        var podcast, row, count;
        // Update table title with result count.
        if (results.length > 0) {
            $('#result-counter').html(results.length + " Results");
            $('#search-results').css('height', '120px');
            $('#search-results').css('padding', '10px');
        } else {
            $('#result-counter').html("No Results");
            $('#search-results').css('height', '0px');
            $('#search-results').css('padding', '0px');
        }
        insertPodcasts(results, '#search-results');
    }

    /* When document is finished loading, execute following code: */
    $().ready(function () {

        var searchBoxTH = null;
        var lastTickSearch = "";
        // Submit search query
        var submitSearch = function () {
            clearInterval(searchBoxTH);
            searchBoxTH = null;
            var searchTerm = $('#podcast-search-input').val();
            // Get search data from API.
            $.get('/api/search/?term=' + searchTerm, function (data) {
                // Parse results and add to table.
                searchResults(data);
                // Push new URL state.
                //window.history.pushState({}, document.title, '/search/' + searchTerm);
            });
        };
        // Search box change
        var quicksearch = function () {
            var s = $('#podcast-search-input').val().trim();
            if (s == lastTickSearch) {
                clearInterval(searchBoxTH);
                searchBoxTH = null;
                return;
            }
            if (s != "") {
                lastTickSearch = s;
                $.get('/api/quicksearch/?term=' + s, function (data) {
                    searchResults(data);
                });
            }
        };
        if (preload_cast !== undefined) {
            window.load_podcast_view(preload_cast);
        }
        else {
            window.load_splash_view();
        }

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


<commit_before>$(document).ready(function () {

	//variables declaration
	var tableData=[], tableDataReverse=[];

	$("#chart").shieldChart({
                theme: "light",
                exportOptions: {
                    image: false,
                    print: false
                },
                primaryHeader: {
                    text: "Pressure, termperature and vibration statistics over six interval"
                },
                zoomMode: "xy",
                seriesSettings: {
                    bar: {
                        barOffset: 0
                    }
                },
                axisX: {
                    categoricalValues: ["1st", "2nd", "3rd", "4th", "5th", "6th"]
                },
                axisY: {
                    title: {
                        text: "Value statistics"
                    }
                },
                dataSeries: [{
                    seriesType: "bar",
                    collectionAlias: "Pressure",
                    data: [obj.pressure[0][0], obj.pressure[0][1], obj.pressure[0][2], obj.pressure[0][3], obj.pressure[0][4], obj.pressure[0][5]]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Temperature",
                    data: [72, 90, 84, 78, 67, 83]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Vibration",
                    data: [152, 234, 123, 348]
                }]
            });

	$("#grid").shieldGrid({
            dataSource: {
				data: tableDataReverse
			},
			rowHover: false,
            scrolling: {
                virtual: true
            },
            sorting: true,
            columnReorder: true,
            columns: [
                { field: "key", title: "Key" },
                { field: "value", title: "Value" }
            ]
        });

	//updating table (live)
    function refreshGird() {
        var grid = $("#grid").swidget(),
            initialOptions = grid.initialOptions;
        initialOptions.dataSource = {
            data: tableDataReverse
        };
        grid.refresh(initialOptions);
    }

	//styling table (assigning red/green colour)
	function gridDataBound(e) {
		var data = e.target.dataSource.view;
		var rows = e.target.contentTable.find(">tbody>tr");
		for (var i = 0; i < data.length; i++) {
            var item = data[i];
            if (item.message == thresholdMsg) {
                $(rows[i].cells[3]).addClass("red");
            }
            if (item.message == msg) {
                $(rows[i].cells[3]).addClass("green");
            }
        }
    }

	if(tableData.length == 5){
						for(var i=0; i<(tableData.length)-1; i++){
							tableData[i]= tableData[i+1];
						}
						tableData[4]={
							key: "internalTemperature",
							value: "128"
						};
					}
					else{
						tableData.push({
							key: "internalTemperature",
							value: "128"
						});
					}

		tableDataReverse = tableData.slice(0);
		tableDataReverse.reverse();

	//websocket connection
	var ws = new WebSocket('wss://' + location.host);

	ws.onopen = function () {
		console.log('Successfully connect WebSocket');
	}

	//websocket receiving messages
	ws.onmessage = function (message) {
		console.log('Receive message via websocket in client side: ' + message.data);
		try {
			var obj = JSON.parse(message.data);

						tableData.push({
							key: "Time of reading",
							value: obj.timeOfReading
						});
						tableData.push({
							key: "Internal temperature",
							value: obj.internalTemperature
						});
						tableData.push({
							key: "Daily flow",
							value: obj.dailyFlow
						});
						tableData.push({
							key: "Daily reverse flow",
							value: obj.dailyReverseFlow
						});
						tableData.push({
							key: "Peak flow rate",
							value: obj.peakFlowRate
						});
						tableData.push({
							key: "Peak flow rate time",
							value: obj.peakFlowRateTime
						});
						tableData.push({
							key: "Event time",
							value: obj.eventTime
						});

			tableDataReverse = tableData.slice(0);
			tableDataReverse.reverse();

			refreshGird();
			}
		catch (err) {
		  console.error(err);
		}
	}
});<commit_msg>trying grid code6<commit_after>$(document).ready(function () {

	//variables declaration
	var tableData=[], tableDataReverse=[];

	$("#chart").shieldChart({
                theme: "light",
                exportOptions: {
                    image: false,
                    print: false
                },
                primaryHeader: {
                    text: "Pressure, termperature and vibration statistics over six interval"
                },
                zoomMode: "xy",
                seriesSettings: {
                    bar: {
                        barOffset: 0
                    }
                },
                axisX: {
                    categoricalValues: ["1st", "2nd", "3rd", "4th", "5th", "6th"]
                },
                axisY: {
                    title: {
                        text: "Value statistics"
                    }
                },
                dataSeries: [{
                    seriesType: "bar",
                    collectionAlias: "Pressure",
                    data: [obj.pressure[0].Value, obj.pressure[1].Value, obj.pressure[2].Value, obj.pressure[3].Value, obj.pressure[4].Value, obj.pressure[5].Value]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Temperature",
                    data: [72, 90, 84, 78, 67, 83]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Vibration",
                    data: [152, 234, 123, 348]
                }]
            });

	$("#grid").shieldGrid({
            dataSource: {
				data: tableDataReverse
			},
			rowHover: false,
            scrolling: {
                virtual: true
            },
            sorting: true,
            columnReorder: true,
            columns: [
                { field: "key", title: "Key" },
                { field: "value", title: "Value" }
            ]
        });

	//updating table (live)
    function refreshGird() {
        var grid = $("#grid").swidget(),
            initialOptions = grid.initialOptions;
        initialOptions.dataSource = {
            data: tableDataReverse
        };
        grid.refresh(initialOptions);
    }

	//styling table (assigning red/green colour)
	function gridDataBound(e) {
		var data = e.target.dataSource.view;
		var rows = e.target.contentTable.find(">tbody>tr");
		for (var i = 0; i < data.length; i++) {
            var item = data[i];
            if (item.message == thresholdMsg) {
                $(rows[i].cells[3]).addClass("red");
            }
            if (item.message == msg) {
                $(rows[i].cells[3]).addClass("green");
            }
        }
    }

	if(tableData.length == 5){
						for(var i=0; i<(tableData.length)-1; i++){
							tableData[i]= tableData[i+1];
						}
						tableData[4]={
							key: "internalTemperature",
							value: "128"
						};
					}
					else{
						tableData.push({
							key: "internalTemperature",
							value: "128"
						});
					}

		tableDataReverse = tableData.slice(0);
		tableDataReverse.reverse();

	//websocket connection
	var ws = new WebSocket('wss://' + location.host);

	ws.onopen = function () {
		console.log('Successfully connect WebSocket');
	}

	//websocket receiving messages
	ws.onmessage = function (message) {
		console.log('Receive message via websocket in client side: ' + message.data);
		try {
			var obj = JSON.parse(message.data);

						tableData.push({
							key: "Time of reading",
							value: obj.timeOfReading
						});
						tableData.push({
							key: "Internal temperature",
							value: obj.internalTemperature
						});
						tableData.push({
							key: "Daily flow",
							value: obj.dailyFlow
						});
						tableData.push({
							key: "Daily reverse flow",
							value: obj.dailyReverseFlow
						});
						tableData.push({
							key: "Peak flow rate",
							value: obj.peakFlowRate
						});
						tableData.push({
							key: "Peak flow rate time",
							value: obj.peakFlowRateTime
						});
						tableData.push({
							key: "Event time",
							value: obj.eventTime
						});

			tableDataReverse = tableData.slice(0);
			tableDataReverse.reverse();

			refreshGird();
			}
		catch (err) {
		  console.error(err);
		}
	}
});<|endoftext|>


<commit_before>$(document).ready(function () {

	//variables declaration
	var tableData=[], tableDataReverse=[];

	//Display empty chart initially
	$("#chart").shieldChart({
                theme: "light",
                exportOptions: {
                    image: false,
                    print: false
                },
                primaryHeader: {
                    text: "Pressure, termperature and vibration statistics over six interval"
                },
                zoomMode: "xy",
                seriesSettings: {
                    bar: {
                        barOffset: 0
                    }
                },
                axisX: {
                    categoricalValues: ["1st", "2nd", "3rd", "4th", "5th", "6th"]
                },
                axisY: {
                    title: {
                        text: "Value statistics"
                    }
                },
                dataSeries: [{
                    seriesType: "bar",
                    collectionAlias: "Pressure",
                    data: [0, 0, 0, 0, 0, 0]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Temperature",
                    data: [0, 0, 0, 0, 0, 0]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Vibration",
                    data: [0, 0, 0, 0]
                }]
            });

	//styling table (assigning red/green colour)
	function gridDataBound(e) {
		var data = e.target.dataSource.view;
		var rows = e.target.contentTable.find(">tbody>tr");
		for (var i = 0; i < data.length; i++) {
            var item = data[i];
            if (item.key) {
                $(rows[i].cells[3]).addClass("green");
            }else
                $(rows[i].cells[3]).addClass("red");

        }
    }

	//websocket connection
	var ws = new WebSocket('wss://' + location.host);

	ws.onopen = function () {
		console.log('Successfully connect WebSocket');
	}

	//websocket receiving messages
	ws.onmessage = function (message) {
		console.log('Receive message via websocket in client side: ' + message.data);
		try {
			var obj = JSON.parse(message.data);

			$("#chart").shieldChart({
                theme: "light",
                exportOptions: {
                    image: false,
                    print: false
                },
                primaryHeader: {
                    text: "Pressure, termperature and vibration statistics over six interval"
                },
                zoomMode: "xy",
                seriesSettings: {
                    bar: {
                        barOffset: 0
                    }
                },
                axisX: {
                    categoricalValues: ["1st", "2nd", "3rd", "4th", "5th", "6th"]
                },
                axisY: {
                    title: {
                        text: "Value statistics"
                    }
                },
                dataSeries: [{
                    seriesType: "bar",
                    collectionAlias: "Pressure",
                    data: [parseInt(obj.pressure[0].Value), parseInt(obj.pressure[1].Value), parseInt(obj.pressure[2].Value), parseInt(obj.pressure[3].Value), parseInt(obj.pressure[4].Value), parseInt(obj.pressure[5].Value)]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Temperature",
                    data: [parseInt(obj.temp[0].Value), parseInt(obj.temp[1].Value), parseInt(obj.temp[2].Value), parseInt(obj.temp[3].Value), parseInt(obj.temp[4].Value), parseInt(obj.temp[5].Value)]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Vibration",
                    data: [parseInt(obj.vibration[0].Value), parseInt(obj.vibration[1].Value), parseInt(obj.vibration[2].Value), parseInt(obj.vibration[3].Value)]
                }]
            });

						tableData.push({
							key: "Time of reading",
							value: obj.timeOfReading
						});
						tableData.push({
							key: "Internal temperature",
							value: obj.internalTemperature
						});
						tableData.push({
							key: "Daily flow",
							value: obj.dailyFlow
						});
						tableData.push({
							key: "Daily reverse flow",
							value: obj.dailyReverseFlow
						});
						tableData.push({
							key: "Peak flow rate",
							value: obj.peakFlowRate
						});
						tableData.push({
							key: "Peak flow rate time",
							value: obj.peakFlowRateTime
						});
						tableData.push({
							key: "Event time",
							value: obj.eventTime
						});

			tableDataReverse = tableData.slice(0);

			$("#grid").shieldGrid({
            dataSource: {
				data: tableDataReverse
			},
			events: {
                dataBound: gridDataBound
            },
			rowHover: false,
            scrolling: {
                virtual: true
            },
            sorting: true,
            columnReorder: true,
            columns: [
                { field: "key", title: "Key" },
                { field: "value", title: "Value" }
            ]
			});

			}
		catch (err) {
		  console.error(err);
		}
	}
});<commit_msg>trying grid code24<commit_after>$(document).ready(function () {

	//variables declaration
	var tableData=[], tableDataReverse=[];

	//Display empty chart initially
	$("#chart").shieldChart({
                theme: "light",
                exportOptions: {
                    image: false,
                    print: false
                },
                primaryHeader: {
                    text: "Pressure, termperature and vibration statistics over six interval"
                },
                zoomMode: "xy",
                seriesSettings: {
                    bar: {
                        barOffset: 0
                    }
                },
                axisX: {
                    categoricalValues: ["1st", "2nd", "3rd", "4th", "5th", "6th"]
                },
                axisY: {
                    title: {
                        text: "Value statistics"
                    }
                },
                dataSeries: [{
                    seriesType: "bar",
                    collectionAlias: "Pressure",
                    data: [0, 0, 0, 0, 0, 0]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Temperature",
                    data: [0, 0, 0, 0, 0, 0]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Vibration",
                    data: [0, 0, 0, 0]
                }]
            });

	$("#grid").shieldGrid({
            dataSource: {
				data: tableDataReverse
			},
			events: {
                dataBound: gridDataBound
            },
			rowHover: false,
            scrolling: {
                virtual: true
            },
            sorting: true,
            columnReorder: true,
            columns: [
                { field: "key", title: "Firstkey" },
                { field: "value", title: "FirstValue" }
            ]
        });

	//styling table (assigning red/green colour)
	function gridDataBound(e) {
		var data = e.target.dataSource.view;
		var rows = e.target.contentTable.find(">tbody>tr");
		for (var i = 0; i < data.length; i++) {
            var item = data[i];
            if (item.key) {
                $(rows[i].cells[3]).addClass("green");
            }else
                $(rows[i].cells[3]).addClass("red");

        }
    }

	//websocket connection
	var ws = new WebSocket('wss://' + location.host);

	ws.onopen = function () {
		console.log('Successfully connect WebSocket');
	}

	//websocket receiving messages
	ws.onmessage = function (message) {
		console.log('Receive message via websocket in client side: ' + message.data);
		try {
			var obj = JSON.parse(message.data);

			$("#chart").shieldChart({
                theme: "light",
                exportOptions: {
                    image: false,
                    print: false
                },
                primaryHeader: {
                    text: "Pressure, termperature and vibration statistics over six interval"
                },
                zoomMode: "xy",
                seriesSettings: {
                    bar: {
                        barOffset: 0
                    }
                },
                axisX: {
                    categoricalValues: ["1st", "2nd", "3rd", "4th", "5th", "6th"]
                },
                axisY: {
                    title: {
                        text: "Value statistics"
                    }
                },
                dataSeries: [{
                    seriesType: "bar",
                    collectionAlias: "Pressure",
                    data: [parseInt(obj.pressure[0].Value), parseInt(obj.pressure[1].Value), parseInt(obj.pressure[2].Value), parseInt(obj.pressure[3].Value), parseInt(obj.pressure[4].Value), parseInt(obj.pressure[5].Value)]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Temperature",
                    data: [parseInt(obj.temp[0].Value), parseInt(obj.temp[1].Value), parseInt(obj.temp[2].Value), parseInt(obj.temp[3].Value), parseInt(obj.temp[4].Value), parseInt(obj.temp[5].Value)]
                }, {
                    seriesType: "bar",
                    collectionAlias: "Vibration",
                    data: [parseInt(obj.vibration[0].Value), parseInt(obj.vibration[1].Value), parseInt(obj.vibration[2].Value), parseInt(obj.vibration[3].Value)]
                }]
            });

						tableData.push({
							key: "Time of reading",
							value: obj.timeOfReading
						});
						tableData.push({
							key: "Internal temperature",
							value: obj.internalTemperature
						});
						tableData.push({
							key: "Daily flow",
							value: obj.dailyFlow
						});
						tableData.push({
							key: "Daily reverse flow",
							value: obj.dailyReverseFlow
						});
						tableData.push({
							key: "Peak flow rate",
							value: obj.peakFlowRate
						});
						tableData.push({
							key: "Peak flow rate time",
							value: obj.peakFlowRateTime
						});
						tableData.push({
							key: "Event time",
							value: obj.eventTime
						});

			tableDataReverse = tableData.slice(0);

			$("#grid").shieldGrid({
            dataSource: {
				data: tableDataReverse
			},
			events: {
                dataBound: gridDataBound
            },
			rowHover: false,
            scrolling: {
                virtual: true
            },
            sorting: true,
            columnReorder: true,
            columns: [
                { field: "key", title: "Key" },
                { field: "value", title: "Value" }
            ]
			});

			}
		catch (err) {
		  console.error(err);
		}
	}
});<|endoftext|>