├── README.md ├── mysql ├── conf │ └── nginx.conf ├── html │ └── mysql.html ├── mysql.lua ├── readme.md └── sql │ └── tb_user.sql ├── upload ├── 2016 │ └── readme.md ├── conf │ └── nginx.conf ├── html │ ├── upload.html │ └── webuploader │ │ └── readme.md ├── logs │ └── readme.md └── upload.lua └── websocket ├── conf └── nginx.conf ├── lib └── resty │ └── shell.lua ├── public ├── index.html └── static │ └── js │ ├── bootstrap │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap-theme.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ ├── highcharts │ ├── adapters │ │ ├── standalone-framework.js │ │ └── standalone-framework.src.js │ ├── highcharts-3d.js │ ├── highcharts-3d.src.js │ ├── highcharts-more.js │ ├── highcharts-more.src.js │ ├── highcharts.js │ ├── highcharts.src.js │ ├── modules │ │ ├── boost.js │ │ ├── boost.src.js │ │ ├── broken-axis.js │ │ ├── broken-axis.src.js │ │ ├── canvas-tools.js │ │ ├── canvas-tools.src.js │ │ ├── data.js │ │ ├── data.src.js │ │ ├── drilldown.js │ │ ├── drilldown.src.js │ │ ├── exporting.js │ │ ├── exporting.src.js │ │ ├── funnel.js │ │ ├── funnel.src.js │ │ ├── heatmap.js │ │ ├── heatmap.src.js │ │ ├── no-data-to-display.js │ │ ├── no-data-to-display.src.js │ │ ├── offline-exporting.js │ │ ├── offline-exporting.src.js │ │ ├── solid-gauge.js │ │ ├── solid-gauge.src.js │ │ ├── treemap.js │ │ └── treemap.src.js │ └── themes │ │ ├── dark-blue.js │ │ ├── dark-green.js │ │ ├── dark-unica.js │ │ ├── gray.js │ │ ├── grid-light.js │ │ ├── grid.js │ │ ├── sand-signika.js │ │ └── skies.js │ ├── jquery.js │ ├── reconnect.js │ └── stats.js ├── readme.md ├── server.lua └── vmstats.png /README.md: -------------------------------------------------------------------------------- 1 | # openresty-practices openresty基础知识练习 2 | openresty技能实践代码 3 | 4 | - [lua-resty-upload模块实现图片上传](https://github.com/shixinke/openresty-practices/tree/master/upload "openresty实现图片上传") 5 | - [lua-resty-mysql模块实现mysql基本操作](https://github.com/shixinke/openresty-practices/tree/master/mysql "openresty实现mysql基本操作") 6 | - [lua-resty-websocket模块实现系统监控](https://github.com/shixinke/openresty-practices/tree/master/websocket "基于lua-resty-websocket实现系统监控") 7 | 8 | 9 | # 注意: 10 | 以上代码纯属基础知识练习,未经过正式环境验证 11 | -------------------------------------------------------------------------------- /mysql/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | lua_package_path '/data/www/openrestyproject/mysql/lib/?.lua;/data/www/openrestyproject/mysql/?.lua;;'; 2 | lua_code_cache off; 3 | server { 4 | server_name localhost; 5 | listen 8000; 6 | charset utf-8; 7 | set $LESSON_ROOT /data/www/openrestyproject/mysql; 8 | error_log /data/www/openrestyproject/mysql/logs/error.log; 9 | access_log /data/www/openrestyproject/mysql/logs/access.log main; 10 | location / { 11 | root /data/www/openrestyproject/mysql/; 12 | index index.html index.htm; 13 | } 14 | 15 | location /mysql { 16 | default_type text/html; 17 | content_by_lua_file $LESSON_ROOT/mysql.lua; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /mysql/html/mysql.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mysql练习 6 | 17 | 18 | 19 |
20 |

项目

21 | 22 |
23 | 名称: 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
ID名称操作
36 |
37 |
38 |
39 | ID: 40 | 名称: 41 | 42 |
43 | 44 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /mysql/mysql.lua: -------------------------------------------------------------------------------- 1 | local args = ngx.req.get_uri_args() 2 | local action = args['action'] 3 | 4 | local mysql = require 'resty.mysql' 5 | local cjson = require 'cjson' 6 | local db_config = { 7 | host = '192.168.137.200', 8 | port = 3306, 9 | database = 'test', 10 | user = 'root', 11 | password = '123456', 12 | table = 'tb_user' 13 | } 14 | 15 | local db, err = mysql:new() 16 | if not db then 17 | ngx.say(cjson.encode({code=500, message='未安装mysql客户端'})) 18 | return 19 | end 20 | local ok, err, errno, sqlstate = db:connect({ 21 | host = db_config.host, 22 | port = db_config.port, 23 | database = db_config.database, 24 | user = db_config.user, 25 | password = db_config.password}) 26 | if not ok then 27 | ngx.say(cjson.encode({code=500, message='mysql连接不上'..err})) 28 | return 29 | end 30 | 31 | -- 列表 32 | function lists() 33 | local data = {} 34 | ngx.req.read_body() 35 | local posts = ngx.req.get_post_args() 36 | local page, pagesize, offset = 0, 15, 0 37 | if posts.page then 38 | page = posts.page 39 | end 40 | if posts.pagesize then 41 | pagesize = posts.pagesize 42 | end 43 | if page > 1 then 44 | offset = (page -1)*pagesize 45 | end 46 | 47 | local res, err, errno, sqlstate = db:query('SELECT * FROM `'..db_config.table..'` LIMIT '..offset..','..pagesize) 48 | if not res then 49 | ngx.say(cjson.encode({code=200, message=err, data=nil})) 50 | else 51 | ngx.say(cjson.encode({code=200, message="", data=res})) 52 | end 53 | 54 | end 55 | 56 | -- 添加操作 57 | function add() 58 | ngx.req.read_body() 59 | local data = ngx.req.get_post_args() 60 | if data.name ~= nil then 61 | local sql = 'INSERT INTO '..db_config.table..'(name) VALUES ("'..data.name..'")'; 62 | local res, err, errno, sqlstate = db:query(sql) 63 | if not res then 64 | ngx.say(cjson.encode({code=501, message="添加失败"..err..';sql:'..sql, data=nil})) 65 | else 66 | ngx.say(cjson.encode({code=200, message="添加成功", data=res.insert_id})) 67 | end 68 | else 69 | ngx.say(cjson.encode({code=501, message="参数不对", data=nil})) 70 | end 71 | end 72 | 73 | -- 详情页 74 | function detail() 75 | ngx.req.read_body() 76 | local post_args = ngx.req.get_post_args() 77 | if post_args.id ~= nil then 78 | local data, err, errno, sqlstate = db:query('SELECT * FROM '..db_config.table..' WHERE id='..post_args.id..' LIMIT 1', 1) 79 | local res = {} 80 | if data ~= nil then 81 | res.code = 200 82 | res.message = '请求成功' 83 | res.data = data[1] 84 | else 85 | res.code = 502 86 | res.message = '没有数据' 87 | res.data = data 88 | end 89 | ngx.say(cjson.encode(res)) 90 | else 91 | ngx.say(cjson.encode({code = 501, message = '参数错误', data = nil})) 92 | end 93 | 94 | end 95 | 96 | -- 删除操作 97 | function delete() 98 | ngx.req.read_body() 99 | local data = ngx.req.get_post_args() 100 | if data.id ~= nil then 101 | local res, err, errno, sqlstate = db:query('DELETE FROM '..db_config.table..' WHERE id='..data.id) 102 | if not res or res.affected_rows < 1 then 103 | ngx.say(cjson.encode({code = 504, message = '删除失败', data = nil})) 104 | else 105 | ngx.say(cjson.encode({code = 200, message = '修改成功', data = nil})) 106 | end 107 | else 108 | ngx.say(cjson.encode({code = 501, message = '参数错误', data = nil})) 109 | end 110 | end 111 | 112 | -- 修改操作 113 | function update() 114 | ngx.req.read_body() 115 | local post_args = ngx.req.get_post_args() 116 | if post_args.id ~= nil and post_args.name ~= nil then 117 | local res, err, errno, sqlstate = db:query('UPDATE '..db_config.table..' SET `name` = "'..post_args.name..'" WHERE id='..post_args.id) 118 | if not res or res.affected_rows < 1 then 119 | ngx.say(cjson.encode({code = 504, message = '修改失败', data = nil})); 120 | else 121 | ngx.say(cjson.encode({code = 200, message = '修改成功', data = nil})) 122 | end 123 | else 124 | ngx.say(cjson.encode({code = 501, message = '参数错误', data = nil})); 125 | end 126 | end 127 | 128 | if action == 'lists' then 129 | lists() 130 | elseif action == 'detail' then 131 | detail() 132 | elseif action == 'add' then 133 | add() 134 | elseif action == 'delete' then 135 | delete() 136 | elseif action == 'update' then 137 | update() 138 | end 139 | 140 | -------------------------------------------------------------------------------- /mysql/readme.md: -------------------------------------------------------------------------------- 1 | #lua-resty-mysql操作 2 | 3 | 主要是增、删、改、查几个操作 4 | -------------------------------------------------------------------------------- /mysql/sql/tb_user.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `tb_user`; 2 | CREATE TABLE `tb_user` ( 3 | `id` int(12) NOT NULL AUTO_INCREMENT, 4 | `name` varchar(50) CHARACTER SET utf8 DEFAULT NULL, 5 | PRIMARY KEY (`id`) 6 | ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; 7 | -------------------------------------------------------------------------------- /upload/2016/readme.md: -------------------------------------------------------------------------------- 1 | 这是文件上传保存目录,程序会自动生成 2 | -------------------------------------------------------------------------------- /upload/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | lua_package_path '/data/www/openrestyproject/upload/lib/?.lua;/data/www/openrestyproject/upload/?.lua;;'; 2 | server { 3 | server_name localhost; 4 | listen 8000; 5 | charset utf-8; 6 | set $LESSON_ROOT /data/www/openrestyproject/lesson; 7 | error_log /data/www/openrestyproject/upload/logs/error.log; 8 | access_log /data/www/openrestyproject/upload/logs/access.log main; 9 | 10 | 11 | location /upload { 12 | default_type text/html; 13 | content_by_lua_file $LESSON_ROOT/upload.lua; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /upload/html/upload.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 演示 - Web Uploader 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |
21 |

Demo

22 |

您可以尝试文件拖拽,使用QQ截屏工具,然后激活窗口后粘贴,或者点击添加图片按钮,来体验此demo.

23 |
24 |
25 |
26 |
27 |

或将照片拖到这里,单次最多可选300张

28 |
29 |
30 | 31 |
32 | 33 | 34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 |
42 | 46 | 47 | 48 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /upload/html/webuploader/readme.md: -------------------------------------------------------------------------------- 1 | 下载webuploader插件,请到:http://fex.baidu.com/webuploader/ 2 | 3 | webuploader文件夹结构: 4 | 5 | images/ 6 | 7 | images/bg.png 8 | 9 | images/image.png 10 | 11 | images/progress.png 12 | 13 | images/Uploader.swf 14 | 15 | css/ 16 | 17 | css/upload.css 18 | 19 | css/webuploader.css 20 | 21 | js/ 22 | 23 | js/jquery.min.js 24 | 25 | js/webuplader.min.js 26 | -------------------------------------------------------------------------------- /upload/logs/readme.md: -------------------------------------------------------------------------------- 1 | 日志文件保存目录 2 | 3 | 一般为access.log 4 | 5 | 和error.log 6 | -------------------------------------------------------------------------------- /upload/upload.lua: -------------------------------------------------------------------------------- 1 | local _M = { 2 | _VERSION = '0.01' 3 | } 4 | 5 | local upload = require "resty.upload" 6 | local chunk_size = 4096 7 | local cjson = require 'cjson.safe' 8 | local os_exec = os.execute 9 | local os_date = os.date 10 | local md5 = ngx.md5 11 | local io_open = io.open 12 | local tonumber = tonumber 13 | local type = type 14 | local gsub = string.gsub 15 | local ngx_var = ngx.var 16 | local ngx_req = ngx.req 17 | local os_time = os.time 18 | local json_encode = cjson.encode 19 | 20 | 21 | 22 | local function get_ext(res) 23 | local ext = 'jpg' 24 | if res == 'image/png' then 25 | ext = 'png' 26 | elseif res == 'image/jpg' or res == 'image/jpeg' then 27 | ext = 'jpg' 28 | elseif res == 'image/gif' then 29 | ext = 'gif' 30 | end 31 | return ext 32 | end 33 | 34 | local function file_exists(path) 35 | local file = io.open(path, "rb") 36 | if file then file:close() end 37 | return file ~= nil 38 | end 39 | 40 | local function json_return(code, message, data) 41 | ngx.say(json_encode({code = code, msg = message, data = {}})) 42 | end 43 | 44 | local function uploadfile() 45 | local file 46 | local file_name 47 | local form = upload:new(chunk_size) 48 | local conf = {max_size = 1000000, allow_exts = {'jpg', 'png', 'gif'} } 49 | local root_path = ngx_var.document_root 50 | local file_info = {extension = '', filesize = 0, url = '', mime = '' } 51 | local content_len = ngx_req.get_headers()['Content-length'] 52 | local body_size = content_len and tonumber(content_len) or 0 53 | if not form then 54 | return nil, '没有上传的文件' 55 | end 56 | if body_size > 0 and body_size > conf.max_size then 57 | return nil, '文件过大' 58 | end 59 | file_info.filesize = body_size 60 | while true do 61 | local typ, res, err = form:read() 62 | if typ == "header" then 63 | if res[1] == "Content-Type" then 64 | file_info.mime = res[2] 65 | elseif res[1] == "Content-Disposition" then 66 | 67 | local file_id = md5('upload'..os_time()) 68 | local extension = get_ext(res[2]) 69 | file_info.extension = extension 70 | 71 | if not extension then 72 | return nil, '未获取文件后缀' 73 | end 74 | 75 | if not func.in_array(extension, conf.allow_exts) then 76 | return nil, '不支持该文件格式' 77 | end 78 | 79 | local dir = root_path..'/uploads/images/'..os_date('%Y')..'/'..os_date('%m')..'/'..os_date('%d')..'/' 80 | if file_exists(dir) ~= true then 81 | local status = os_exec('mkdir -p '..dir) 82 | if status ~= true then 83 | return nil, '创建目录失败' 84 | end 85 | end 86 | file_name = dir..file_id.."."..extension 87 | if file_name then 88 | file = io_open(file_name, "w+") 89 | if not file then 90 | return nil, '打开文件失败' 91 | end 92 | end 93 | end 94 | elseif typ == "body" then 95 | if file then 96 | file:write(res) 97 | end 98 | elseif typ == "part_end" then 99 | if file then 100 | file:close() 101 | file = nil 102 | end 103 | elseif typ == "eof" then 104 | file_name = gsub(file_name, root_path, '') 105 | file_info.url = file_name 106 | return file_info 107 | else 108 | 109 | end 110 | end 111 | end 112 | 113 | 114 | 115 | local file_info, err = uploadfile() 116 | if file_info then 117 | json_return(200, '上传成功', {imgurl = file_info.url}) 118 | else 119 | json_return(5003, err) 120 | end 121 | 122 | 123 | -------------------------------------------------------------------------------- /websocket/conf/nginx.conf: -------------------------------------------------------------------------------- 1 | lua_package_path '/data/web/vmstats/lib/?.lua;;'; 2 | server { 3 | listen 8000; 4 | #根据自身情况做调整 5 | set $web_root /data/web/vmstats; 6 | 7 | location / { 8 | root $web_root/public; 9 | } 10 | 11 | location =/vmstats { 12 | default_type text/html; 13 | content_by_lua_file $web_root/server.lua; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /websocket/lib/resty/shell.lua: -------------------------------------------------------------------------------- 1 | local _M = { 2 | _VERSION = '0.0.1' 3 | } 4 | 5 | local regex = ngx.re 6 | 7 | function _M.pwd() 8 | return _M.cmd('pwd') 9 | end 10 | 11 | function _M.vmstat() 12 | local tab 13 | local res = _M.cmd('vmstat', 1) 14 | if type(res) == 'table' and #res > 0 then 15 | tab = {} 16 | ngx.say(res[2]) 17 | local line = res[3] 18 | ngx.say(line) 19 | local m = regex.match(line, '(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)') 20 | if m then 21 | tab.r = tonumber(m[1]) 22 | tab.b = tonumber(m[2]) 23 | tab.swpd = tonumber(m[3]) 24 | tab.free = tonumber(m[4]) 25 | tab.buff = tonumber(m[5]) 26 | tab.cache = tonumber(m[6]) 27 | tab.si = tonumber(m[7]) 28 | tab.so = tonumber(m[8]) 29 | tab.bi = tonumber(m[9]) 30 | tab.bo = tonumber(m[10]) 31 | tab.ir = tonumber(m[11]) 32 | tab.cs = tonumber(m[12]) 33 | tab.us = tonumber(m[13]) 34 | tab.sy = tonumber(m[14]) 35 | tab.id = tonumber(m[15]) 36 | tab.wa = tonumber(m[16]) 37 | tab.st = tonumber(m[17]) 38 | end 39 | end 40 | return tab 41 | end 42 | 43 | function _M.cmd(prog, multi_line) 44 | local pd = io.popen(prog) 45 | if pd == nil then 46 | return nil, err 47 | end 48 | local res 49 | if multi_line == 1 then 50 | res = {} 51 | for v in pd:lines() do 52 | res[#res+1] = v 53 | end 54 | else 55 | res = pd:read('*all') 56 | end 57 | pd:close() 58 | return res 59 | end 60 | 61 | return _M 62 | -------------------------------------------------------------------------------- /websocket/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 系统负载统计 9 | 10 | 11 | 12 |
13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 | 21 |
22 | 23 |
24 | 25 |
26 | 27 |
28 | 29 |
30 | 31 |
32 | 33 |
34 | 35 |
36 |
37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /websocket/public/static/js/bootstrap/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.3.7 (http://getbootstrap.com) 3 | * Copyright 2011-2016 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */.btn-danger,.btn-default,.btn-info,.btn-primary,.btn-success,.btn-warning{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-danger.active,.btn-danger:active,.btn-default.active,.btn-default:active,.btn-info.active,.btn-info:active,.btn-primary.active,.btn-primary:active,.btn-success.active,.btn-success:active,.btn-warning.active,.btn-warning:active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-danger.disabled,.btn-danger[disabled],.btn-default.disabled,.btn-default[disabled],.btn-info.disabled,.btn-info[disabled],.btn-primary.disabled,.btn-primary[disabled],.btn-success.disabled,.btn-success[disabled],.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-danger,fieldset[disabled] .btn-default,fieldset[disabled] .btn-info,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-success,fieldset[disabled] .btn-warning{-webkit-box-shadow:none;box-shadow:none}.btn-danger .badge,.btn-default .badge,.btn-info .badge,.btn-primary .badge,.btn-success .badge,.btn-warning .badge{text-shadow:none}.btn.active,.btn:active{background-image:none}.btn-default{text-shadow:0 1px 0 #fff;background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-o-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#e0e0e0));background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;border-color:#ccc}.btn-default:focus,.btn-default:hover{background-color:#e0e0e0;background-position:0 -15px}.btn-default.active,.btn-default:active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-default.disabled,.btn-default.disabled.active,.btn-default.disabled.focus,.btn-default.disabled:active,.btn-default.disabled:focus,.btn-default.disabled:hover,.btn-default[disabled],.btn-default[disabled].active,.btn-default[disabled].focus,.btn-default[disabled]:active,.btn-default[disabled]:focus,.btn-default[disabled]:hover,fieldset[disabled] .btn-default,fieldset[disabled] .btn-default.active,fieldset[disabled] .btn-default.focus,fieldset[disabled] .btn-default:active,fieldset[disabled] .btn-default:focus,fieldset[disabled] .btn-default:hover{background-color:#e0e0e0;background-image:none}.btn-primary{background-image:-webkit-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-o-linear-gradient(top,#337ab7 0,#265a88 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#265a88));background-image:linear-gradient(to bottom,#337ab7 0,#265a88 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#245580}.btn-primary:focus,.btn-primary:hover{background-color:#265a88;background-position:0 -15px}.btn-primary.active,.btn-primary:active{background-color:#265a88;border-color:#245580}.btn-primary.disabled,.btn-primary.disabled.active,.btn-primary.disabled.focus,.btn-primary.disabled:active,.btn-primary.disabled:focus,.btn-primary.disabled:hover,.btn-primary[disabled],.btn-primary[disabled].active,.btn-primary[disabled].focus,.btn-primary[disabled]:active,.btn-primary[disabled]:focus,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary,fieldset[disabled] .btn-primary.active,fieldset[disabled] .btn-primary.focus,fieldset[disabled] .btn-primary:active,fieldset[disabled] .btn-primary:focus,fieldset[disabled] .btn-primary:hover{background-color:#265a88;background-image:none}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#419641));background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:focus,.btn-success:hover{background-color:#419641;background-position:0 -15px}.btn-success.active,.btn-success:active{background-color:#419641;border-color:#3e8f3e}.btn-success.disabled,.btn-success.disabled.active,.btn-success.disabled.focus,.btn-success.disabled:active,.btn-success.disabled:focus,.btn-success.disabled:hover,.btn-success[disabled],.btn-success[disabled].active,.btn-success[disabled].focus,.btn-success[disabled]:active,.btn-success[disabled]:focus,.btn-success[disabled]:hover,fieldset[disabled] .btn-success,fieldset[disabled] .btn-success.active,fieldset[disabled] .btn-success.focus,fieldset[disabled] .btn-success:active,fieldset[disabled] .btn-success:focus,fieldset[disabled] .btn-success:hover{background-color:#419641;background-image:none}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#2aabd2));background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:focus,.btn-info:hover{background-color:#2aabd2;background-position:0 -15px}.btn-info.active,.btn-info:active{background-color:#2aabd2;border-color:#28a4c9}.btn-info.disabled,.btn-info.disabled.active,.btn-info.disabled.focus,.btn-info.disabled:active,.btn-info.disabled:focus,.btn-info.disabled:hover,.btn-info[disabled],.btn-info[disabled].active,.btn-info[disabled].focus,.btn-info[disabled]:active,.btn-info[disabled]:focus,.btn-info[disabled]:hover,fieldset[disabled] .btn-info,fieldset[disabled] .btn-info.active,fieldset[disabled] .btn-info.focus,fieldset[disabled] .btn-info:active,fieldset[disabled] .btn-info:focus,fieldset[disabled] .btn-info:hover{background-color:#2aabd2;background-image:none}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#eb9316));background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:focus,.btn-warning:hover{background-color:#eb9316;background-position:0 -15px}.btn-warning.active,.btn-warning:active{background-color:#eb9316;border-color:#e38d13}.btn-warning.disabled,.btn-warning.disabled.active,.btn-warning.disabled.focus,.btn-warning.disabled:active,.btn-warning.disabled:focus,.btn-warning.disabled:hover,.btn-warning[disabled],.btn-warning[disabled].active,.btn-warning[disabled].focus,.btn-warning[disabled]:active,.btn-warning[disabled]:focus,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning,fieldset[disabled] .btn-warning.active,fieldset[disabled] .btn-warning.focus,fieldset[disabled] .btn-warning:active,fieldset[disabled] .btn-warning:focus,fieldset[disabled] .btn-warning:hover{background-color:#eb9316;background-image:none}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c12e2a));background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:focus,.btn-danger:hover{background-color:#c12e2a;background-position:0 -15px}.btn-danger.active,.btn-danger:active{background-color:#c12e2a;border-color:#b92c28}.btn-danger.disabled,.btn-danger.disabled.active,.btn-danger.disabled.focus,.btn-danger.disabled:active,.btn-danger.disabled:focus,.btn-danger.disabled:hover,.btn-danger[disabled],.btn-danger[disabled].active,.btn-danger[disabled].focus,.btn-danger[disabled]:active,.btn-danger[disabled]:focus,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger,fieldset[disabled] .btn-danger.active,fieldset[disabled] .btn-danger.focus,fieldset[disabled] .btn-danger:active,fieldset[disabled] .btn-danger:focus,fieldset[disabled] .btn-danger:hover{background-color:#c12e2a;background-image:none}.img-thumbnail,.thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:focus,.dropdown-menu>li>a:hover{background-color:#e8e8e8;background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.dropdown-menu>.active>a,.dropdown-menu>.active>a:focus,.dropdown-menu>.active>a:hover{background-color:#2e6da4;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-o-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fff),to(#f8f8f8));background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-o-linear-gradient(top,#dbdbdb 0,#e2e2e2 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dbdbdb),to(#e2e2e2));background-image:linear-gradient(to bottom,#dbdbdb 0,#e2e2e2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-o-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#3c3c3c),to(#222));background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-radius:4px}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.open>a{background-image:-webkit-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-o-linear-gradient(top,#080808 0,#0f0f0f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#080808),to(#0f0f0f));background-image:linear-gradient(to bottom,#080808 0,#0f0f0f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);background-repeat:repeat-x;-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-fixed-bottom,.navbar-fixed-top,.navbar-static-top{border-radius:0}@media (max-width:767px){.navbar .navbar-nav .open .dropdown-menu>.active>a,.navbar .navbar-nav .open .dropdown-menu>.active>a:focus,.navbar .navbar-nav .open .dropdown-menu>.active>a:hover{color:#fff;background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#c8e5bc));background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);background-repeat:repeat-x;border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#b9def0));background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);background-repeat:repeat-x;border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#f8efc0));background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);background-repeat:repeat-x;border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-o-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#e7c3c3));background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);background-repeat:repeat-x;border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#ebebeb),to(#f5f5f5));background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x}.progress-bar{background-image:-webkit-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-o-linear-gradient(top,#337ab7 0,#286090 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#286090));background-image:linear-gradient(to bottom,#337ab7 0,#286090 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);background-repeat:repeat-x}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-o-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5cb85c),to(#449d44));background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);background-repeat:repeat-x}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-o-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#5bc0de),to(#31b0d5));background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);background-repeat:repeat-x}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-o-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f0ad4e),to(#ec971f));background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);background-repeat:repeat-x}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-o-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9534f),to(#c9302c));background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);background-repeat:repeat-x}.progress-bar-striped{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:focus,.list-group-item.active:hover{text-shadow:0 -1px 0 #286090;background-image:-webkit-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2b669a 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2b669a));background-image:linear-gradient(to bottom,#337ab7 0,#2b669a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);background-repeat:repeat-x;border-color:#2b669a}.list-group-item.active .badge,.list-group-item.active:focus .badge,.list-group-item.active:hover .badge{text-shadow:none}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-o-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#e8e8e8));background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-repeat:repeat-x}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-o-linear-gradient(top,#337ab7 0,#2e6da4 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#337ab7),to(#2e6da4));background-image:linear-gradient(to bottom,#337ab7 0,#2e6da4 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);background-repeat:repeat-x}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-o-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#dff0d8),to(#d0e9c6));background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);background-repeat:repeat-x}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-o-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#d9edf7),to(#c4e3f3));background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);background-repeat:repeat-x}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-o-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#fcf8e3),to(#faf2cc));background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);background-repeat:repeat-x}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-o-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#f2dede),to(#ebcccc));background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);background-repeat:repeat-x}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-o-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:-webkit-gradient(linear,left top,left bottom,from(#e8e8e8),to(#f5f5f5));background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);background-repeat:repeat-x;border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} 6 | /*# sourceMappingURL=bootstrap-theme.min.css.map */ -------------------------------------------------------------------------------- /websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixinke/openresty-practices/c34b2322cc2428586eec45ebd4d4b205bad0377e/websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixinke/openresty-practices/c34b2322cc2428586eec45ebd4d4b205bad0377e/websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixinke/openresty-practices/c34b2322cc2428586eec45ebd4d4b205bad0377e/websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixinke/openresty-practices/c34b2322cc2428586eec45ebd4d4b205bad0377e/websocket/public/static/js/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /websocket/public/static/js/bootstrap/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/adapters/standalone-framework.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/adapters/standalone-framework.src.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/highcharts-3d.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | 4 | 3D features for Highcharts JS 5 | 6 | @license: www.highcharts.com/license 7 | */ 8 | (function(d){typeof module==="object"&&module.exports?module.exports=d:d(Highcharts)})(function(d){function C(c){return c!==void 0&&c!==null}function H(c){var b=0,a,f;for(a=0;ae&&g-e>p/2+1.0E-4?(k=k.concat(u(c,b,a,f,e,e+p/2,d,j)),k=k.concat(u(c,b,a,f,e+p/2,g,d,j))):gp/2+1.0E-4?(k=k.concat(u(c,b, 9 | a,f,e,e-p/2,d,j)),k=k.concat(u(c,b,a,f,e-p/2,g,d,j))):(k=g-e,k=["C",c+a*l(e)-a*E*k*q(e)+d,b+f*q(e)+f*E*k*l(e)+j,c+a*l(g)+a*E*k*q(g)+d,b+f*q(g)-f*E*k*l(g)+j,c+a*l(g)+d,b+f*q(g)+j]);return k}function L(c,b){var a=c.plotLeft,f=c.plotWidth+a,e=c.plotTop,g=c.plotHeight+e,d=a+c.plotWidth/2,j=e+c.plotHeight/2,k=Number.MAX_VALUE,h=-Number.MAX_VALUE,m=Number.MAX_VALUE,t=-Number.MAX_VALUE,o,l=1;o=[{x:a,y:e,z:0},{x:a,y:e,z:b}];r([0,1],function(a){o.push({x:f,y:o[a].y,z:o[a].z})});r([0,1,2,3],function(a){o.push({x:o[a].x, 10 | y:g,z:o[a].z})});o=s(o,c,!1);r(o,function(a){k=Math.min(k,a.x);h=Math.max(h,a.x);m=Math.min(m,a.y);t=Math.max(t,a.y)});a>k&&(l=Math.min(l,1-Math.abs((a+d)/(k+d))%1));fm&&(l=m<0?Math.min(l,(e+j)/(-m+e+j)):Math.min(l,1-(e+j)/(m+j)%1));g0&&kp&&(a=2*p-a);return a}var a=c.x,f=c.y,e=c.start,d=c.end-1.0E-5,i=c.r,j=c.innerR,k=c.depth,h=c.alpha,m=c.beta,t=l(e),o=q(e),c=l(d),r=q(d),n=i*l(m);i*=l(h); 22 | var x=j*l(m),y=j*l(h),j=k*q(m),v=k*q(h),k=["M",a+n*t,f+i*o],k=k.concat(u(a,f,n,i,e,d,0,0)),k=k.concat(["L",a+x*c,f+y*r]),k=k.concat(u(a,f,x,y,d,e,0,0)),k=k.concat(["Z"]),s=m>0?p/2:0,m=h>0?0:p/2,s=e>-s?e:d>-s?-s:e,w=dz&&ep-m&&e0?4:-1}).css({stroke:g.color}).add()):(d={x:m+(b.yAxis[0].opposite?0:-e.size),y:l+(b.xAxis[0].opposite?-g.size:0),z:j,width:h+e.size,height:k+g.size,depth:i.size,insidePlotArea:!1},this.backFrame? 30 | this.backFrame.animate(d):this.backFrame=a.cuboid(d).attr({fill:i.color,zIndex:-3}).css({stroke:i.color}).add(),b={x:m+(b.yAxis[0].opposite?h:-e.size),y:l+(b.xAxis[0].opposite?-g.size:0),z:0,width:e.size,height:k+g.size,depth:j,insidePlotArea:!1},this.sideFrame?this.sideFrame.animate(b):this.sideFrame=a.cuboid(b).attr({fill:e.color,zIndex:-2}).css({stroke:e.color}).add())}});d.wrap(d.Axis.prototype,"getPlotLinePath",function(c){var b=c.apply(this,[].slice.call(arguments,1));if(!this.chart.is3d())return b; 31 | if(b===null)return b;var a=this.chart,d=a.options.chart.options3d,a=this.isZAxis?a.plotWidth:d.depth,d=this.opposite;this.horiz&&(d=!d);b=[this.swapZ({x:b[1],y:b[2],z:d?a:0}),this.swapZ({x:b[1],y:b[2],z:a}),this.swapZ({x:b[4],y:b[5],z:a}),this.swapZ({x:b[4],y:b[5],z:d?0:a})];b=s(b,this.chart,!1);return b=this.chart.renderer.toLinePath(b,!1)});d.wrap(d.Axis.prototype,"getLinePath",function(c){return this.chart.is3d()?[]:c.apply(this,[].slice.call(arguments,1))});d.wrap(d.Axis.prototype,"getPlotBandPath", 32 | function(c){if(!this.chart.is3d())return c.apply(this,[].slice.call(arguments,1));var b=arguments,a=b[1],b=this.getPlotLinePath(b[2]);(a=this.getPlotLinePath(a))&&b?a.push("L",b[10],b[11],"L",b[7],b[8],"L",b[4],b[5],"L",b[1],b[2]):a=null;return a});d.wrap(d.Tick.prototype,"getMarkPath",function(c){var b=c.apply(this,[].slice.call(arguments,1));if(!this.axis.chart.is3d())return b;b=[this.axis.swapZ({x:b[1],y:b[2],z:0}),this.axis.swapZ({x:b[4],y:b[5],z:0})];b=s(b,this.axis.chart,!1);return b=["M",b[0].x, 33 | b[0].y,"L",b[1].x,b[1].y]});d.wrap(d.Tick.prototype,"getLabelPosition",function(c){var b=c.apply(this,[].slice.call(arguments,1));this.axis.chart.is3d()&&(b=s([this.axis.swapZ({x:b.x,y:b.y,z:0})],this.axis.chart,!1)[0]);return b});d.wrap(d.Axis.prototype,"getTitlePosition",function(c){var b=this.chart.is3d(),a,d;if(b)d=this.axisTitleMargin,this.axisTitleMargin=0;a=c.apply(this,[].slice.call(arguments,1));if(b)a=s([this.swapZ({x:a.x,y:a.y,z:0})],this.chart,!1)[0],a[this.horiz?"y":"x"]+=(this.horiz? 34 | 1:-1)*(this.opposite?-1:1)*d,this.axisTitleMargin=d;return a});d.wrap(d.Axis.prototype,"drawCrosshair",function(c){var b=arguments;this.chart.is3d()&&b[2]&&(b[2]={plotX:b[2].plotXold||b[2].plotX,plotY:b[2].plotYold||b[2].plotY});c.apply(this,[].slice.call(b,1))});d.Axis.prototype.swapZ=function(c,b){if(this.isZAxis){var a=b?0:this.chart.plotLeft,d=this.chart;return{x:a+(d.yAxis[0].opposite?c.z:d.xAxis[0].width-c.z),y:c.y,z:c.x-a}}return c};var G=d.ZAxis=function(){this.isZAxis=!0;this.init.apply(this, 35 | arguments)};d.extend(G.prototype,d.Axis.prototype);d.extend(G.prototype,{setOptions:function(c){c=d.merge({offset:0,lineWidth:0},c);d.Axis.prototype.setOptions.call(this,c);this.coll="zAxis"},setAxisSize:function(){d.Axis.prototype.setAxisSize.call(this);this.width=this.len=this.chart.options.chart.options3d.depth;this.right=this.chart.chartWidth-this.width-this.left},getSeriesExtremes:function(){var c=this,b=c.chart;c.hasVisibleSeries=!1;c.dataMin=c.dataMax=c.ignoreMinPadding=c.ignoreMaxPadding= 36 | null;c.buildStacks&&c.buildStacks();d.each(c.series,function(a){if(a.visible||!b.options.chart.ignoreHiddenSeries)if(c.hasVisibleSeries=!0,a=a.zData,a.length)c.dataMin=Math.min(A(c.dataMin,a[0]),Math.min.apply(null,a)),c.dataMax=Math.max(A(c.dataMax,a[0]),Math.max.apply(null,a))})}});d.wrap(d.Chart.prototype,"getAxes",function(c){var b=this,a=this.options,a=a.zAxis=d.splat(a.zAxis||{});c.call(this);if(b.is3d())this.zAxis=[],d.each(a,function(a,c){a.index=c;a.isX=!0;(new G(b,a)).setScale()})});d.wrap(d.seriesTypes.column.prototype, 37 | "translate",function(c){c.apply(this,[].slice.call(arguments,1));if(this.chart.is3d()){var b=this.chart,a=this.options,f=a.depth||25,e=(a.stacking?a.stack||0:this._i)*(f+(a.groupZPadding||1));a.grouping!==!1&&(e=0);e+=a.groupZPadding||1;d.each(this.data,function(a){if(a.y!==null){var c=a.shapeArgs,d=a.tooltipPos;a.shapeType="cuboid";c.z=e;c.depth=f;c.insidePlotArea=!0;d=s([{x:d[0],y:d[1],z:e}],b,!0)[0];a.tooltipPos=[d.x,d.y]}});this.z=e}});d.wrap(d.seriesTypes.column.prototype,"animate",function(c){if(this.chart.is3d()){var b= 38 | arguments[1],a=this.yAxis,f=this,e=this.yAxis.reversed;if(d.svg)b?d.each(f.data,function(b){if(b.y!==null&&(b.height=b.shapeArgs.height,b.shapey=b.shapeArgs.y,b.shapeArgs.height=1,!e))b.shapeArgs.y=b.stackY?b.plotY+a.translate(b.stackY):b.plotY+(b.negative?-b.height:b.height)}):(d.each(f.data,function(a){if(a.y!==null)a.shapeArgs.height=a.height,a.shapeArgs.y=a.shapey,a.graphic&&a.graphic.animate(a.shapeArgs,f.options.animation)}),this.drawDataLabels(),f.animate=null)}else c.apply(this,[].slice.call(arguments, 39 | 1))});d.wrap(d.seriesTypes.column.prototype,"init",function(c){c.apply(this,[].slice.call(arguments,1));if(this.chart.is3d()){var b=this.options,a=b.grouping,d=b.stacking,e=A(this.yAxis.options.reversedStacks,!0),g=0;if(a===void 0||a){a=this.chart.retrieveStacks(d);g=b.stack||0;for(d=0;d=a.min&&g<=a.max:!1,f.push({x:e.plotX,y:e.plotY,z:e.plotZ});b=s(f,b,!0);for(i=0;i{point.x}
y: {point.y}
z: {point.z}
":"x: {point.x}
y: {point.y}
z: {point.z}
";return c});if(d.VMLRenderer)d.setOptions({animate:!1}), 48 | d.VMLRenderer.prototype.cuboid=d.SVGRenderer.prototype.cuboid,d.VMLRenderer.prototype.cuboidPath=d.SVGRenderer.prototype.cuboidPath,d.VMLRenderer.prototype.toLinePath=d.SVGRenderer.prototype.toLinePath,d.VMLRenderer.prototype.createElement3D=d.SVGRenderer.prototype.createElement3D,d.VMLRenderer.prototype.arc3d=function(c){c=d.SVGRenderer.prototype.arc3d.call(this,c);c.css({zIndex:c.zIndex});return c},d.VMLRenderer.prototype.arc3dPath=d.SVGRenderer.prototype.arc3dPath,d.wrap(d.Axis.prototype,"render", 49 | function(c){c.apply(this,[].slice.call(arguments,1));this.sideFrame&&(this.sideFrame.css({zIndex:0}),this.sideFrame.front.attr({fill:this.sideFrame.color}));this.bottomFrame&&(this.bottomFrame.css({zIndex:1}),this.bottomFrame.front.attr({fill:this.bottomFrame.color}));this.backFrame&&(this.backFrame.css({zIndex:0}),this.backFrame.front.attr({fill:this.backFrame.color}))})}); 50 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/boost.js: -------------------------------------------------------------------------------- 1 | (function(c){typeof module==="object"&&module.exports?module.exports=c:c(Highcharts)})(function(c){function z(a,b,d,f,h){for(var h=h||0,f=f||A,c=h+f,r=!0;r&&h(b.boostThreshold||Number.MAX_VALUE)&&m(f.min)&&m(f.max)&&(!a||m(d.min)&&m(d.max))},destroyGraphics:function(){var a=this,b=this.points,d,f;if(b)for(f=0;f99999)d.options.loading=V(i,{labelStyle:{backgroundColor:"rgba(255,255,255,0.75)",padding:"1em",borderRadius:"0.5em"},style:{backgroundColor:"none",opacity:1}}),clearTimeout(B),d.showLoading("Drawing..."),d.options.loading=i;z(M?a.data: 9 | j||l,function(b,c){var e,g,j,i,l=typeof d.index==="undefined",m=!0;if(!l){O?(e=b[0],g=b[1]):(e=b,g=k[c]);if(L)O&&(g=b.slice(1,3)),i=g[0],g=g[1];else if(M)e=b.x,g=b.stackY,i=g-b.y;j=g===null;ba||(m=g>=u&&g<=X);if(!j&&e>=p&&e<=s&&m)if(e=Math.round(f.toPixels(e,!0)),Y){if(o===void 0||e===v){L||(i=g);if(q===void 0||g>x)x=g,q=c;if(o===void 0||i=c?(e-c)%b:b-(c-e)%b;return g.inclusive?b<=a:b=a)break;else if(c.isInBreak(k,a)){d-=a-k.from;break}return d};this.lin2val=function(a){var d,b;for(b=0;b=a)break;else d.tol;)i-=e;for(;i< 5 | l;)i+=e;for(;ia.to||d>a.from&&ja.from&&ja.from&&j>a.to&&j= from ? (val - from) % repeat : repeat - ((from - val) % repeat)); 40 | 41 | if (!brk.inclusive) { 42 | ret = test < length && test !== 0; 43 | } else { 44 | ret = test <= length; 45 | } 46 | return ret; 47 | }, 48 | 49 | isInAnyBreak: function (val, testKeep) { 50 | 51 | var breaks = this.options.breaks, 52 | i = breaks && breaks.length, 53 | inbrk, 54 | keep, 55 | ret; 56 | 57 | 58 | if (i) { 59 | 60 | while (i--) { 61 | if (this.isInBreak(breaks[i], val)) { 62 | inbrk = true; 63 | if (!keep) { 64 | keep = pick(breaks[i].showPoints, this.isXAxis ? false : true); 65 | } 66 | } 67 | } 68 | 69 | if (inbrk && testKeep) { 70 | ret = inbrk && !keep; 71 | } else { 72 | ret = inbrk; 73 | } 74 | } 75 | return ret; 76 | } 77 | }); 78 | 79 | wrap(Axis.prototype, 'setTickPositions', function (proceed) { 80 | proceed.apply(this, Array.prototype.slice.call(arguments, 1)); 81 | 82 | if (this.options.breaks) { 83 | var axis = this, 84 | tickPositions = this.tickPositions, 85 | info = this.tickPositions.info, 86 | newPositions = [], 87 | i; 88 | 89 | for (i = 0; i < tickPositions.length; i++) { 90 | if (!axis.isInAnyBreak(tickPositions[i])) { 91 | newPositions.push(tickPositions[i]); 92 | } 93 | } 94 | 95 | this.tickPositions = newPositions; 96 | this.tickPositions.info = info; 97 | } 98 | }); 99 | 100 | wrap(Axis.prototype, 'init', function (proceed, chart, userOptions) { 101 | // Force Axis to be not-ordinal when breaks are defined 102 | if (userOptions.breaks && userOptions.breaks.length) { 103 | userOptions.ordinal = false; 104 | } 105 | 106 | proceed.call(this, chart, userOptions); 107 | 108 | if (this.options.breaks) { 109 | 110 | var axis = this; 111 | 112 | axis.isBroken = true; 113 | 114 | this.val2lin = function (val) { 115 | var nval = val, 116 | brk, 117 | i; 118 | 119 | for (i = 0; i < axis.breakArray.length; i++) { 120 | brk = axis.breakArray[i]; 121 | if (brk.to <= val) { 122 | nval -= brk.len; 123 | } else if (brk.from >= val) { 124 | break; 125 | } else if (axis.isInBreak(brk, val)) { 126 | nval -= (val - brk.from); 127 | break; 128 | } 129 | } 130 | 131 | return nval; 132 | }; 133 | 134 | this.lin2val = function (val) { 135 | var nval = val, 136 | brk, 137 | i; 138 | 139 | for (i = 0; i < axis.breakArray.length; i++) { 140 | brk = axis.breakArray[i]; 141 | if (brk.from >= nval) { 142 | break; 143 | } else if (brk.to < nval) { 144 | nval += brk.len; 145 | } else if (axis.isInBreak(brk, nval)) { 146 | nval += brk.len; 147 | } 148 | } 149 | return nval; 150 | }; 151 | 152 | this.setExtremes = function (newMin, newMax, redraw, animation, eventArguments) { 153 | // If trying to set extremes inside a break, extend it to before and after the break ( #3857 ) 154 | while (this.isInAnyBreak(newMin)) { 155 | newMin -= this.closestPointRange; 156 | } 157 | while (this.isInAnyBreak(newMax)) { 158 | newMax -= this.closestPointRange; 159 | } 160 | Axis.prototype.setExtremes.call(this, newMin, newMax, redraw, animation, eventArguments); 161 | }; 162 | 163 | this.setAxisTranslation = function (saveOld) { 164 | Axis.prototype.setAxisTranslation.call(this, saveOld); 165 | 166 | var breaks = axis.options.breaks, 167 | breakArrayT = [], // Temporary one 168 | breakArray = [], 169 | length = 0, 170 | inBrk, 171 | repeat, 172 | brk, 173 | min = axis.userMin || axis.min, 174 | max = axis.userMax || axis.max, 175 | start, 176 | i, 177 | j; 178 | 179 | // Min & max check (#4247) 180 | for (i in breaks) { 181 | brk = breaks[i]; 182 | repeat = brk.repeat || Infinity; 183 | if (axis.isInBreak(brk, min)) { 184 | min += (brk.to % repeat) - (min % repeat); 185 | } 186 | if (axis.isInBreak(brk, max)) { 187 | max -= (max % repeat) - (brk.from % repeat); 188 | } 189 | } 190 | 191 | // Construct an array holding all breaks in the axis 192 | for (i in breaks) { 193 | brk = breaks[i]; 194 | start = brk.from; 195 | repeat = brk.repeat || Infinity; 196 | 197 | while (start - repeat > min) { 198 | start -= repeat; 199 | } 200 | while (start < min) { 201 | start += repeat; 202 | } 203 | 204 | for (j = start; j < max; j += repeat) { 205 | breakArrayT.push({ 206 | value: j, 207 | move: 'in' 208 | }); 209 | breakArrayT.push({ 210 | value: j + (brk.to - brk.from), 211 | move: 'out', 212 | size: brk.breakSize 213 | }); 214 | } 215 | } 216 | 217 | breakArrayT.sort(function (a, b) { 218 | var ret; 219 | if (a.value === b.value) { 220 | ret = (a.move === 'in' ? 0 : 1) - (b.move === 'in' ? 0 : 1); 221 | } else { 222 | ret = a.value - b.value; 223 | } 224 | return ret; 225 | }); 226 | 227 | // Simplify the breaks 228 | inBrk = 0; 229 | start = min; 230 | 231 | for (i in breakArrayT) { 232 | brk = breakArrayT[i]; 233 | inBrk += (brk.move === 'in' ? 1 : -1); 234 | 235 | if (inBrk === 1 && brk.move === 'in') { 236 | start = brk.value; 237 | } 238 | if (inBrk === 0) { 239 | breakArray.push({ 240 | from: start, 241 | to: brk.value, 242 | len: brk.value - start - (brk.size || 0) 243 | }); 244 | length += brk.value - start - (brk.size || 0); 245 | } 246 | } 247 | 248 | axis.breakArray = breakArray; 249 | 250 | fireEvent(axis, 'afterBreaks'); 251 | 252 | axis.transA *= ((max - axis.min) / (max - min - length)); 253 | 254 | axis.min = min; 255 | axis.max = max; 256 | }; 257 | } 258 | }); 259 | 260 | wrap(Series.prototype, 'generatePoints', function (proceed) { 261 | 262 | proceed.apply(this, stripArguments(arguments)); 263 | 264 | var series = this, 265 | xAxis = series.xAxis, 266 | yAxis = series.yAxis, 267 | points = series.points, 268 | point, 269 | i = points.length, 270 | connectNulls = series.options.connectNulls, 271 | nullGap; 272 | 273 | 274 | if (xAxis && yAxis && (xAxis.options.breaks || yAxis.options.breaks)) { 275 | while (i--) { 276 | point = points[i]; 277 | 278 | nullGap = point.y === null && connectNulls === false; // respect nulls inside the break (#4275) 279 | if (!nullGap && (xAxis.isInAnyBreak(point.x, true) || yAxis.isInAnyBreak(point.y, true))) { 280 | points.splice(i, 1); 281 | if (this.data[i]) { 282 | this.data[i].destroyElements(); // removes the graphics for this point if they exist 283 | } 284 | } 285 | } 286 | } 287 | 288 | }); 289 | 290 | function drawPointsWrapped(proceed) { 291 | proceed.apply(this); 292 | this.drawBreaks(this.xAxis, ['x']); 293 | this.drawBreaks(this.yAxis, pick(this.pointArrayMap, ['y'])); 294 | } 295 | 296 | H.Series.prototype.drawBreaks = function (axis, keys) { 297 | var series = this, 298 | points = series.points, 299 | breaks, 300 | threshold, 301 | eventName, 302 | y; 303 | 304 | each(keys, function (key) { 305 | breaks = axis.breakArray || []; 306 | threshold = axis.isXAxis ? axis.min : pick(series.options.threshold, axis.min); 307 | each(points, function (point) { 308 | y = pick(point['stack' + key.toUpperCase()], point[key]); 309 | each(breaks, function (brk) { 310 | eventName = false; 311 | 312 | if ((threshold < brk.from && y > brk.to) || (threshold > brk.from && y < brk.from)) { 313 | eventName = 'pointBreak'; 314 | } else if ((threshold < brk.from && y > brk.from && y < brk.to) || (threshold > brk.from && y > brk.to && y < brk.from)) { // point falls inside the break 315 | eventName = 'pointInBreak'; 316 | } 317 | if (eventName) { 318 | fireEvent(axis, eventName, { point: point, brk: brk }); 319 | } 320 | }); 321 | }); 322 | }); 323 | }; 324 | 325 | wrap(H.seriesTypes.column.prototype, 'drawPoints', drawPointsWrapped); 326 | wrap(H.Series.prototype, 'drawPoints', drawPointsWrapped); 327 | 328 | })); 329 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/data.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | Data module 4 | 5 | (c) 2012-2016 Torstein Honsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(g){typeof module==="object"&&module.exports?module.exports=g:g(Highcharts)})(function(g){var v=g.win.document,k=g.each,w=g.pick,s=g.inArray,t=g.isNumber,x=g.splat,l,p=function(b,a){this.init(b,a)};g.extend(p.prototype,{init:function(b,a){this.options=b;this.chartOptions=a;this.columns=b.columns||this.rowsToColumns(b.rows)||[];this.firstRowAsNames=w(b.firstRowAsNames,!0);this.decimalRegex=b.decimalPoint&&RegExp("^(-?[0-9]+)"+b.decimalPoint+"([0-9]+)$");this.rawColumns=[];this.columns.length? 10 | this.dataFound():(this.parseCSV(),this.parseTable(),this.parseGoogleSpreadsheet())},getColumnDistribution:function(){var b=this.chartOptions,a=this.options,e=[],f=function(b){return(g.seriesTypes[b||"line"].prototype.pointArrayMap||[0]).length},d=b&&b.chart&&b.chart.type,c=[],h=[],r=0,i;k(b&&b.series||[],function(b){c.push(f(b.type||d))});k(a&&a.seriesMapping||[],function(b){e.push(b.x||0)});e.length===0&&e.push(0);k(a&&a.seriesMapping||[],function(a){var e=new l,o,n=c[r]||f(d),m=g.seriesTypes[((b&& 11 | b.series||[])[r]||{}).type||d||"line"].prototype.pointArrayMap||["y"];e.addColumnReader(a.x,"x");for(o in a)a.hasOwnProperty(o)&&o!=="x"&&e.addColumnReader(a[o],o);for(i=0;i=d&&e<=c&&!q&&g!==""&&(g=a.split(i),k(g,function(b,a){a>= 13 | h&&a<=r&&(f[a-h]||(f[a-h]=[]),f[a-h][u]=b)}),u+=1)}),this.dataFound())},parseTable:function(){var b=this.options,a=b.table,e=this.columns,f=b.startRow||0,d=b.endRow||Number.MAX_VALUE,c=b.startColumn||0,h=b.endColumn||Number.MAX_VALUE;a&&(typeof a==="string"&&(a=v.getElementById(a)),k(a.getElementsByTagName("tr"),function(b,a){a>=f&&a<=d&&k(b.children,function(b,d){if((b.tagName==="TD"||b.tagName==="TH")&&d>=c&&d<=h)e[d-c]||(e[d-c]=[]),e[d-c][a-f]=b.innerHTML})}),this.dataFound())},parseGoogleSpreadsheet:function(){var b= 14 | this,a=this.options,e=a.googleSpreadsheetKey,f=this.columns,d=a.startRow||0,c=a.endRow||Number.MAX_VALUE,h=a.startColumn||0,g=a.endColumn||Number.MAX_VALUE,i,q;e&&jQuery.ajax({dataType:"json",url:"https://spreadsheets.google.com/feeds/cells/"+e+"/"+(a.googleSpreadsheetWorksheet||"od6")+"/public/values?alt=json-in-script&callback=?",error:a.error,success:function(a){var a=a.feed.entry,e,n=a.length,m=0,l=0,j;for(j=0;j= 15 | h&&j<=g)f[j-h]=[],f[j-h].length=Math.min(l,c-d);for(j=0;j=h&&q<=g&&i>=d&&i<=c)f[q-h][i-d]=e.content.$t;k(f,function(a){for(j=0;j31536E6&&p!=="float"?b.isDatetime=!0:b.isNumeric=!0,b[d+1]!==void 0&& 17 | (m=h>b[d+1]);else if(h=this.parseDate(c),k&&t(h)&&p!=="float"){if(o[d]=c,b[d]=h,b.isDatetime=!0,b[d+1]!==void 0){c=h>b[d+1];if(c!==m&&m!==void 0)this.alternativeFormat?(this.dateFormat=this.alternativeFormat,d=b.length,this.alternativeFormat=this.dateFormats[this.dateFormat].alternative):b.unsorted=!0;m=c}}else if(b[d]=g===""?null:g,d!==0&&(b.isDatetime||b.isNumeric))b.mixed=!0;k&&b.mixed&&(f[a]=e[a]);if(k&&m&&this.options.sort)for(a=0;a0;){i=new l;i.addColumnReader(0,"x");c=s(0, 22 | d);c!==-1&&d.splice(c,1);for(c=0;c0&&g[0].readers.length>0&&(i=b[g[0].readers[0].columnIndex],i!==void 0&&(i.isDatetime?a="datetime":i.isNumeric||(a="category")));if(a==="category")for(c=0;c=2&&(d=this.getReferencedColumnIndexes(),d.length>=2))d.shift(),d.sort(),this.name=b[d.shift()].name;return f};l.prototype.addColumnReader=function(b,a){this.readers.push({columnIndex:b,configName:a});if(!(a==="x"||a==="y"||a===void 0))this.pointIsArray=!1};l.prototype.getReferencedColumnIndexes=function(){var b,a=[],e;for(b=0;b0)a=b[b.length-1].levelNumber,i(this.drilldownLevels,function(b){b.levelNumber===a&&i(b.levelSeries,function(b){b.options&&b.options._levelNumber===a&&b.remove(!1)})});this.redraw();this.showDrillUpButton()};l.prototype.getDrilldownBackText=function(){var b=this.drilldownLevels;if(b&&b.length>0)return b=b[b.length-1],b.series=b.seriesOptions,B(this.options.lang.drillUpText,b)};l.prototype.showDrillUpButton=function(){var b=this,a=this.getDrilldownBackText(),d= 7 | b.options.drilldown.drillUpButton,c,g;this.drillUpButton?this.drillUpButton.attr({text:a}).align():(g=(c=d.theme)&&c.states,this.drillUpButton=this.renderer.button(a,null,null,function(){b.drillUp()},c,g&&g.hover,g&&g.select).attr({align:d.position.align,zIndex:9}).add().align(d.position,!1,d.relativeTo||"plotBox"))};l.prototype.drillUp=function(){for(var b=this,a=b.drilldownLevels,d=a[a.length-1].levelNumber,c=a.length,g=b.series,f,h,e,j,k=function(a){var c;i(g,function(b){b.options._ddSeriesId=== 8 | a._ddSeriesId&&(c=b)});c=c||b.addSeries(a,!1);if(c.type===e.type&&c.animateDrillupTo)c.animate=c.animateDrillupTo;a===h.seriesOptions&&(j=c)};c--;)if(h=a[c],h.levelNumber===d){a.pop();e=h.lowerSeries;if(!e.chart)for(f=g.length;f--;)if(g[f].options.id===h.lowerSeriesOptions.id&&g[f].options._levelNumber===d+1){e=g[f];break}e.xData=[];i(h.levelSeriesOptions,k);s(b,"drillup",{seriesOptions:h.seriesOptions});if(j.type===e.type)j.drilldownLevel=h,j.options.animation=b.options.drilldown.animation,e.animateDrillupFrom&& 9 | e.chart&&e.animateDrillupFrom(h);j.options._levelNumber=d;e.remove(!1);if(j.xAxis)f=h.oldExtremes,j.xAxis.setExtremes(f.xMin,f.xMax,!1),j.yAxis.setExtremes(f.yMin,f.yMax,!1)}s(b,"drillupall");this.redraw();this.drilldownLevels.length===0?this.drillUpButton=this.drillUpButton.destroy():this.drillUpButton.attr({text:this.getDrilldownBackText()}).align();this.ddDupes.length=[]};m.prototype.supportsDrilldown=!0;m.prototype.animateDrillupTo=function(b){if(!b){var a=this,d=a.drilldownLevel;i(this.points, 10 | function(a){a.graphic&&a.graphic.hide();a.dataLabel&&a.dataLabel.hide();a.connector&&a.connector.hide()});setTimeout(function(){a.points&&i(a.points,function(a,b){var f=b===(d&&d.pointIndex)?"show":"fadeIn",e=f==="show"?!0:void 0;if(a.graphic)a.graphic[f](e);if(a.dataLabel)a.dataLabel[f](e);if(a.connector)a.connector[f](e)})},Math.max(this.chart.options.drilldown.animation.duration-50,0));this.animate=u}};m.prototype.animateDrilldown=function(b){var a=this,d=this.chart.drilldownLevels,c,g=this.chart.options.drilldown.animation, 11 | f=this.xAxis;if(!b)i(d,function(b){if(a.options._ddSeriesId===b.lowerSeriesOptions._ddSeriesId)c=b.shapeArgs,c.fill=b.color}),c.x+=v(f.oldPos,f.pos)-f.pos,i(this.points,function(b){b.graphic&&b.graphic.attr(c).animate(o(b.shapeArgs,{fill:b.color||a.color}),g);b.dataLabel&&b.dataLabel.fadeIn(g)}),this.animate=null};m.prototype.animateDrillupFrom=function(b){var a=this.chart.options.drilldown.animation,d=this.group,c=this;i(c.trackerGroups,function(a){if(c[a])c[a].on("mouseover")});delete this.group; 12 | i(this.points,function(c){var f=c.graphic,h=function(){f.destroy();d&&(d=d.destroy())};f&&(delete c.graphic,a?f.animate(o(b.shapeArgs,{fill:b.color}),e.merge(a,{complete:h})):(f.attr(b.shapeArgs),h()))})};w&&o(w.prototype,{supportsDrilldown:!0,animateDrillupTo:m.prototype.animateDrillupTo,animateDrillupFrom:m.prototype.animateDrillupFrom,animateDrilldown:function(b){var a=this.chart.drilldownLevels[this.chart.drilldownLevels.length-1],d=this.chart.options.drilldown.animation,c=a.shapeArgs,g=c.start, 13 | f=(c.end-g)/this.points.length;if(!b)i(this.points,function(b,i){b.graphic.attr(e.merge(c,{start:g+i*f,end:g+(i+1)*f,fill:a.color}))[d?"animate":"attr"](o(b.shapeArgs,{fill:b.color}),d)}),this.animate=null}});e.Point.prototype.doDrilldown=function(b,a,d){var c=this.series.chart,e=c.options.drilldown,f=(e.series||[]).length,h;if(!c.ddDupes)c.ddDupes=[];for(;f--&&!h;)e.series[f].id===this.drilldown&&y(this.drilldown,c.ddDupes)===-1&&(h=e.series[f],c.ddDupes.push(this.drilldown));s(c,"drilldown",{point:this, 14 | seriesOptions:h,category:a,originalEvent:d,points:a!==void 0&&this.series.xAxis.ddPoints[a].slice(0)},function(a){var c=a.point.series&&a.point.series.chart,d=a.seriesOptions;c&&d&&(b?c.addSingleSeriesAsDrilldown(a.point,d):c.addSeriesAsDrilldown(a.point,d))})};e.Axis.prototype.drilldownCategory=function(b,a){var d,c,e=this.ddPoints[b];for(d in e)(c=e[d])&&c.series&&c.series.visible&&c.doDrilldown&&c.doDrilldown(!0,b,a);this.chart.applyDrilldown()};e.Axis.prototype.getDDPoints=function(b,a){var d= 15 | this.ddPoints;if(!d)this.ddPoints=d={};d[b]||(d[b]=[]);if(d[b].levelNumber!==a)d[b].length=0;return d[b]};x.prototype.drillable=function(){var b=this.pos,a=this.label,d=this.axis,c=d.ddPoints&&d.ddPoints[b];if(a&&c&&c.length){if(!a.basicStyles)a.basicStyles=e.merge(a.styles);a.addClass("highcharts-drilldown-axis-label").css(d.chart.options.drilldown.activeAxisLabelStyle).on("click",function(a){d.drilldownCategory(b,a)})}else if(a&&a.basicStyles)a.styles={},a.css(a.basicStyles),a.on("click",null)}; 16 | r(x.prototype,"addLabel",function(b){b.call(this);this.drillable()});r(e.Point.prototype,"init",function(b,a,d,c){var g=b.call(this,a,d,c),b=(d=a.xAxis)&&d.ticks[c],d=d&&d.getDDPoints(c,a.options._levelNumber);if(g.drilldown&&(e.addEvent(g,"click",function(b){a.xAxis&&a.chart.options.drilldown.allowPointDrilldown===!1?a.xAxis.drilldownCategory(c,b):g.doDrilldown(void 0,void 0,b)}),d))d.push(g),d.levelNumber=a.options._levelNumber;b&&b.drillable();return g});r(e.Series.prototype,"drawDataLabels",function(b){var a= 17 | this,d=a.chart.options.drilldown.activeDataLabelStyle,c=a.chart.renderer;b.call(a);i(a.points,function(b){var e={};if(b.drilldown&&b.dataLabel){if(d.color==="contrast")e.color=c.getContrast(b.color||a.color);b.dataLabel.attr({"class":"highcharts-drilldown-data-label"}).css(C(d,e))}})});var t,q=function(b){b.call(this);i(this.points,function(a){a.drilldown&&a.graphic&&a.graphic.attr({"class":"highcharts-drilldown-point"}).css({cursor:"pointer"})})};for(t in p)p[t].prototype.supportsDrilldown&&r(p[t].prototype, 18 | "drawTracker",q)}); 19 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/exporting.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | Exporting module 4 | 5 | (c) 2010-2016 Torstein Honsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(f){typeof module==="object"&&module.exports?module.exports=f:f(Highcharts)})(function(f){var s=f.win,j=s.document,B=f.Chart,u=f.addEvent,C=f.removeEvent,D=f.fireEvent,r=f.createElement,t=f.discardElement,w=f.css,l=f.merge,m=f.each,q=f.extend,F=f.splat,G=Math.max,H=f.isTouchDevice,I=f.Renderer.prototype.symbols,z=f.getOptions(),A;q(z.lang,{printChart:"Print chart",downloadPNG:"Download PNG image",downloadJPEG:"Download JPEG image",downloadPDF:"Download PDF document",downloadSVG:"Download SVG vector image", 10 | contextButtonTitle:"Chart context menu"});z.navigation={menuStyle:{border:"1px solid #A0A0A0",background:"#FFFFFF",padding:"5px 0"},menuItemStyle:{padding:"0 10px",background:"none",color:"#303030",fontSize:H?"14px":"11px"},menuItemHoverStyle:{background:"#4572A5",color:"#FFFFFF"},buttonOptions:{symbolFill:"#E0E0E0",symbolSize:14,symbolStroke:"#666",symbolStrokeWidth:3,symbolX:12.5,symbolY:10.5,align:"right",buttonSpacing:3,height:22,theme:{fill:"white",stroke:"none"},verticalAlign:"top",width:24}}; 11 | z.exporting={type:"image/png",url:"https://export.highcharts.com/",printMaxWidth:780,scale:2,buttons:{contextButton:{menuClassName:"highcharts-contextmenu",symbol:"menu",_titleKey:"contextButtonTitle",menuItems:[{textKey:"printChart",onclick:function(){this.print()}},{separator:!0},{textKey:"downloadPNG",onclick:function(){this.exportChart()}},{textKey:"downloadJPEG",onclick:function(){this.exportChart({type:"image/jpeg"})}},{textKey:"downloadPDF",onclick:function(){this.exportChart({type:"application/pdf"})}}, 12 | {textKey:"downloadSVG",onclick:function(){this.exportChart({type:"image/svg+xml"})}}]}}};f.post=function(a,b,e){var c,a=r("form",l({method:"post",action:a,enctype:"multipart/form-data"},e),{display:"none"},j.body);for(c in b)r("input",{type:"hidden",name:c,value:b[c]},null,a);a.submit();t(a)};q(B.prototype,{sanitizeSVG:function(a){return a.replace(/zIndex="[^"]+"/g,"").replace(/isShadow="[^"]+"/g,"").replace(/symbolName="[^"]+"/g,"").replace(/jQuery[0-9]+="[^"]+"/g,"").replace(/url\([^#]+#/g,"url(#").replace(/.*?$/,"").replace(/(fill|stroke)="rgba\(([ 0-9]+,[ 0-9]+,[ 0-9]+),([ 0-9\.]+)\)"/g,'$1="rgb($2)" $1-opacity="$3"').replace(/ /g,"\u00a0").replace(/­/g,"\u00ad").replace(//g,"<$1title>").replace(/height=([^" ]+)/g,'height="$1"').replace(/width=([^" ]+)/g,'width="$1"').replace(/hc-svg-href="([^"]+)">/g,'xlink:href="$1"/>').replace(/ id=([^" >]+)/g, 14 | ' id="$1"').replace(/class=([^" >]+)/g,'class="$1"').replace(/ transform /g," ").replace(/:(path|rect)/g,"$1").replace(/style="([^"]+)"/g,function(a){return a.toLowerCase()})},getChartHTML:function(){return this.container.innerHTML},getSVG:function(a){var b=this,e,c,g,k,h,d=l(b.options,a),n=d.exporting.allowHTML;if(!j.createElementNS)j.createElementNS=function(a,b){return j.createElement(b)};c=r("div",null,{position:"absolute",top:"-9999em",width:b.chartWidth+"px",height:b.chartHeight+"px"},j.body); 15 | g=b.renderTo.style.width;h=b.renderTo.style.height;g=d.exporting.sourceWidth||d.chart.width||/px$/.test(g)&&parseInt(g,10)||600;h=d.exporting.sourceHeight||d.chart.height||/px$/.test(h)&&parseInt(h,10)||400;q(d.chart,{animation:!1,renderTo:c,forExport:!0,renderer:"SVGRenderer",width:g,height:h});d.exporting.enabled=!1;delete d.data;d.series=[];m(b.series,function(a){k=l(a.userOptions,{animation:!1,enableMouseTracking:!1,showCheckbox:!1,visible:a.visible});k.isInternal||d.series.push(k)});a&&m(["xAxis", 16 | "yAxis"],function(b){m(F(a[b]),function(a,c){d[b][c]=l(d[b][c],a)})});e=new f.Chart(d,b.callback);m(["xAxis","yAxis"],function(a){m(b[a],function(b,c){var d=e[a][c],f=b.getExtremes(),g=f.userMin,f=f.userMax;d&&(g!==void 0||f!==void 0)&&d.setExtremes(g,f,!0,!1)})});g=e.getChartHTML();d=null;e.destroy();t(c);if(n&&(c=g.match(/<\/svg>(.*?$)/)))c=''+c[1]+"",g=g.replace("",c+""); 17 | g=this.sanitizeSVG(g);return g=g.replace(/(url\(#highcharts-[0-9]+)"/g,"$1").replace(/"/g,"'")},getSVGForExport:function(a,b){var e=this.options.exporting;return this.getSVG(l({chart:{borderRadius:0}},e.chartOptions,b,{exporting:{sourceWidth:a&&a.sourceWidth||e.sourceWidth,sourceHeight:a&&a.sourceHeight||e.sourceHeight}}))},exportChart:function(a,b){var e=this.getSVGForExport(a,b),a=l(this.options.exporting,a);f.post(a.url,{filename:a.filename||"chart",type:a.type,width:a.width||0,scale:a.scale, 18 | svg:e},a.formAttributes)},print:function(){var a=this,b=a.container,e=[],c=b.parentNode,f=j.body,k=f.childNodes,h=a.options.exporting.printMaxWidth,d,n;if(!a.isPrinting){a.isPrinting=!0;a.pointer.reset(null,0);D(a,"beforePrint");if(n=h&&a.chartWidth>h)d=[a.options.chart.width,void 0,!1],a.setSize(h,void 0,!1);m(k,function(a,b){if(a.nodeType===1)e[b]=a.style.display,a.style.display="none"});f.appendChild(b);s.focus();s.print();setTimeout(function(){c.appendChild(b);m(k,function(a,b){if(a.nodeType=== 19 | 1)a.style.display=e[b]});a.isPrinting=!1;n&&a.setSize.apply(a,d);D(a,"afterPrint")},1E3)}},contextMenu:function(a,b,e,c,f,k,h){var d=this,n=d.options.navigation,l=n.menuItemStyle,o=d.chartWidth,p=d.chartHeight,E="cache-"+a,i=d[E],v=G(f,k),x,y,s,t=function(b){d.pointer.inClass(b.target,a)||y()};if(!i)d[E]=i=r("div",{className:a},{position:"absolute",zIndex:1E3,padding:v+"px"},d.container),x=r("div",null,q({MozBoxShadow:"3px 3px 10px #888",WebkitBoxShadow:"3px 3px 10px #888",boxShadow:"3px 3px 10px #888"}, 20 | n.menuStyle),i),y=function(){w(i,{display:"none"});h&&h.setState(0);d.openMenu=!1},u(i,"mouseleave",function(){s=setTimeout(y,500)}),u(i,"mouseenter",function(){clearTimeout(s)}),u(j,"mouseup",t),u(d,"destroy",function(){C(j,"mouseup",t)}),m(b,function(a){if(a){var b=a.separator?r("hr",null,null,x):r("div",{onmouseover:function(){w(this,n.menuItemHoverStyle)},onmouseout:function(){w(this,l)},onclick:function(b){b&&b.stopPropagation();y();a.onclick&&a.onclick.apply(d,arguments)},innerHTML:a.text|| 21 | d.options.lang[a.textKey]},q({cursor:"pointer"},l),x);d.exportDivElements.push(b)}}),d.exportDivElements.push(x,i),d.exportMenuWidth=i.offsetWidth,d.exportMenuHeight=i.offsetHeight;b={display:"block"};e+d.exportMenuWidth>o?b.right=o-e-f-v+"px":b.left=e-v+"px";c+k+d.exportMenuHeight>p&&h.alignOptions.verticalAlign!=="top"?b.bottom=p-c-v+"px":b.top=c+k-v+"px";w(i,b);d.openMenu=!0},addButton:function(a){var b=this,e=b.renderer,c=l(b.options.navigation.buttonOptions,a),g=c.onclick,k=c.menuItems,h,d,n= 22 | {stroke:c.symbolStroke,fill:c.symbolFill},j=c.symbolSize||12;if(!b.btnCount)b.btnCount=0;if(!b.exportDivElements)b.exportDivElements=[],b.exportSVGElements=[];if(c.enabled!==!1){var o=c.theme,p=o.states,m=p&&p.hover,p=p&&p.select,i;delete o.states;g?i=function(a){a.stopPropagation();g.call(b,a)}:k&&(i=function(){b.contextMenu(d.menuClassName,k,d.translateX,d.translateY,d.width,d.height,d);d.setState(2)});c.text&&c.symbol?o.paddingLeft=f.pick(o.paddingLeft,25):c.text||q(o,{width:c.width,height:c.height, 23 | padding:0});d=e.button(c.text,0,0,i,o,m,p).attr({title:b.options.lang[c._titleKey],"stroke-linecap":"round",zIndex:3});d.menuClassName=a.menuClassName||"highcharts-menu-"+b.btnCount++;c.symbol&&(h=e.symbol(c.symbol,c.symbolX-j/2,c.symbolY-j/2,j,j).attr(q(n,{"stroke-width":c.symbolStrokeWidth||1,zIndex:1})).add(d));d.add().align(q(c,{width:d.width,x:f.pick(c.x,A)}),!0,"spacingBox");A+=(d.width+c.buttonSpacing)*(c.align==="right"?-1:1);b.exportSVGElements.push(d,h)}},destroyExport:function(a){var a= 24 | a.target,b,e;for(b=0;bv||k===C?u:u+(s-u)*(1-(i-a)/(k-C))};this.getX=function(i,a){return g+(a?-1:1)*(t(e?2*o-i:i)/ 11 | 2+c.dataLabels.distance)};this.center=[g,o,k];this.centerX=g;B(a,function(a){if(!f||a.visible!==!1)b+=a.y});B(a,function(a){m=null;z=b?a.y/b:0;l=o-k/2+n*k;h=l+z*k;j=t(l);A=g-j/2;D=A+j;j=t(h);q=g-j/2;w=q+j;l>v?(A=q=g-u/2,D=w=g+u/2):h>v&&(m=h,j=t(v),q=g-j/2,w=q+j,h=v);e&&(l=2*o-l,h=2*o-h,m=m?2*o-m:null);y=["M",A,l,"L",D,l,w,h];m&&y.push(w,m,q,m);y.push(q,h,"Z");a.shapeType="path";a.shapeArgs={d:y};a.percentage=z*100;a.plotX=g;a.plotY=(l+(m||h))/2;a.tooltipPos=[g,a.plotY];a.slice=E;a.half=x;if(!f||a.visible!== 12 | !1)n+=z})},drawPoints:function(){var a=this,b=a.chart.renderer,d,c,e;B(a.data,function(f){e=f.graphic;c=f.shapeArgs;d=f.pointAttr[f.selected?"select":""];e?e.attr(d).animate(c):f.graphic=b.path(c).attr(d).add(a.group)})},sortByAngle:function(a){a.sort(function(a,b){return a.plotY-b.plotY})},drawDataLabels:function(){var a=this.data,b=this.options.dataLabels.distance,d,c,e,f=a.length,p,n;for(this.center[2]-=2*b;f--;)e=a[f],c=(d=e.half)?1:-1,n=e.plotY,p=this.getX(n,d),e.labelPos=[0,n,p+(b-5)*c,n,p+ 13 | b*c,n,d?"right":"left",0];s.pie.prototype.drawDataLabels.call(this)}});r.plotOptions.pyramid=b.merge(r.plotOptions.funnel,{neckWidth:"0%",neckHeight:"0%",reversed:!0});b.seriesTypes.pyramid=b.extendClass(b.seriesTypes.funnel,{type:"pyramid"})}); 14 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/funnel.src.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Highcharts funnel module 4 | * 5 | * (c) 2010-2016 Torstein Honsi 6 | * 7 | * License: www.highcharts.com/license 8 | */ 9 | /* eslint indent:0 */ 10 | (function (factory) { 11 | if (typeof module === 'object' && module.exports) { 12 | module.exports = factory; 13 | } else { 14 | factory(Highcharts); 15 | } 16 | }(function (Highcharts) { 17 | 18 | 'use strict'; 19 | 20 | // create shortcuts 21 | var defaultOptions = Highcharts.getOptions(), 22 | defaultPlotOptions = defaultOptions.plotOptions, 23 | seriesTypes = Highcharts.seriesTypes, 24 | merge = Highcharts.merge, 25 | noop = function () {}, 26 | each = Highcharts.each; 27 | 28 | // set default options 29 | defaultPlotOptions.funnel = merge(defaultPlotOptions.pie, { 30 | animation: false, 31 | center: ['50%', '50%'], 32 | width: '90%', 33 | neckWidth: '30%', 34 | height: '100%', 35 | neckHeight: '25%', 36 | reversed: false, 37 | dataLabels: { 38 | //position: 'right', 39 | connectorWidth: 1, 40 | connectorColor: '#606060' 41 | }, 42 | size: true, // to avoid adapting to data label size in Pie.drawDataLabels 43 | states: { 44 | select: { 45 | color: '#C0C0C0', 46 | borderColor: '#000000', 47 | shadow: false 48 | } 49 | } 50 | }); 51 | 52 | 53 | seriesTypes.funnel = Highcharts.extendClass(seriesTypes.pie, { 54 | 55 | type: 'funnel', 56 | animate: noop, 57 | 58 | /** 59 | * Overrides the pie translate method 60 | */ 61 | translate: function () { 62 | 63 | var 64 | // Get positions - either an integer or a percentage string must be given 65 | getLength = function (length, relativeTo) { 66 | return (/%$/).test(length) ? 67 | relativeTo * parseInt(length, 10) / 100 : 68 | parseInt(length, 10); 69 | }, 70 | 71 | sum = 0, 72 | series = this, 73 | chart = series.chart, 74 | options = series.options, 75 | reversed = options.reversed, 76 | ignoreHiddenPoint = options.ignoreHiddenPoint, 77 | plotWidth = chart.plotWidth, 78 | plotHeight = chart.plotHeight, 79 | cumulative = 0, // start at top 80 | center = options.center, 81 | centerX = getLength(center[0], plotWidth), 82 | centerY = getLength(center[1], plotHeight), 83 | width = getLength(options.width, plotWidth), 84 | tempWidth, 85 | getWidthAt, 86 | height = getLength(options.height, plotHeight), 87 | neckWidth = getLength(options.neckWidth, plotWidth), 88 | neckHeight = getLength(options.neckHeight, plotHeight), 89 | neckY = (centerY - height / 2) + height - neckHeight, 90 | data = series.data, 91 | path, 92 | fraction, 93 | half = options.dataLabels.position === 'left' ? 1 : 0, 94 | 95 | x1, 96 | y1, 97 | x2, 98 | x3, 99 | y3, 100 | x4, 101 | y5; 102 | 103 | // Return the width at a specific y coordinate 104 | series.getWidthAt = getWidthAt = function (y) { 105 | var top = (centerY - height / 2); 106 | 107 | return y > neckY || height === neckHeight ? 108 | neckWidth : 109 | neckWidth + (width - neckWidth) * (1 - (y - top) / (height - neckHeight)); 110 | }; 111 | series.getX = function (y, half) { 112 | return centerX + (half ? -1 : 1) * ((getWidthAt(reversed ? 2 * centerY - y : y) / 2) + options.dataLabels.distance); 113 | }; 114 | 115 | // Expose 116 | series.center = [centerX, centerY, height]; 117 | series.centerX = centerX; 118 | 119 | /* 120 | * Individual point coordinate naming: 121 | * 122 | * x1,y1 _________________ x2,y1 123 | * \ / 124 | * \ / 125 | * \ / 126 | * \ / 127 | * \ / 128 | * x3,y3 _________ x4,y3 129 | * 130 | * Additional for the base of the neck: 131 | * 132 | * | | 133 | * | | 134 | * | | 135 | * x3,y5 _________ x4,y5 136 | */ 137 | 138 | 139 | 140 | 141 | // get the total sum 142 | each(data, function (point) { 143 | if (!ignoreHiddenPoint || point.visible !== false) { 144 | sum += point.y; 145 | } 146 | }); 147 | 148 | each(data, function (point) { 149 | // set start and end positions 150 | y5 = null; 151 | fraction = sum ? point.y / sum : 0; 152 | y1 = centerY - height / 2 + cumulative * height; 153 | y3 = y1 + fraction * height; 154 | //tempWidth = neckWidth + (width - neckWidth) * ((height - neckHeight - y1) / (height - neckHeight)); 155 | tempWidth = getWidthAt(y1); 156 | x1 = centerX - tempWidth / 2; 157 | x2 = x1 + tempWidth; 158 | tempWidth = getWidthAt(y3); 159 | x3 = centerX - tempWidth / 2; 160 | x4 = x3 + tempWidth; 161 | 162 | // the entire point is within the neck 163 | if (y1 > neckY) { 164 | x1 = x3 = centerX - neckWidth / 2; 165 | x2 = x4 = centerX + neckWidth / 2; 166 | 167 | // the base of the neck 168 | } else if (y3 > neckY) { 169 | y5 = y3; 170 | 171 | tempWidth = getWidthAt(neckY); 172 | x3 = centerX - tempWidth / 2; 173 | x4 = x3 + tempWidth; 174 | 175 | y3 = neckY; 176 | } 177 | 178 | if (reversed) { 179 | y1 = 2 * centerY - y1; 180 | y3 = 2 * centerY - y3; 181 | y5 = (y5 ? 2 * centerY - y5 : null); 182 | } 183 | // save the path 184 | path = [ 185 | 'M', 186 | x1, y1, 187 | 'L', 188 | x2, y1, 189 | x4, y3 190 | ]; 191 | if (y5) { 192 | path.push(x4, y5, x3, y5); 193 | } 194 | path.push(x3, y3, 'Z'); 195 | 196 | // prepare for using shared dr 197 | point.shapeType = 'path'; 198 | point.shapeArgs = { d: path }; 199 | 200 | 201 | // for tooltips and data labels 202 | point.percentage = fraction * 100; 203 | point.plotX = centerX; 204 | point.plotY = (y1 + (y5 || y3)) / 2; 205 | 206 | // Placement of tooltips and data labels 207 | point.tooltipPos = [ 208 | centerX, 209 | point.plotY 210 | ]; 211 | 212 | // Slice is a noop on funnel points 213 | point.slice = noop; 214 | 215 | // Mimicking pie data label placement logic 216 | point.half = half; 217 | 218 | if (!ignoreHiddenPoint || point.visible !== false) { 219 | cumulative += fraction; 220 | } 221 | }); 222 | }, 223 | /** 224 | * Draw a single point (wedge) 225 | * @param {Object} point The point object 226 | * @param {Object} color The color of the point 227 | * @param {Number} brightness The brightness relative to the color 228 | */ 229 | drawPoints: function () { 230 | var series = this, 231 | chart = series.chart, 232 | renderer = chart.renderer, 233 | pointAttr, 234 | shapeArgs, 235 | graphic; 236 | 237 | each(series.data, function (point) { 238 | graphic = point.graphic; 239 | shapeArgs = point.shapeArgs; 240 | 241 | pointAttr = point.pointAttr[point.selected ? 'select' : '']; 242 | 243 | if (!graphic) { // Create the shapes 244 | point.graphic = renderer.path(shapeArgs) 245 | .attr(pointAttr) 246 | .add(series.group); 247 | 248 | } else { // Update the shapes 249 | graphic.attr(pointAttr).animate(shapeArgs); 250 | } 251 | }); 252 | }, 253 | 254 | /** 255 | * Funnel items don't have angles (#2289) 256 | */ 257 | sortByAngle: function (points) { 258 | points.sort(function (a, b) { 259 | return a.plotY - b.plotY; 260 | }); 261 | }, 262 | 263 | /** 264 | * Extend the pie data label method 265 | */ 266 | drawDataLabels: function () { 267 | var data = this.data, 268 | labelDistance = this.options.dataLabels.distance, 269 | leftSide, 270 | sign, 271 | point, 272 | i = data.length, 273 | x, 274 | y; 275 | 276 | // In the original pie label anticollision logic, the slots are distributed 277 | // from one labelDistance above to one labelDistance below the pie. In funnels 278 | // we don't want this. 279 | this.center[2] -= 2 * labelDistance; 280 | 281 | // Set the label position array for each point. 282 | while (i--) { 283 | point = data[i]; 284 | leftSide = point.half; 285 | sign = leftSide ? 1 : -1; 286 | y = point.plotY; 287 | x = this.getX(y, leftSide); 288 | 289 | // set the anchor point for data labels 290 | point.labelPos = [ 291 | 0, // first break of connector 292 | y, // a/a 293 | x + (labelDistance - 5) * sign, // second break, right outside point shape 294 | y, // a/a 295 | x + labelDistance * sign, // landing point for connector 296 | y, // a/a 297 | leftSide ? 'right' : 'left', // alignment 298 | 0 // center angle 299 | ]; 300 | } 301 | 302 | seriesTypes.pie.prototype.drawDataLabels.call(this); 303 | } 304 | 305 | }); 306 | 307 | /** 308 | * Pyramid series type. 309 | * A pyramid series is a special type of funnel, without neck and reversed by default. 310 | */ 311 | defaultOptions.plotOptions.pyramid = Highcharts.merge(defaultOptions.plotOptions.funnel, { 312 | neckWidth: '0%', 313 | neckHeight: '0%', 314 | reversed: true 315 | }); 316 | Highcharts.seriesTypes.pyramid = Highcharts.extendClass(Highcharts.seriesTypes.funnel, { 317 | type: 'pyramid' 318 | }); 319 | 320 | })); 321 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/heatmap.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | 4 | (c) 2011-2016 Torstein Honsi 5 | 6 | License: www.highcharts.com/license 7 | */ 8 | (function(d){typeof module==="object"&&module.exports?module.exports=d:d(Highcharts)})(function(d){var m=d.Axis,q=d.Chart,i=d.Color,x=d.Legend,s=d.LegendSymbolMixin,t=d.Series,y=d.Point,u=d.getOptions(),h=d.each,r=d.extend,v=d.extendClass,z=d.isNumber,j=d.merge,k=d.pick,o=d.seriesTypes,w=d.wrap,n=function(){},p=d.ColorAxis=function(){this.isColorAxis=!0;this.init.apply(this,arguments)};r(p.prototype,m.prototype);r(p.prototype,{defaultColorAxisOptions:{lineWidth:0,minPadding:0,maxPadding:0,gridLineWidth:1, 9 | tickPixelInterval:72,startOnTick:!0,endOnTick:!0,offset:0,marker:{animation:{duration:50},color:"gray",width:0.01},labels:{overflow:"justify"},minColor:"#EFEFFF",maxColor:"#003875",tickLength:5},init:function(a,b){var c=a.options.legend.layout!=="vertical",f;f=j(this.defaultColorAxisOptions,{side:c?2:1,reversed:!c},b,{opposite:!c,showEmpty:!1,title:null,isColor:!0});m.prototype.init.call(this,a,f);b.dataClasses&&this.initDataClasses(b);this.initStops(b);this.horiz=c;this.zoomEnabled=!1},tweenColors:function(a, 10 | b,c){var f;!b.rgba.length||!a.rgba.length?a=b.input||"none":(a=a.rgba,b=b.rgba,f=b[3]!==1||a[3]!==1,a=(f?"rgba(":"rgb(")+Math.round(b[0]+(a[0]-b[0])*(1-c))+","+Math.round(b[1]+(a[1]-b[1])*(1-c))+","+Math.round(b[2]+(a[2]-b[2])*(1-c))+(f?","+(b[3]+(a[3]-b[3])*(1-c)):"")+")");return a},initDataClasses:function(a){var b=this,c=this.chart,f,e=0,l=this.options,g=a.dataClasses.length;this.dataClasses=f=[];this.legendItems=[];h(a.dataClasses,function(a,d){var h,a=j(a);f.push(a);if(!a.color)l.dataClassColor=== 11 | "category"?(h=c.options.colors,a.color=h[e++],e===h.length&&(e=0)):a.color=b.tweenColors(i(l.minColor),i(l.maxColor),g<2?0.5:d/(g-1))})},initStops:function(a){this.stops=a.stops||[[0,this.options.minColor],[1,this.options.maxColor]];h(this.stops,function(a){a.color=i(a[1])})},setOptions:function(a){m.prototype.setOptions.call(this,a);this.options.crosshair=this.options.marker;this.coll="colorAxis"},setAxisSize:function(){var a=this.legendSymbol,b=this.chart,c,f,e;if(a)this.left=c=a.attr("x"),this.top= 12 | f=a.attr("y"),this.width=e=a.attr("width"),this.height=a=a.attr("height"),this.right=b.chartWidth-c-e,this.bottom=b.chartHeight-f-a,this.len=this.horiz?e:a,this.pos=this.horiz?c:f},toColor:function(a,b){var c,f=this.stops,e,l=this.dataClasses,g,d;if(l)for(d=l.length;d--;){if(g=l[d],e=g.from,f=g.to,(e===void 0||a>=e)&&(f===void 0||a<=f)){c=g.color;if(b)b.dataClass=d;break}}else{this.isLog&&(a=this.val2lin(a));c=1-(this.max-a)/(this.max-this.min||1);for(d=f.length;d--;)if(c>f[d][0])break;e=f[d]||f[d+ 13 | 1];f=f[d+1]||e;c=1-(f[0]-c)/(f[0]-e[0]||1);c=this.tweenColors(e.color,f.color,c)}return c},getOffset:function(){var a=this.legendGroup,b=this.chart.axisOffset[this.side];if(a){this.axisParent=a;m.prototype.getOffset.call(this);if(!this.added)this.added=!0,this.labelLeft=0,this.labelRight=this.width;this.chart.axisOffset[this.side]=b}},setLegendColor:function(){var a,b=this.options,c=this.reversed;a=c?1:0;c=c?0:1;a=this.horiz?[a,0,c,0]:[0,c,0,a];this.legendColor={linearGradient:{x1:a[0],y1:a[1],x2:a[2], 14 | y2:a[3]},stops:b.stops||[[0,b.minColor],[1,b.maxColor]]}},drawLegendSymbol:function(a,b){var c=a.padding,f=a.options,e=this.horiz,d=k(f.symbolWidth,e?200:12),g=k(f.symbolHeight,e?12:200),h=k(f.labelPadding,e?16:30),f=k(f.itemDistance,10);this.setLegendColor();b.legendSymbol=this.chart.renderer.rect(0,a.baseline-11,d,g).attr({zIndex:1}).add(b.legendGroup);this.legendItemWidth=d+c+(e?f:h);this.legendItemHeight=g+c+(e?h:0)},setState:n,visible:!0,setVisible:n,getSeriesExtremes:function(){var a;if(this.series.length)a= 15 | this.series[0],this.dataMin=a.valueMin,this.dataMax=a.valueMax},drawCrosshair:function(a,b){var c=b&&b.plotX,f=b&&b.plotY,e,d=this.pos,g=this.len;if(b)e=this.toPixels(b[b.series.colorKey]),ed+g&&(e=d+g+2),b.plotX=e,b.plotY=this.len-e,m.prototype.drawCrosshair.call(this,a,b),b.plotX=c,b.plotY=f,this.cross&&this.cross.attr({fill:this.crosshair.color}).add(this.legendGroup)},getPlotLinePath:function(a,b,c,f,e){return z(e)?this.horiz?["M",e-4,this.top-6,"L",e+4,this.top-6,e,this.top,"Z"]:["M", 16 | this.left,e,"L",this.left-6,e+6,this.left-6,e-6,"Z"]:m.prototype.getPlotLinePath.call(this,a,b,c,f)},update:function(a,b){var c=this.chart,f=c.legend;h(this.series,function(a){a.isDirtyData=!0});if(a.dataClasses&&f.allItems)h(f.allItems,function(a){a.isDataClass&&a.legendGroup.destroy()}),c.isDirtyLegend=!0;c.options[this.coll]=j(this.userOptions,a);m.prototype.update.call(this,a,b);this.legendItem&&(this.setLegendColor(),f.colorizeItem(this,!0))},getDataClassLegendSymbols:function(){var a=this,b= 17 | this.chart,c=this.legendItems,f=b.options.legend,e=f.valueDecimals,l=f.valueSuffix||"",g;c.length||h(this.dataClasses,function(f,m){var i=!0,j=f.from,k=f.to;g="";j===void 0?g="< ":k===void 0&&(g="> ");j!==void 0&&(g+=d.numberFormat(j,e)+l);j!==void 0&&k!==void 0&&(g+=" - ");k!==void 0&&(g+=d.numberFormat(k,e)+l);c.push(r({chart:b,name:g,options:{},drawLegendSymbol:s.drawRectangle,visible:!0,setState:n,isDataClass:!0,setVisible:function(){i=this.visible=!i;h(a.series,function(a){h(a.points,function(a){a.dataClass=== 18 | m&&a.setVisible(i)})});b.legend.colorizeItem(this,i)}},f))});return c},name:""});h(["fill","stroke"],function(a){d.Fx.prototype[a+"Setter"]=function(){this.elem.attr(a,p.prototype.tweenColors(i(this.start),i(this.end),this.pos))}});w(q.prototype,"getAxes",function(a){var b=this.options.colorAxis;a.call(this);this.colorAxis=[];b&&new p(this,b)});w(x.prototype,"getAllItems",function(a){var b=[],c=this.chart.colorAxis[0];c&&(c.options.dataClasses?b=b.concat(c.getDataClassLegendSymbols()):b.push(c),h(c.series, 19 | function(a){a.options.showInLegend=!1}));return b.concat(a.call(this))});q={pointAttrToOptions:{stroke:"borderColor","stroke-width":"borderWidth",fill:"color",dashstyle:"dashStyle"},pointArrayMap:["value"],axisTypes:["xAxis","yAxis","colorAxis"],optionalAxis:"colorAxis",trackerGroups:["group","markerGroup","dataLabelsGroup"],getSymbol:n,parallelArrays:["x","y","value"],colorKey:"value",translateColors:function(){var a=this,b=this.options.nullColor,c=this.colorAxis,f=this.colorKey;h(this.data,function(e){var d= 20 | e[f];if(d=e.options.color||(d===null?b:c&&d!==void 0?c.toColor(d,e):e.color||a.color))e.color=d})}};u.plotOptions.heatmap=j(u.plotOptions.scatter,{animation:!1,borderWidth:0,nullColor:"#F8F8F8",dataLabels:{formatter:function(){return this.point.value},inside:!0,verticalAlign:"middle",crop:!1,overflow:!1,padding:0},marker:null,pointRange:null,tooltip:{pointFormat:"{point.x}, {point.y}: {point.value}
"},states:{normal:{animation:!0},hover:{halo:!1,brightness:0.2}}});o.heatmap=v(o.scatter,j(q,{type:"heatmap", 21 | pointArrayMap:["y","value"],hasPointSpecificOptions:!0,pointClass:v(y,{setVisible:function(a){var b=this,c=a?"show":"hide";h(["graphic","dataLabel"],function(a){if(b[a])b[a][c]()})}}),supportsDrilldown:!0,getExtremesFromAll:!0,directTouch:!0,init:function(){var a;o.scatter.prototype.init.apply(this,arguments);a=this.options;a.pointRange=k(a.pointRange,a.colsize||1);this.yAxis.axisPointRange=a.rowsize||1},translate:function(){var a=this.options,b=this.xAxis,c=this.yAxis,f=function(a,b,c){return Math.min(Math.max(b, 22 | a),c)};this.generatePoints();h(this.points,function(e){var d=(a.colsize||1)/2,g=(a.rowsize||1)/2,h=f(Math.round(b.len-b.translate(e.x-d,0,1,0,1)),-b.len,2*b.len),d=f(Math.round(b.len-b.translate(e.x+d,0,1,0,1)),-b.len,2*b.len),i=f(Math.round(c.translate(e.y-g,0,1,0,1)),-c.len,2*c.len),g=f(Math.round(c.translate(e.y+g,0,1,0,1)),-c.len,2*c.len);e.plotX=e.clientX=(h+d)/2;e.plotY=(i+g)/2;e.shapeType="rect";e.shapeArgs={x:Math.min(h,d),y:Math.min(i,g),width:Math.abs(d-h),height:Math.abs(g-i)}});this.translateColors(); 23 | this.chart.hasRendered&&h(this.points,function(a){a.shapeArgs.fill=a.options.color||a.color})},drawPoints:o.column.prototype.drawPoints,animate:n,getBox:n,drawLegendSymbol:s.drawRectangle,alignDataLabel:o.column.prototype.alignDataLabel,getExtremes:function(){t.prototype.getExtremes.call(this,this.valueData);this.valueMin=this.dataMin;this.valueMax=this.dataMax;t.prototype.getExtremes.call(this)}}))}); 24 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/no-data-to-display.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | Plugin for displaying a message when there is no data visible in chart. 4 | 5 | (c) 2010-2016 Highsoft AS 6 | Author: Oystein Moseng 7 | 8 | License: www.highcharts.com/license 9 | */ 10 | (function(a){typeof module==="object"&&module.exports?module.exports=a:a(Highcharts)})(function(a){function h(){return!!this.points.length}function d(){this.hasData()?this.hideNoData():this.showNoData()}var e=a.seriesTypes,c=a.Chart.prototype,f=a.getOptions(),g=a.extend,i=a.each;g(f.lang,{noData:"No data to display"});f.noData={position:{x:0,y:0,align:"center",verticalAlign:"middle"},attr:{},style:{fontWeight:"bold",fontSize:"12px",color:"#60606a"}};i(["pie","gauge","waterfall","bubble","treemap"], 11 | function(b){if(e[b])e[b].prototype.hasData=h});a.Series.prototype.hasData=function(){return this.visible&&this.dataMax!==void 0&&this.dataMin!==void 0};c.showNoData=function(b){var a=this.options,b=b||a.lang.noData,a=a.noData;if(!this.noDataLabel)this.noDataLabel=this.renderer.label(b,0,0,null,null,null,a.useHTML,null,"no-data").attr(a.attr).css(a.style).add(),this.noDataLabel.align(g(this.noDataLabel.getBBox(),a.position),!1,"plotBox")};c.hideNoData=function(){if(this.noDataLabel)this.noDataLabel= 12 | this.noDataLabel.destroy()};c.hasData=function(){for(var a=this.series,c=a.length;c--;)if(a[c].hasData()&&!a[c].options.isInternal)return!0;return!1};c.callbacks.push(function(b){a.addEvent(b,"load",d);a.addEvent(b,"redraw",d)})}); 13 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/no-data-to-display.src.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Highcharts JS v4.2.6 (2016-08-02) 3 | * Plugin for displaying a message when there is no data visible in chart. 4 | * 5 | * (c) 2010-2016 Highsoft AS 6 | * Author: Oystein Moseng 7 | * 8 | * License: www.highcharts.com/license 9 | */ 10 | 11 | (function (factory) { 12 | if (typeof module === 'object' && module.exports) { 13 | module.exports = factory; 14 | } else { 15 | factory(Highcharts); 16 | } 17 | }(function (H) { 18 | 19 | var seriesTypes = H.seriesTypes, 20 | chartPrototype = H.Chart.prototype, 21 | defaultOptions = H.getOptions(), 22 | extend = H.extend, 23 | each = H.each; 24 | 25 | // Add language option 26 | extend(defaultOptions.lang, { 27 | noData: 'No data to display' 28 | }); 29 | 30 | // Add default display options for message 31 | defaultOptions.noData = { 32 | position: { 33 | x: 0, 34 | y: 0, 35 | align: 'center', 36 | verticalAlign: 'middle' 37 | }, 38 | attr: { 39 | }, 40 | style: { 41 | fontWeight: 'bold', 42 | fontSize: '12px', 43 | color: '#60606a' 44 | } 45 | // useHTML: false 46 | }; 47 | 48 | /** 49 | * Define hasData functions for series. These return true if there are data points on this series within the plot area 50 | */ 51 | function hasDataPie() { 52 | return !!this.points.length; /* != 0 */ 53 | } 54 | 55 | each(['pie', 'gauge', 'waterfall', 'bubble', 'treemap'], function (type) { 56 | if (seriesTypes[type]) { 57 | seriesTypes[type].prototype.hasData = hasDataPie; 58 | } 59 | }); 60 | 61 | H.Series.prototype.hasData = function () { 62 | return this.visible && this.dataMax !== undefined && this.dataMin !== undefined; // #3703 63 | }; 64 | 65 | /** 66 | * Display a no-data message. 67 | * 68 | * @param {String} str An optional message to show in place of the default one 69 | */ 70 | chartPrototype.showNoData = function (str) { 71 | var chart = this, 72 | options = chart.options, 73 | text = str || options.lang.noData, 74 | noDataOptions = options.noData; 75 | 76 | if (!chart.noDataLabel) { 77 | chart.noDataLabel = chart.renderer 78 | .label( 79 | text, 80 | 0, 81 | 0, 82 | null, 83 | null, 84 | null, 85 | noDataOptions.useHTML, 86 | null, 87 | 'no-data' 88 | ) 89 | .attr(noDataOptions.attr) 90 | .css(noDataOptions.style) 91 | .add(); 92 | chart.noDataLabel.align(extend(chart.noDataLabel.getBBox(), noDataOptions.position), false, 'plotBox'); 93 | } 94 | }; 95 | 96 | /** 97 | * Hide no-data message 98 | */ 99 | chartPrototype.hideNoData = function () { 100 | var chart = this; 101 | if (chart.noDataLabel) { 102 | chart.noDataLabel = chart.noDataLabel.destroy(); 103 | } 104 | }; 105 | 106 | /** 107 | * Returns true if there are data points within the plot area now 108 | */ 109 | chartPrototype.hasData = function () { 110 | var chart = this, 111 | series = chart.series, 112 | i = series.length; 113 | 114 | while (i--) { 115 | if (series[i].hasData() && !series[i].options.isInternal) { 116 | return true; 117 | } 118 | } 119 | 120 | return false; 121 | }; 122 | 123 | /** 124 | * Show no-data message if there is no data in sight. Otherwise, hide it. 125 | */ 126 | function handleNoData() { 127 | var chart = this; 128 | if (chart.hasData()) { 129 | chart.hideNoData(); 130 | } else { 131 | chart.showNoData(); 132 | } 133 | } 134 | 135 | /** 136 | * Add event listener to handle automatic display of no-data message 137 | */ 138 | chartPrototype.callbacks.push(function (chart) { 139 | H.addEvent(chart, 'load', handleNoData); 140 | H.addEvent(chart, 'redraw', handleNoData); 141 | }); 142 | 143 | })); 144 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/offline-exporting.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | Client side exporting module 4 | 5 | (c) 2015 Torstein Honsi / Oystein Moseng 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(a){typeof module==="object"&&module.exports?module.exports=a:a(Highcharts)})(function(a){function v(g,a){var c=m.getElementsByTagName("head")[0],b=m.createElement("script");b.type="text/javascript";b.src=g;b.onload=a;c.appendChild(b)}var j=a.win,k=j.navigator,m=j.document,r=j.URL||j.webkitURL||j,s=/Edge\/|Trident\/|MSIE /.test(k.userAgent),w=s?150:0;a.CanVGRenderer={};a.downloadURL=function(g,a){var c=m.createElement("a"),b;if(k.msSaveOrOpenBlob)k.msSaveOrOpenBlob(g,a);else if(c.download!== 10 | void 0)c.href=g,c.download=a,c.target="_blank",m.body.appendChild(c),c.click(),m.body.removeChild(c);else try{if(b=j.open(g,"chart"),b===void 0||b===null)throw"Failed to open window";}catch(i){j.location.href=g}};a.svgToDataUrl=function(a){var h=k.userAgent.indexOf("WebKit")>-1&&k.userAgent.indexOf("Chrome")<0;try{if(!h&&k.userAgent.toLowerCase().indexOf("firefox")<0)return r.createObjectURL(new j.Blob([a],{type:"image/svg+xml;charset-utf-16"}))}catch(c){}return"data:image/svg+xml;charset=UTF-8,"+ 11 | encodeURIComponent(a)};a.imageToDataUrl=function(a,h,c,b,i,d,l,f,n){var e=new j.Image,k,o=function(){setTimeout(function(){var d=m.createElement("canvas"),o=d.getContext&&d.getContext("2d"),f;try{if(o){d.height=e.height*b;d.width=e.width*b;o.drawImage(e,0,0,d.width,d.height);try{f=d.toDataURL(h),i(f,h,c,b)}catch(j){k(a,h,c,b)}}else l(a,h,c,b)}finally{n&&n(a,h,c,b)}},w)},q=function(){f(a,h,c,b);n&&n(a,h,c,b)};k=function(){e=new j.Image;k=d;e.crossOrigin="Anonymous";e.onload=o;e.onerror=q;e.src=a}; 12 | e.onload=o;e.onerror=q;e.src=a};a.downloadSVGLocal=function(g,h,c,b,i,d){var l,f,n=!0,e;if(c==="image/svg+xml")try{k.msSaveOrOpenBlob?(f=new MSBlobBuilder,f.append(g),l=f.getBlob("image/svg+xml")):l=a.svgToDataUrl(g),a.downloadURL(l,h),d&&d()}catch(p){i()}else l=a.svgToDataUrl(g),e=function(){try{r.revokeObjectURL(l)}catch(a){}},a.imageToDataUrl(l,c,{},b,function(b){try{a.downloadURL(b,h),d&&d()}catch(c){i()}},function(){var f=m.createElement("canvas"),l=f.getContext("2d"),t=g.match(/^]*width\s*=\s*\"?(\d+)\"?[^>]*>/)[1]* 13 | b,p=g.match(/^]*height\s*=\s*\"?(\d+)\"?[^>]*>/)[1]*b,u=function(){l.drawSvg(g,0,0,t,p);try{a.downloadURL(k.msSaveOrOpenBlob?f.msToBlob():f.toDataURL(c),h),d&&d()}catch(b){i()}finally{e()}};f.width=t;f.height=p;j.canvg?u():(n=!0,v(a.getOptions().global.canvasToolsURL,function(){u()}))},i,i,function(){n&&e()})};a.Chart.prototype.getSVGForLocalExport=function(g,h,c,b){var i=this,d,l=0,f,j,e,k,m=function(a,c,e){++l;e.imageElement.setAttributeNS("http://www.w3.org/1999/xlink","href",a);l===d.length&& 14 | b(i.sanitizeSVG(f.innerHTML))};a.wrap(a.Chart.prototype,"getChartHTML",function(a){f=this.container.cloneNode(!0);return a.apply(this,Array.prototype.slice.call(arguments,1))});i.getSVGForExport(g,h);d=f.getElementsByTagName("image");try{if(d.length)for(e=0,k=d.length;e -1 && nav.userAgent.indexOf('Chrome') < 0; // Webkit and not chrome 82 | try { 83 | // Safari requires data URI since it doesn't allow navigation to blob URLs 84 | // Firefox has an issue with Blobs and internal references, leading to gradients not working using Blobs (#4550) 85 | if (!webKit && nav.userAgent.toLowerCase().indexOf('firefox') < 0) { 86 | return domurl.createObjectURL(new win.Blob([svg], { type: 'image/svg+xml;charset-utf-16' })); 87 | } 88 | } catch (e) { 89 | // Ignore 90 | } 91 | return 'data:image/svg+xml;charset=UTF-8,' + encodeURIComponent(svg); 92 | }; 93 | 94 | // Get data:URL from image URL 95 | // Pass in callbacks to handle results. finallyCallback is always called at the end of the process. Supplying this callback is optional. 96 | // All callbacks receive four arguments: imageURL, imageType, callbackArgs and scale. callbackArgs is used only by callbacks and can contain whatever. 97 | Highcharts.imageToDataUrl = function (imageURL, imageType, callbackArgs, scale, successCallback, taintedCallback, noCanvasSupportCallback, failedLoadCallback, finallyCallback) { 98 | var img = new win.Image(), 99 | taintedHandler, 100 | loadHandler = function () { 101 | setTimeout(function () { 102 | var canvas = doc.createElement('canvas'), 103 | ctx = canvas.getContext && canvas.getContext('2d'), 104 | dataURL; 105 | try { 106 | if (!ctx) { 107 | noCanvasSupportCallback(imageURL, imageType, callbackArgs, scale); 108 | } else { 109 | canvas.height = img.height * scale; 110 | canvas.width = img.width * scale; 111 | ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 112 | 113 | // Now we try to get the contents of the canvas. 114 | try { 115 | dataURL = canvas.toDataURL(imageType); 116 | successCallback(dataURL, imageType, callbackArgs, scale); 117 | } catch (e) { 118 | taintedHandler(imageURL, imageType, callbackArgs, scale); 119 | } 120 | } 121 | } finally { 122 | if (finallyCallback) { 123 | finallyCallback(imageURL, imageType, callbackArgs, scale); 124 | } 125 | } 126 | }, loadEventDeferDelay); // IE bug where image is not always ready despite calling load event. 127 | }, 128 | // Image load failed (e.g. invalid URL) 129 | errorHandler = function () { 130 | failedLoadCallback(imageURL, imageType, callbackArgs, scale); 131 | if (finallyCallback) { 132 | finallyCallback(imageURL, imageType, callbackArgs, scale); 133 | } 134 | }; 135 | 136 | // This is called on load if the image drawing to canvas failed with a security error. 137 | // We retry the drawing with crossOrigin set to Anonymous. 138 | taintedHandler = function () { 139 | img = new win.Image(); 140 | taintedHandler = taintedCallback; 141 | img.crossOrigin = 'Anonymous'; // Must be set prior to loading image source 142 | img.onload = loadHandler; 143 | img.onerror = errorHandler; 144 | img.src = imageURL; 145 | }; 146 | 147 | img.onload = loadHandler; 148 | img.onerror = errorHandler; 149 | img.src = imageURL; 150 | }; 151 | 152 | // Get data URL to an image of an SVG and call download on it 153 | Highcharts.downloadSVGLocal = function (svg, filename, imageType, scale, failCallback, successCallback) { 154 | var svgurl, 155 | blob, 156 | objectURLRevoke = true, 157 | finallyHandler; 158 | 159 | // Initiate download depending on file type 160 | if (imageType === 'image/svg+xml') { 161 | // SVG download. In this case, we want to use Microsoft specific Blob if available 162 | try { 163 | if (nav.msSaveOrOpenBlob) { 164 | blob = new MSBlobBuilder(); 165 | blob.append(svg); 166 | svgurl = blob.getBlob('image/svg+xml'); 167 | } else { 168 | svgurl = Highcharts.svgToDataUrl(svg); 169 | } 170 | Highcharts.downloadURL(svgurl, filename); 171 | if (successCallback) { 172 | successCallback(); 173 | } 174 | } catch (e) { 175 | failCallback(); 176 | } 177 | } else { 178 | // PNG/JPEG download - create bitmap from SVG 179 | 180 | svgurl = Highcharts.svgToDataUrl(svg); 181 | finallyHandler = function () { 182 | try { 183 | domurl.revokeObjectURL(svgurl); 184 | } catch (e) { 185 | // Ignore 186 | } 187 | }; 188 | // First, try to get PNG by rendering on canvas 189 | Highcharts.imageToDataUrl(svgurl, imageType, { /* args */ }, scale, function (imageURL) { 190 | // Success 191 | try { 192 | Highcharts.downloadURL(imageURL, filename); 193 | if (successCallback) { 194 | successCallback(); 195 | } 196 | } catch (e) { 197 | failCallback(); 198 | } 199 | }, function () { 200 | // Failed due to tainted canvas 201 | // Create new and untainted canvas 202 | var canvas = doc.createElement('canvas'), 203 | ctx = canvas.getContext('2d'), 204 | imageWidth = svg.match(/^]*width\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale, 205 | imageHeight = svg.match(/^]*height\s*=\s*\"?(\d+)\"?[^>]*>/)[1] * scale, 206 | downloadWithCanVG = function () { 207 | ctx.drawSvg(svg, 0, 0, imageWidth, imageHeight); 208 | try { 209 | Highcharts.downloadURL(nav.msSaveOrOpenBlob ? canvas.msToBlob() : canvas.toDataURL(imageType), filename); 210 | if (successCallback) { 211 | successCallback(); 212 | } 213 | } catch (e) { 214 | failCallback(); 215 | } finally { 216 | finallyHandler(); 217 | } 218 | }; 219 | 220 | canvas.width = imageWidth; 221 | canvas.height = imageHeight; 222 | if (win.canvg) { 223 | // Use preloaded canvg 224 | downloadWithCanVG(); 225 | } else { 226 | // Must load canVG first 227 | objectURLRevoke = true; // Don't destroy the object URL yet since we are doing things asynchronously. A cleaner solution would be nice, but this will do for now. 228 | getScript(Highcharts.getOptions().global.canvasToolsURL, function () { 229 | downloadWithCanVG(); 230 | }); 231 | } 232 | }, 233 | // No canvas support 234 | failCallback, 235 | // Failed to load image 236 | failCallback, 237 | // Finally 238 | function () { 239 | if (objectURLRevoke) { 240 | finallyHandler(); 241 | } 242 | }); 243 | } 244 | }; 245 | 246 | // Get SVG of chart prepared for client side export. This converts embedded images in the SVG to data URIs. 247 | // The options and chartOptions arguments are passed to the getSVGForExport function. 248 | Highcharts.Chart.prototype.getSVGForLocalExport = function (options, chartOptions, failCallback, successCallback) { 249 | var chart = this, 250 | images, 251 | imagesEmbedded = 0, 252 | chartCopyContainer, 253 | el, 254 | i, 255 | l, 256 | // Success handler, we converted image to base64! 257 | embeddedSuccess = function (imageURL, imageType, callbackArgs) { 258 | ++imagesEmbedded; 259 | 260 | // Change image href in chart copy 261 | callbackArgs.imageElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imageURL); 262 | 263 | // When done with last image we have our SVG 264 | if (imagesEmbedded === images.length) { 265 | successCallback(chart.sanitizeSVG(chartCopyContainer.innerHTML)); 266 | } 267 | }; 268 | 269 | // Hook into getSVG to get a copy of the chart copy's container 270 | Highcharts.wrap(Highcharts.Chart.prototype, 'getChartHTML', function (proceed) { 271 | chartCopyContainer = this.container.cloneNode(true); 272 | return proceed.apply(this, Array.prototype.slice.call(arguments, 1)); 273 | }); 274 | 275 | // Trigger hook to get chart copy 276 | chart.getSVGForExport(options, chartOptions); 277 | images = chartCopyContainer.getElementsByTagName('image'); 278 | 279 | try { 280 | // If there are no images to embed, the SVG is okay now. 281 | if (!images.length) { 282 | successCallback(chart.sanitizeSVG(chartCopyContainer.innerHTML)); // Use SVG of chart copy 283 | return; 284 | } 285 | 286 | // Go through the images we want to embed 287 | for (i = 0, l = images.length; i < l; ++i) { 288 | el = images[i]; 289 | Highcharts.imageToDataUrl(el.getAttributeNS('http://www.w3.org/1999/xlink', 'href'), 'image/png', { imageElement: el }, options.scale, 290 | embeddedSuccess, 291 | // Tainted canvas 292 | failCallback, 293 | // No canvas support 294 | failCallback, 295 | // Failed to load source 296 | failCallback 297 | ); 298 | } 299 | } catch (e) { 300 | failCallback(); 301 | } 302 | }; 303 | 304 | /** 305 | * Add a new method to the Chart object to perform a local download 306 | */ 307 | Highcharts.Chart.prototype.exportChartLocal = function (exportingOptions, chartOptions) { 308 | var chart = this, 309 | options = Highcharts.merge(chart.options.exporting, exportingOptions), 310 | imageType = options && options.type || 'image/png', 311 | fallbackToExportServer = function () { 312 | if (options.fallbackToExportServer === false) { 313 | if (options.error) { 314 | options.error(); 315 | } else { 316 | throw 'Fallback to export server disabled'; 317 | } 318 | } else { 319 | chart.exportChart(options); 320 | } 321 | }, 322 | svgSuccess = function (svg) { 323 | var filename = (options.filename || 'chart') + '.' + (imageType === 'image/svg+xml' ? 'svg' : imageType.split('/')[1]); 324 | Highcharts.downloadSVGLocal(svg, filename, imageType, options.scale, fallbackToExportServer); 325 | }; 326 | 327 | // If we have embedded images and are exporting to JPEG/PNG, Microsoft browsers won't handle it, so fall back 328 | // docs 329 | if (isMSBrowser && imageType !== 'image/svg+xml' && chart.container.getElementsByTagName('image').length) { 330 | fallbackToExportServer(); 331 | return; 332 | } 333 | 334 | chart.getSVGForLocalExport(options, chartOptions, fallbackToExportServer, svgSuccess); 335 | }; 336 | 337 | // Extend the default options to use the local exporter logic 338 | Highcharts.getOptions().exporting.buttons.contextButton.menuItems = [{ 339 | textKey: 'printChart', 340 | onclick: function () { 341 | this.print(); 342 | } 343 | }, { 344 | separator: true 345 | }, { 346 | textKey: 'downloadPNG', 347 | onclick: function () { 348 | this.exportChartLocal(); 349 | } 350 | }, { 351 | textKey: 'downloadJPEG', 352 | onclick: function () { 353 | this.exportChartLocal({ 354 | type: 'image/jpeg' 355 | }); 356 | } 357 | }, { 358 | textKey: 'downloadSVG', 359 | onclick: function () { 360 | this.exportChartLocal({ 361 | type: 'image/svg+xml' 362 | }); 363 | } 364 | }]; 365 | 366 | })); 367 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/solid-gauge.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | Solid angular gauge module 4 | 5 | (c) 2010-2016 Torstein Honsi 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(a){typeof module==="object"&&module.exports?module.exports=a:a(Highcharts)})(function(a){var q=a.getOptions().plotOptions,r=a.pInt,s=a.pick,k=a.each,t=a.isNumber,l;q.solidgauge=a.merge(q.gauge,{colorByPoint:!0});l={initDataClasses:function(b){var e=this,i=this.chart,c,g=0,d=this.options;this.dataClasses=c=[];k(b.dataClasses,function(f,h){var p,f=a.merge(f);c.push(f);if(!f.color)d.dataClassColor==="category"?(p=i.options.colors,f.color=p[g++],g===p.length&&(g=0)):f.color=e.tweenColors(a.Color(d.minColor), 10 | a.Color(d.maxColor),h/(b.dataClasses.length-1))})},initStops:function(b){this.stops=b.stops||[[0,this.options.minColor],[1,this.options.maxColor]];k(this.stops,function(b){b.color=a.Color(b[1])})},toColor:function(b,e){var a,c=this.stops,g,d=this.dataClasses,f,h;if(d)for(h=d.length;h--;){if(f=d[h],g=f.from,c=f.to,(g===void 0||b>=g)&&(c===void 0||b<=c)){a=f.color;if(e)e.dataClass=h;break}}else{this.isLog&&(b=this.val2lin(b));a=1-(this.max-b)/(this.max-this.min);for(h=c.length;h--;)if(a>c[h][0])break; 11 | g=c[h]||c[h+1];c=c[h+1]||g;a=1-(c[0]-a)/(c[0]-g[0]||1);a=this.tweenColors(g.color,c.color,a)}return a},tweenColors:function(b,a,i){var c;!a.rgba.length||!b.rgba.length?b=a.input||"none":(b=b.rgba,a=a.rgba,c=a[3]!==1||b[3]!==1,b=(c?"rgba(":"rgb(")+Math.round(a[0]+(b[0]-a[0])*(1-i))+","+Math.round(a[1]+(b[1]-a[1])*(1-i))+","+Math.round(a[2]+(b[2]-a[2])*(1-i))+(c?","+(a[3]+(b[3]-a[3])*(1-i)):"")+")");return b}};k(["fill","stroke"],function(b){a.Fx.prototype[b+"Setter"]=function(){this.elem.attr(b,l.tweenColors(a.Color(this.start), 12 | a.Color(this.end),this.pos))}});a.seriesTypes.solidgauge=a.extendClass(a.seriesTypes.gauge,{type:"solidgauge",pointAttrToOptions:{},bindAxes:function(){var b;a.seriesTypes.gauge.prototype.bindAxes.call(this);b=this.yAxis;a.extend(b,l);b.options.dataClasses&&b.initDataClasses(b.options);b.initStops(b.options)},drawPoints:function(){var b=this,e=b.yAxis,i=e.center,c=b.options,g=b.chart.renderer,d=c.overshoot,f=t(d)?d/180*Math.PI:0;a.each(b.points,function(a){var d=a.graphic,j=e.startAngleRad+e.translate(a.y, 13 | null,null,null,!0),k=r(s(a.options.radius,c.radius,100))*i[2]/200,m=r(s(a.options.innerRadius,c.innerRadius,60))*i[2]/200,n=e.toColor(a.y,a),o=Math.min(e.startAngleRad,e.endAngleRad),l=Math.max(e.startAngleRad,e.endAngleRad);n==="none"&&(n=a.color||b.color||"none");if(n!=="none")a.color=n;j=Math.max(o-f,Math.min(l+f,j));c.wrap===!1&&(j=Math.max(o,Math.min(l,j)));o=Math.min(j,e.startAngleRad);j=Math.max(j,e.startAngleRad);j-o>2*Math.PI&&(j=o+2*Math.PI);a.shapeArgs=m={x:i[0],y:i[1],r:k,innerR:m,start:o, 14 | end:j,fill:n};a.startR=k;if(d){if(a=m.d,d.animate(m),a)m.d=a}else d={stroke:c.borderColor||"none","stroke-width":c.borderWidth||0,fill:n,"sweep-flag":0},c.linecap!=="square"&&(d["stroke-linecap"]=d["stroke-linejoin"]="round"),a.graphic=g.arc(m).attr(d).add(b.group)})},animate:function(b){if(!b)this.startAngleRad=this.yAxis.startAngleRad,a.seriesTypes.pie.prototype.animate.call(this,b)}})}); 15 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/solid-gauge.src.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license Highcharts JS v4.2.6 (2016-08-02) 3 | * Solid angular gauge module 4 | * 5 | * (c) 2010-2016 Torstein Honsi 6 | * 7 | * License: www.highcharts.com/license 8 | */ 9 | 10 | (function (factory) { 11 | if (typeof module === 'object' && module.exports) { 12 | module.exports = factory; 13 | } else { 14 | factory(Highcharts); 15 | } 16 | }(function (H) { 17 | 'use strict'; 18 | 19 | var defaultPlotOptions = H.getOptions().plotOptions, 20 | pInt = H.pInt, 21 | pick = H.pick, 22 | each = H.each, 23 | isNumber = H.isNumber, 24 | colorAxisMethods, 25 | UNDEFINED; 26 | 27 | // The default options 28 | defaultPlotOptions.solidgauge = H.merge(defaultPlotOptions.gauge, { 29 | colorByPoint: true 30 | }); 31 | 32 | 33 | // These methods are defined in the ColorAxis object, and copied here. 34 | // If we implement an AMD system we should make ColorAxis a dependency. 35 | colorAxisMethods = { 36 | 37 | 38 | initDataClasses: function (userOptions) { 39 | var axis = this, 40 | chart = this.chart, 41 | dataClasses, 42 | colorCounter = 0, 43 | options = this.options; 44 | this.dataClasses = dataClasses = []; 45 | 46 | each(userOptions.dataClasses, function (dataClass, i) { 47 | var colors; 48 | 49 | dataClass = H.merge(dataClass); 50 | dataClasses.push(dataClass); 51 | if (!dataClass.color) { 52 | if (options.dataClassColor === 'category') { 53 | colors = chart.options.colors; 54 | dataClass.color = colors[colorCounter++]; 55 | // loop back to zero 56 | if (colorCounter === colors.length) { 57 | colorCounter = 0; 58 | } 59 | } else { 60 | dataClass.color = axis.tweenColors(H.Color(options.minColor), H.Color(options.maxColor), i / (userOptions.dataClasses.length - 1)); 61 | } 62 | } 63 | }); 64 | }, 65 | 66 | initStops: function (userOptions) { 67 | this.stops = userOptions.stops || [ 68 | [0, this.options.minColor], 69 | [1, this.options.maxColor] 70 | ]; 71 | each(this.stops, function (stop) { 72 | stop.color = H.Color(stop[1]); 73 | }); 74 | }, 75 | /** 76 | * Translate from a value to a color 77 | */ 78 | toColor: function (value, point) { 79 | var pos, 80 | stops = this.stops, 81 | from, 82 | to, 83 | color, 84 | dataClasses = this.dataClasses, 85 | dataClass, 86 | i; 87 | 88 | if (dataClasses) { 89 | i = dataClasses.length; 90 | while (i--) { 91 | dataClass = dataClasses[i]; 92 | from = dataClass.from; 93 | to = dataClass.to; 94 | if ((from === UNDEFINED || value >= from) && (to === UNDEFINED || value <= to)) { 95 | color = dataClass.color; 96 | if (point) { 97 | point.dataClass = i; 98 | } 99 | break; 100 | } 101 | } 102 | 103 | } else { 104 | 105 | if (this.isLog) { 106 | value = this.val2lin(value); 107 | } 108 | pos = 1 - ((this.max - value) / (this.max - this.min)); 109 | i = stops.length; 110 | while (i--) { 111 | if (pos > stops[i][0]) { 112 | break; 113 | } 114 | } 115 | from = stops[i] || stops[i + 1]; 116 | to = stops[i + 1] || from; 117 | 118 | // The position within the gradient 119 | pos = 1 - (to[0] - pos) / ((to[0] - from[0]) || 1); 120 | 121 | color = this.tweenColors( 122 | from.color, 123 | to.color, 124 | pos 125 | ); 126 | } 127 | return color; 128 | }, 129 | /* 130 | * Return an intermediate color between two colors, according to pos where 0 131 | * is the from color and 1 is the to color. 132 | */ 133 | tweenColors: function (from, to, pos) { 134 | // Check for has alpha, because rgba colors perform worse due to lack of 135 | // support in WebKit. 136 | var hasAlpha, 137 | ret; 138 | 139 | // Unsupported color, return to-color (#3920) 140 | if (!to.rgba.length || !from.rgba.length) { 141 | ret = to.input || 'none'; 142 | 143 | // Interpolate 144 | } else { 145 | from = from.rgba; 146 | to = to.rgba; 147 | hasAlpha = (to[3] !== 1 || from[3] !== 1); 148 | ret = (hasAlpha ? 'rgba(' : 'rgb(') + 149 | Math.round(to[0] + (from[0] - to[0]) * (1 - pos)) + ',' + 150 | Math.round(to[1] + (from[1] - to[1]) * (1 - pos)) + ',' + 151 | Math.round(to[2] + (from[2] - to[2]) * (1 - pos)) + 152 | (hasAlpha ? (',' + (to[3] + (from[3] - to[3]) * (1 - pos))) : '') + ')'; 153 | } 154 | return ret; 155 | } 156 | }; 157 | 158 | /** 159 | * Handle animation of the color attributes directly 160 | */ 161 | each(['fill', 'stroke'], function (prop) { 162 | H.Fx.prototype[prop + 'Setter'] = function () { 163 | this.elem.attr(prop, colorAxisMethods.tweenColors(H.Color(this.start), H.Color(this.end), this.pos)); 164 | }; 165 | }); 166 | 167 | // The series prototype 168 | H.seriesTypes.solidgauge = H.extendClass(H.seriesTypes.gauge, { 169 | type: 'solidgauge', 170 | pointAttrToOptions: {}, // #4301, don't inherit line marker's attribs 171 | bindAxes: function () { 172 | var axis; 173 | H.seriesTypes.gauge.prototype.bindAxes.call(this); 174 | 175 | axis = this.yAxis; 176 | H.extend(axis, colorAxisMethods); 177 | 178 | // Prepare data classes 179 | if (axis.options.dataClasses) { 180 | axis.initDataClasses(axis.options); 181 | } 182 | axis.initStops(axis.options); 183 | }, 184 | 185 | /** 186 | * Draw the points where each point is one needle 187 | */ 188 | drawPoints: function () { 189 | var series = this, 190 | yAxis = series.yAxis, 191 | center = yAxis.center, 192 | options = series.options, 193 | renderer = series.chart.renderer, 194 | overshoot = options.overshoot, 195 | overshootVal = isNumber(overshoot) ? overshoot / 180 * Math.PI : 0; 196 | 197 | H.each(series.points, function (point) { 198 | var graphic = point.graphic, 199 | rotation = yAxis.startAngleRad + yAxis.translate(point.y, null, null, null, true), 200 | radius = (pInt(pick(point.options.radius, options.radius, 100)) * center[2]) / 200, 201 | innerRadius = (pInt(pick(point.options.innerRadius, options.innerRadius, 60)) * center[2]) / 200, 202 | shapeArgs, 203 | d, 204 | toColor = yAxis.toColor(point.y, point), 205 | axisMinAngle = Math.min(yAxis.startAngleRad, yAxis.endAngleRad), 206 | axisMaxAngle = Math.max(yAxis.startAngleRad, yAxis.endAngleRad), 207 | minAngle, 208 | maxAngle, 209 | attribs; 210 | 211 | if (toColor === 'none') { // #3708 212 | toColor = point.color || series.color || 'none'; 213 | } 214 | if (toColor !== 'none') { 215 | point.color = toColor; 216 | } 217 | 218 | // Handle overshoot and clipping to axis max/min 219 | rotation = Math.max(axisMinAngle - overshootVal, Math.min(axisMaxAngle + overshootVal, rotation)); 220 | 221 | // Handle the wrap option 222 | if (options.wrap === false) { 223 | rotation = Math.max(axisMinAngle, Math.min(axisMaxAngle, rotation)); 224 | } 225 | 226 | minAngle = Math.min(rotation, yAxis.startAngleRad); 227 | maxAngle = Math.max(rotation, yAxis.startAngleRad); 228 | 229 | if (maxAngle - minAngle > 2 * Math.PI) { 230 | maxAngle = minAngle + 2 * Math.PI; 231 | } 232 | 233 | point.shapeArgs = shapeArgs = { 234 | x: center[0], 235 | y: center[1], 236 | r: radius, 237 | innerR: innerRadius, 238 | start: minAngle, 239 | end: maxAngle, 240 | fill: toColor 241 | }; 242 | point.startR = radius; // For PieSeries.animate 243 | 244 | if (graphic) { 245 | d = shapeArgs.d; 246 | graphic.animate(shapeArgs); 247 | if (d) { 248 | shapeArgs.d = d; // animate alters it 249 | } 250 | } else { 251 | attribs = { 252 | stroke: options.borderColor || 'none', 253 | 'stroke-width': options.borderWidth || 0, 254 | fill: toColor, 255 | 'sweep-flag': 0 256 | }; 257 | if (options.linecap !== 'square') { 258 | attribs['stroke-linecap'] = attribs['stroke-linejoin'] = 'round'; 259 | } 260 | point.graphic = renderer.arc(shapeArgs) 261 | .attr(attribs) 262 | .add(series.group); 263 | } 264 | }); 265 | }, 266 | 267 | /** 268 | * Extend the pie slice animation by animating from start angle and up 269 | */ 270 | animate: function (init) { 271 | 272 | if (!init) { 273 | this.startAngleRad = this.yAxis.startAngleRad; 274 | H.seriesTypes.pie.prototype.animate.call(this, init); 275 | } 276 | } 277 | }); 278 | 279 | })); 280 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/modules/treemap.js: -------------------------------------------------------------------------------- 1 | /* 2 | Highcharts JS v4.2.6 (2016-08-02) 3 | 4 | (c) 2014 Highsoft AS 5 | Authors: Jon Arild Nygard / Oystein Moseng 6 | 7 | License: www.highcharts.com/license 8 | */ 9 | (function(f){typeof module==="object"&&module.exports?module.exports=f:f(Highcharts)})(function(f){var i=f.seriesTypes,B=f.map,m=f.merge,t=f.extend,u=f.extendClass,v=f.getOptions().plotOptions,w=function(){},k=f.each,r=f.grep,j=f.pick,n=f.Series,C=f.stableSort,x=f.Color,D=function(a,b,c){var d,c=c||this;for(d in a)a.hasOwnProperty(d)&&b.call(c,a[d],d,a)},y=function(a,b,c,d){d=d||this;a=a||[];k(a,function(e,h){c=b.call(d,c,e,h,a)});return c},q=function(a,b,c){c=c||this;a=b.call(c,a);a!==!1&&q(a,b, 10 | c)};v.treemap=m(v.scatter,{showInLegend:!1,marker:!1,borderColor:"#E0E0E0",borderWidth:1,dataLabels:{enabled:!0,defer:!1,verticalAlign:"middle",formatter:function(){return this.point.name||this.point.id},inside:!0},tooltip:{headerFormat:"",pointFormat:"{point.name}: {point.value}
"},layoutAlgorithm:"sliceAndDice",layoutStartingDirection:"vertical",alternateStartingDirection:!1,levelIsConstant:!0,opacity:0.15,states:{hover:{borderColor:"#A0A0A0",brightness:i.heatmap?0:0.1,opacity:0.75, 11 | shadow:!1}},drillUpButton:{position:{align:"right",x:-10,y:10}}});i.treemap=u(i.scatter,m({pointAttrToOptions:{},pointArrayMap:["value"],axisTypes:i.heatmap?["xAxis","yAxis","colorAxis"]:["xAxis","yAxis"],optionalAxis:"colorAxis",getSymbol:w,parallelArrays:["x","y","value","colorValue"],colorKey:"colorValue",translateColors:i.heatmap&&i.heatmap.prototype.translateColors},{type:"treemap",trackerGroups:["group","dataLabelsGroup"],pointClass:u(f.Point,{setVisible:i.pie.prototype.pointClass.prototype.setVisible}), 12 | getListOfParents:function(a,b){var c=y(a,function(a,c,b){c=j(c.parent,"");a[c]===void 0&&(a[c]=[]);a[c].push(b);return a},{});D(c,function(a,c,h){c!==""&&f.inArray(c,b)===-1&&(k(a,function(a){h[""].push(a)}),delete h[c])});return c},getTree:function(){var a,b=this;a=B(this.data,function(a){return a.id});a=b.getListOfParents(this.data,a);b.nodeMap=[];a=b.buildNode("",-1,0,a,null);q(this.nodeMap[this.rootNode],function(a){var d=!1,e=a.parent;a.visible=!0;if(e||e==="")d=b.nodeMap[e];return d});q(this.nodeMap[this.rootNode].children, 13 | function(a){var b=!1;k(a,function(a){a.visible=!0;a.children.length&&(b=(b||[]).concat(a.children))});return b});this.setTreeValues(a);return a},init:function(a,b){n.prototype.init.call(this,a,b);this.options.allowDrillToNode&&this.drillTo()},buildNode:function(a,b,c,d,e){var h=this,g=[],z=h.points[b],A;k(d[a]||[],function(b){A=h.buildNode(h.points[b].id,b,c+1,d,a);g.push(A)});b={id:a,i:b,children:g,level:c,parent:e,visible:!1};h.nodeMap[b.id]=b;if(z)z.node=b;return b},setTreeValues:function(a){var b= 14 | this,c=b.options,d=0,e=[],h,g=b.points[a.i];k(a.children,function(a){a=b.setTreeValues(a);e.push(a);a.ignore?q(a.children,function(a){var c=!1;k(a,function(a){t(a,{ignore:!0,isLeaf:!1,visible:!1});a.children.length&&(c=(c||[]).concat(a.children))});return c}):d+=a.val});C(e,function(a,c){return a.sortIndex-c.sortIndex});h=j(g&&g.options.value,d);if(g)g.value=h;t(a,{children:e,childrenTotal:d,ignore:!(j(g&&g.visible,!0)&&h>0),isLeaf:a.visible&&!d,levelDynamic:c.levelIsConstant?a.level:a.level-b.nodeMap[b.rootNode].level, 15 | name:j(g&&g.name,""),sortIndex:j(g&&g.sortIndex,-h),val:h});return a},calculateChildrenAreas:function(a,b){var c=this,d=c.options,e=this.levelMap[a.levelDynamic+1],h=j(c[e&&e.layoutAlgorithm]&&e.layoutAlgorithm,d.layoutAlgorithm),g=d.alternateStartingDirection,f=[],d=r(a.children,function(a){return!a.ignore});if(e&&e.layoutStartingDirection)b.direction=e.layoutStartingDirection==="vertical"?0:1;f=c[h](b,d);k(d,function(a,d){var e=f[d];a.values=m(e,{val:a.childrenTotal,direction:g?1-b.direction:b.direction}); 16 | a.pointValues=m(e,{x:e.x/c.axisRatio,width:e.width/c.axisRatio});a.children.length&&c.calculateChildrenAreas(a,a.values)})},setPointValues:function(){var a=this.xAxis,b=this.yAxis;k(this.points,function(c){var d=c.node,e=d.pointValues,h,g;e&&d.visible?(d=Math.round(a.translate(e.x,0,0,0,1)),h=Math.round(a.translate(e.x+e.width,0,0,0,1)),g=Math.round(b.translate(e.y,0,0,0,1)),e=Math.round(b.translate(e.y+e.height,0,0,0,1)),c.shapeType="rect",c.shapeArgs={x:Math.min(d,h),y:Math.min(g,e),width:Math.abs(h- 17 | d),height:Math.abs(e-g)},c.plotX=c.shapeArgs.x+c.shapeArgs.width/2,c.plotY=c.shapeArgs.y+c.shapeArgs.height/2):(delete c.plotX,delete c.plotY)})},setColorRecursive:function(a,b){var c=this,d,e;if(a){d=c.points[a.i];e=c.levelMap[a.levelDynamic];b=j(d&&d.options.color,e&&e.color,b);if(d)d.color=b;a.children.length&&k(a.children,function(a){c.setColorRecursive(a,b)})}},algorithmGroup:function(a,b,c,d){this.height=a;this.width=b;this.plot=d;this.startDirection=this.direction=c;this.lH=this.nH=this.lW= 18 | this.nW=this.total=0;this.elArr=[];this.lP={total:0,lH:0,nH:0,lW:0,nW:0,nR:0,lR:0,aspectRatio:function(a,c){return Math.max(a/c,c/a)}};this.addElement=function(a){this.lP.total=this.elArr[this.elArr.length-1];this.total+=a;this.direction===0?(this.lW=this.nW,this.lP.lH=this.lP.total/this.lW,this.lP.lR=this.lP.aspectRatio(this.lW,this.lP.lH),this.nW=this.total/this.height,this.lP.nH=this.lP.total/this.nW,this.lP.nR=this.lP.aspectRatio(this.nW,this.lP.nH)):(this.lH=this.nH,this.lP.lW=this.lP.total/ 19 | this.lH,this.lP.lR=this.lP.aspectRatio(this.lP.lW,this.lH),this.nH=this.total/this.width,this.lP.nW=this.lP.total/this.nH,this.lP.nR=this.lP.aspectRatio(this.lP.nW,this.nH));this.elArr.push(a)};this.reset=function(){this.lW=this.nW=0;this.elArr=[];this.total=0}},algorithmCalcPoints:function(a,b,c,d){var e,h,g,f,j=c.lW,s=c.lH,l=c.plot,i,o=0,p=c.elArr.length-1;b?(j=c.nW,s=c.nH):i=c.elArr[c.elArr.length-1];k(c.elArr,function(a){if(b||oi.lP.lR&&e.algorithmCalcPoints(a, 21 | !1,i,d,g);f===j&&e.algorithmCalcPoints(a,!0,i,d,g);f+=1});return d},algorithmFill:function(a,b,c){var d=[],e,f=b.direction,g=b.x,i=b.y,j=b.width,m=b.height,l,n,o,p;k(c,function(c){e=b.width*b.height*(c.val/b.val);l=g;n=i;f===0?(p=m,o=e/p,j-=o,g+=o):(o=j,p=e/o,m-=p,i+=p);d.push({x:l,y:n,width:o,height:p});a&&(f=1-f)});return d},strip:function(a,b){return this.algorithmLowAspectRatio(!1,a,b)},squarified:function(a,b){return this.algorithmLowAspectRatio(!0,a,b)},sliceAndDice:function(a,b){return this.algorithmFill(!0, 22 | a,b)},stripes:function(a,b){return this.algorithmFill(!1,a,b)},translate:function(){var a,b;n.prototype.translate.call(this);this.rootNode=j(this.options.rootId,"");this.levelMap=y(this.options.levels,function(a,b){a[b.level]=b;return a},{});b=this.tree=this.getTree();this.axisRatio=this.xAxis.len/this.yAxis.len;this.nodeMap[""].pointValues=a={x:0,y:0,width:100,height:100};this.nodeMap[""].values=a=m(a,{width:a.width*this.axisRatio,direction:this.options.layoutStartingDirection==="vertical"?0:1,val:b.val}); 23 | this.calculateChildrenAreas(b,a);this.colorAxis?this.translateColors():this.options.colorByPoint||this.setColorRecursive(this.tree,void 0);if(this.options.allowDrillToNode)b=this.nodeMap[this.rootNode].pointValues,this.xAxis.setExtremes(b.x,b.x+b.width,!1),this.yAxis.setExtremes(b.y,b.y+b.height,!1),this.xAxis.setScale(),this.yAxis.setScale();this.setPointValues()},drawDataLabels:function(){var a=this,b=r(a.points,function(a){return a.node.visible}),c,d;k(b,function(b){d=a.levelMap[b.node.levelDynamic]; 24 | c={style:{}};if(!b.node.isLeaf)c.enabled=!1;if(d&&d.dataLabels)c=m(c,d.dataLabels),a._hasPointLabels=!0;if(b.shapeArgs)c.style.width=b.shapeArgs.width,b.dataLabel&&b.dataLabel.css({width:b.shapeArgs.width+"px"});b.dlOptions=m(c,b.options.dataLabels)});n.prototype.drawDataLabels.call(this)},alignDataLabel:i.column.prototype.alignDataLabel,pointAttribs:function(a,b){var c=this.levelMap[a.node.levelDynamic]||{},d=this.options,e=b&&d.states[b]||{},c={stroke:a.borderColor||c.borderColor||e.borderColor|| 25 | d.borderColor,"stroke-width":j(a.borderWidth,c.borderWidth,e.borderWidth,d.borderWidth),dashstyle:a.borderDashStyle||c.borderDashStyle||e.borderDashStyle||d.borderDashStyle,fill:a.color||this.color,zIndex:b==="hover"?1:0};if(a.node.level<=this.nodeMap[this.rootNode].level)c.fill="none",c["stroke-width"]=0;else if(a.node.isLeaf){if(b)c.fill=x(c.fill).brighten(e.brightness).get()}else j(d.interactByLeaf,!d.allowDrillToNode)?c.fill="none":(d=j(e.opacity,d.opacity),c.fill=x(c.fill).setOpacity(d).get()); 26 | return c},drawPoints:function(){var a=this,b=r(a.points,function(a){return a.node.visible});k(b,function(c){var b="levelGroup-"+c.node.levelDynamic;a[b]||(a[b]=a.chart.renderer.g(b).attr({zIndex:1E3-c.node.levelDynamic}).add(a.group));c.group=a[b];b=a.pointAttribs(c);c.pointAttr={"":b,hover:a.pointAttribs(c,"hover"),select:{}};b=parseInt(b["stroke-width"],10)%2/2;c.shapeArgs.x-=b;c.shapeArgs.y-=b});i.column.prototype.drawPoints.call(this);a.options.allowDrillToNode&&k(b,function(b){var d;if(b.graphic)d= 27 | b.drillId=a.options.interactByLeaf?a.drillToByLeaf(b):a.drillToByGroup(b),b.graphic.css({cursor:d?"pointer":"default"})})},drillTo:function(){var a=this;f.addEvent(a,"click",function(b){var b=b.point,c=b.drillId,d;c&&(d=a.nodeMap[a.rootNode].name||a.rootNode,b.setState(""),a.drillToNode(c),a.showDrillUpButton(d))})},drillToByGroup:function(a){var b=!1;if(a.node.level-this.nodeMap[this.rootNode].level===1&&!a.node.isLeaf)b=a.id;return b},drillToByLeaf:function(a){var b=!1;if(a.node.parent!==this.rootNode&& 28 | a.node.isLeaf)for(a=a.node;!b;)if(a=this.nodeMap[a.parent],a.parent===this.rootNode)b=a.id;return b},drillUp:function(){var a=null;this.rootNode&&(a=this.nodeMap[this.rootNode],a=a.parent!==null?this.nodeMap[a.parent]:this.nodeMap[""]);if(a!==null)this.drillToNode(a.id),a.id===""?this.drillUpButton=this.drillUpButton.destroy():(a=this.nodeMap[a.parent],this.showDrillUpButton(a.name||a.id))},drillToNode:function(a){this.options.rootId=a;this.isDirty=!0;this.chart.redraw()},showDrillUpButton:function(a){var b= 29 | this,a=a||"< Back",c=b.options.drillUpButton,d,e;if(c.text)a=c.text;this.drillUpButton?this.drillUpButton.attr({text:a}).align():(e=(d=c.theme)&&d.states,this.drillUpButton=this.chart.renderer.button(a,null,null,function(){b.drillUp()},d,e&&e.hover,e&&e.select).attr({align:c.position.align,zIndex:9}).add().align(c.position,!1,c.relativeTo||"plotBox"))},buildKDTree:w,drawLegendSymbol:f.LegendSymbolMixin.drawRectangle,getExtremes:function(){n.prototype.getExtremes.call(this,this.colorValueData);this.valueMin= 30 | this.dataMin;this.valueMax=this.dataMax;n.prototype.getExtremes.call(this)},getExtremesFromAll:!0,bindAxes:function(){var a={endOnTick:!1,gridLineWidth:0,lineWidth:0,min:0,dataMin:0,minPadding:0,max:100,dataMax:100,maxPadding:0,startOnTick:!1,title:null,tickPositions:[]};n.prototype.bindAxes.call(this);f.extend(this.yAxis.options,a);f.extend(this.xAxis.options,a)}}))}); 31 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/dark-blue.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dark blue theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | Highcharts.theme = { 7 | colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 8 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], 9 | chart: { 10 | backgroundColor: { 11 | linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, 12 | stops: [ 13 | [0, 'rgb(48, 48, 96)'], 14 | [1, 'rgb(0, 0, 0)'] 15 | ] 16 | }, 17 | borderColor: '#000000', 18 | borderWidth: 2, 19 | className: 'dark-container', 20 | plotBackgroundColor: 'rgba(255, 255, 255, .1)', 21 | plotBorderColor: '#CCCCCC', 22 | plotBorderWidth: 1 23 | }, 24 | title: { 25 | style: { 26 | color: '#C0C0C0', 27 | font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' 28 | } 29 | }, 30 | subtitle: { 31 | style: { 32 | color: '#666666', 33 | font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' 34 | } 35 | }, 36 | xAxis: { 37 | gridLineColor: '#333333', 38 | gridLineWidth: 1, 39 | labels: { 40 | style: { 41 | color: '#A0A0A0' 42 | } 43 | }, 44 | lineColor: '#A0A0A0', 45 | tickColor: '#A0A0A0', 46 | title: { 47 | style: { 48 | color: '#CCC', 49 | fontWeight: 'bold', 50 | fontSize: '12px', 51 | fontFamily: 'Trebuchet MS, Verdana, sans-serif' 52 | 53 | } 54 | } 55 | }, 56 | yAxis: { 57 | gridLineColor: '#333333', 58 | labels: { 59 | style: { 60 | color: '#A0A0A0' 61 | } 62 | }, 63 | lineColor: '#A0A0A0', 64 | minorTickInterval: null, 65 | tickColor: '#A0A0A0', 66 | tickWidth: 1, 67 | title: { 68 | style: { 69 | color: '#CCC', 70 | fontWeight: 'bold', 71 | fontSize: '12px', 72 | fontFamily: 'Trebuchet MS, Verdana, sans-serif' 73 | } 74 | } 75 | }, 76 | tooltip: { 77 | backgroundColor: 'rgba(0, 0, 0, 0.75)', 78 | style: { 79 | color: '#F0F0F0' 80 | } 81 | }, 82 | toolbar: { 83 | itemStyle: { 84 | color: 'silver' 85 | } 86 | }, 87 | plotOptions: { 88 | line: { 89 | dataLabels: { 90 | color: '#CCC' 91 | }, 92 | marker: { 93 | lineColor: '#333' 94 | } 95 | }, 96 | spline: { 97 | marker: { 98 | lineColor: '#333' 99 | } 100 | }, 101 | scatter: { 102 | marker: { 103 | lineColor: '#333' 104 | } 105 | }, 106 | candlestick: { 107 | lineColor: 'white' 108 | } 109 | }, 110 | legend: { 111 | itemStyle: { 112 | font: '9pt Trebuchet MS, Verdana, sans-serif', 113 | color: '#A0A0A0' 114 | }, 115 | itemHoverStyle: { 116 | color: '#FFF' 117 | }, 118 | itemHiddenStyle: { 119 | color: '#444' 120 | } 121 | }, 122 | credits: { 123 | style: { 124 | color: '#666' 125 | } 126 | }, 127 | labels: { 128 | style: { 129 | color: '#CCC' 130 | } 131 | }, 132 | 133 | navigation: { 134 | buttonOptions: { 135 | symbolStroke: '#DDDDDD', 136 | hoverSymbolStroke: '#FFFFFF', 137 | theme: { 138 | fill: { 139 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 140 | stops: [ 141 | [0.4, '#606060'], 142 | [0.6, '#333333'] 143 | ] 144 | }, 145 | stroke: '#000000' 146 | } 147 | } 148 | }, 149 | 150 | // scroll charts 151 | rangeSelector: { 152 | buttonTheme: { 153 | fill: { 154 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 155 | stops: [ 156 | [0.4, '#888'], 157 | [0.6, '#555'] 158 | ] 159 | }, 160 | stroke: '#000000', 161 | style: { 162 | color: '#CCC', 163 | fontWeight: 'bold' 164 | }, 165 | states: { 166 | hover: { 167 | fill: { 168 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 169 | stops: [ 170 | [0.4, '#BBB'], 171 | [0.6, '#888'] 172 | ] 173 | }, 174 | stroke: '#000000', 175 | style: { 176 | color: 'white' 177 | } 178 | }, 179 | select: { 180 | fill: { 181 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 182 | stops: [ 183 | [0.1, '#000'], 184 | [0.3, '#333'] 185 | ] 186 | }, 187 | stroke: '#000000', 188 | style: { 189 | color: 'yellow' 190 | } 191 | } 192 | } 193 | }, 194 | inputStyle: { 195 | backgroundColor: '#333', 196 | color: 'silver' 197 | }, 198 | labelStyle: { 199 | color: 'silver' 200 | } 201 | }, 202 | 203 | navigator: { 204 | handles: { 205 | backgroundColor: '#666', 206 | borderColor: '#AAA' 207 | }, 208 | outlineColor: '#CCC', 209 | maskFill: 'rgba(16, 16, 16, 0.5)', 210 | series: { 211 | color: '#7798BF', 212 | lineColor: '#A6C7ED' 213 | } 214 | }, 215 | 216 | scrollbar: { 217 | barBackgroundColor: { 218 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 219 | stops: [ 220 | [0.4, '#888'], 221 | [0.6, '#555'] 222 | ] 223 | }, 224 | barBorderColor: '#CCC', 225 | buttonArrowColor: '#CCC', 226 | buttonBackgroundColor: { 227 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 228 | stops: [ 229 | [0.4, '#888'], 230 | [0.6, '#555'] 231 | ] 232 | }, 233 | buttonBorderColor: '#CCC', 234 | rifleColor: '#FFF', 235 | trackBackgroundColor: { 236 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 237 | stops: [ 238 | [0, '#000'], 239 | [1, '#333'] 240 | ] 241 | }, 242 | trackBorderColor: '#666' 243 | }, 244 | 245 | // special colors for some of the 246 | legendBackgroundColor: 'rgba(0, 0, 0, 0.5)', 247 | background2: 'rgb(35, 35, 70)', 248 | dataLabelsColor: '#444', 249 | textColor: '#C0C0C0', 250 | maskColor: 'rgba(255,255,255,0.3)' 251 | }; 252 | 253 | // Apply the theme 254 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme); 255 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/dark-green.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dark blue theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | Highcharts.theme = { 7 | colors: ["#DDDF0D", "#55BF3B", "#DF5353", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 8 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], 9 | chart: { 10 | backgroundColor: { 11 | linearGradient: [0, 0, 250, 500], 12 | stops: [ 13 | [0, 'rgb(48, 96, 48)'], 14 | [1, 'rgb(0, 0, 0)'] 15 | ] 16 | }, 17 | borderColor: '#000000', 18 | borderWidth: 2, 19 | className: 'dark-container', 20 | plotBackgroundColor: 'rgba(255, 255, 255, .1)', 21 | plotBorderColor: '#CCCCCC', 22 | plotBorderWidth: 1 23 | }, 24 | title: { 25 | style: { 26 | color: '#C0C0C0', 27 | font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' 28 | } 29 | }, 30 | subtitle: { 31 | style: { 32 | color: '#666666', 33 | font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' 34 | } 35 | }, 36 | xAxis: { 37 | gridLineColor: '#333333', 38 | gridLineWidth: 1, 39 | labels: { 40 | style: { 41 | color: '#A0A0A0' 42 | } 43 | }, 44 | lineColor: '#A0A0A0', 45 | tickColor: '#A0A0A0', 46 | title: { 47 | style: { 48 | color: '#CCC', 49 | fontWeight: 'bold', 50 | fontSize: '12px', 51 | fontFamily: 'Trebuchet MS, Verdana, sans-serif' 52 | 53 | } 54 | } 55 | }, 56 | yAxis: { 57 | gridLineColor: '#333333', 58 | labels: { 59 | style: { 60 | color: '#A0A0A0' 61 | } 62 | }, 63 | lineColor: '#A0A0A0', 64 | minorTickInterval: null, 65 | tickColor: '#A0A0A0', 66 | tickWidth: 1, 67 | title: { 68 | style: { 69 | color: '#CCC', 70 | fontWeight: 'bold', 71 | fontSize: '12px', 72 | fontFamily: 'Trebuchet MS, Verdana, sans-serif' 73 | } 74 | } 75 | }, 76 | tooltip: { 77 | backgroundColor: 'rgba(0, 0, 0, 0.75)', 78 | style: { 79 | color: '#F0F0F0' 80 | } 81 | }, 82 | toolbar: { 83 | itemStyle: { 84 | color: 'silver' 85 | } 86 | }, 87 | plotOptions: { 88 | line: { 89 | dataLabels: { 90 | color: '#CCC' 91 | }, 92 | marker: { 93 | lineColor: '#333' 94 | } 95 | }, 96 | spline: { 97 | marker: { 98 | lineColor: '#333' 99 | } 100 | }, 101 | scatter: { 102 | marker: { 103 | lineColor: '#333' 104 | } 105 | }, 106 | candlestick: { 107 | lineColor: 'white' 108 | } 109 | }, 110 | legend: { 111 | itemStyle: { 112 | font: '9pt Trebuchet MS, Verdana, sans-serif', 113 | color: '#A0A0A0' 114 | }, 115 | itemHoverStyle: { 116 | color: '#FFF' 117 | }, 118 | itemHiddenStyle: { 119 | color: '#444' 120 | } 121 | }, 122 | credits: { 123 | style: { 124 | color: '#666' 125 | } 126 | }, 127 | labels: { 128 | style: { 129 | color: '#CCC' 130 | } 131 | }, 132 | 133 | 134 | navigation: { 135 | buttonOptions: { 136 | symbolStroke: '#DDDDDD', 137 | hoverSymbolStroke: '#FFFFFF', 138 | theme: { 139 | fill: { 140 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 141 | stops: [ 142 | [0.4, '#606060'], 143 | [0.6, '#333333'] 144 | ] 145 | }, 146 | stroke: '#000000' 147 | } 148 | } 149 | }, 150 | 151 | // scroll charts 152 | rangeSelector: { 153 | buttonTheme: { 154 | fill: { 155 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 156 | stops: [ 157 | [0.4, '#888'], 158 | [0.6, '#555'] 159 | ] 160 | }, 161 | stroke: '#000000', 162 | style: { 163 | color: '#CCC', 164 | fontWeight: 'bold' 165 | }, 166 | states: { 167 | hover: { 168 | fill: { 169 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 170 | stops: [ 171 | [0.4, '#BBB'], 172 | [0.6, '#888'] 173 | ] 174 | }, 175 | stroke: '#000000', 176 | style: { 177 | color: 'white' 178 | } 179 | }, 180 | select: { 181 | fill: { 182 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 183 | stops: [ 184 | [0.1, '#000'], 185 | [0.3, '#333'] 186 | ] 187 | }, 188 | stroke: '#000000', 189 | style: { 190 | color: 'yellow' 191 | } 192 | } 193 | } 194 | }, 195 | inputStyle: { 196 | backgroundColor: '#333', 197 | color: 'silver' 198 | }, 199 | labelStyle: { 200 | color: 'silver' 201 | } 202 | }, 203 | 204 | navigator: { 205 | handles: { 206 | backgroundColor: '#666', 207 | borderColor: '#AAA' 208 | }, 209 | outlineColor: '#CCC', 210 | maskFill: 'rgba(16, 16, 16, 0.5)', 211 | series: { 212 | color: '#7798BF', 213 | lineColor: '#A6C7ED' 214 | } 215 | }, 216 | 217 | scrollbar: { 218 | barBackgroundColor: { 219 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 220 | stops: [ 221 | [0.4, '#888'], 222 | [0.6, '#555'] 223 | ] 224 | }, 225 | barBorderColor: '#CCC', 226 | buttonArrowColor: '#CCC', 227 | buttonBackgroundColor: { 228 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 229 | stops: [ 230 | [0.4, '#888'], 231 | [0.6, '#555'] 232 | ] 233 | }, 234 | buttonBorderColor: '#CCC', 235 | rifleColor: '#FFF', 236 | trackBackgroundColor: { 237 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 238 | stops: [ 239 | [0, '#000'], 240 | [1, '#333'] 241 | ] 242 | }, 243 | trackBorderColor: '#666' 244 | }, 245 | 246 | // special colors for some of the 247 | legendBackgroundColor: 'rgba(0, 0, 0, 0.5)', 248 | background2: 'rgb(35, 35, 70)', 249 | dataLabelsColor: '#444', 250 | textColor: '#C0C0C0', 251 | maskColor: 'rgba(255,255,255,0.3)' 252 | }; 253 | 254 | // Apply the theme 255 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme); 256 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/dark-unica.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Dark theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | // Load the fonts 7 | Highcharts.createElement('link', { 8 | href: 'https://fonts.googleapis.com/css?family=Unica+One', 9 | rel: 'stylesheet', 10 | type: 'text/css' 11 | }, null, document.getElementsByTagName('head')[0]); 12 | 13 | Highcharts.theme = { 14 | colors: ["#2b908f", "#90ee7e", "#f45b5b", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 15 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], 16 | chart: { 17 | backgroundColor: { 18 | linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, 19 | stops: [ 20 | [0, '#2a2a2b'], 21 | [1, '#3e3e40'] 22 | ] 23 | }, 24 | style: { 25 | fontFamily: "'Unica One', sans-serif" 26 | }, 27 | plotBorderColor: '#606063' 28 | }, 29 | title: { 30 | style: { 31 | color: '#E0E0E3', 32 | textTransform: 'uppercase', 33 | fontSize: '20px' 34 | } 35 | }, 36 | subtitle: { 37 | style: { 38 | color: '#E0E0E3', 39 | textTransform: 'uppercase' 40 | } 41 | }, 42 | xAxis: { 43 | gridLineColor: '#707073', 44 | labels: { 45 | style: { 46 | color: '#E0E0E3' 47 | } 48 | }, 49 | lineColor: '#707073', 50 | minorGridLineColor: '#505053', 51 | tickColor: '#707073', 52 | title: { 53 | style: { 54 | color: '#A0A0A3' 55 | 56 | } 57 | } 58 | }, 59 | yAxis: { 60 | gridLineColor: '#707073', 61 | labels: { 62 | style: { 63 | color: '#E0E0E3' 64 | } 65 | }, 66 | lineColor: '#707073', 67 | minorGridLineColor: '#505053', 68 | tickColor: '#707073', 69 | tickWidth: 1, 70 | title: { 71 | style: { 72 | color: '#A0A0A3' 73 | } 74 | } 75 | }, 76 | tooltip: { 77 | backgroundColor: 'rgba(0, 0, 0, 0.85)', 78 | style: { 79 | color: '#F0F0F0' 80 | } 81 | }, 82 | plotOptions: { 83 | series: { 84 | dataLabels: { 85 | color: '#B0B0B3' 86 | }, 87 | marker: { 88 | lineColor: '#333' 89 | } 90 | }, 91 | boxplot: { 92 | fillColor: '#505053' 93 | }, 94 | candlestick: { 95 | lineColor: 'white' 96 | }, 97 | errorbar: { 98 | color: 'white' 99 | } 100 | }, 101 | legend: { 102 | itemStyle: { 103 | color: '#E0E0E3' 104 | }, 105 | itemHoverStyle: { 106 | color: '#FFF' 107 | }, 108 | itemHiddenStyle: { 109 | color: '#606063' 110 | } 111 | }, 112 | credits: { 113 | style: { 114 | color: '#666' 115 | } 116 | }, 117 | labels: { 118 | style: { 119 | color: '#707073' 120 | } 121 | }, 122 | 123 | drilldown: { 124 | activeAxisLabelStyle: { 125 | color: '#F0F0F3' 126 | }, 127 | activeDataLabelStyle: { 128 | color: '#F0F0F3' 129 | } 130 | }, 131 | 132 | navigation: { 133 | buttonOptions: { 134 | symbolStroke: '#DDDDDD', 135 | theme: { 136 | fill: '#505053' 137 | } 138 | } 139 | }, 140 | 141 | // scroll charts 142 | rangeSelector: { 143 | buttonTheme: { 144 | fill: '#505053', 145 | stroke: '#000000', 146 | style: { 147 | color: '#CCC' 148 | }, 149 | states: { 150 | hover: { 151 | fill: '#707073', 152 | stroke: '#000000', 153 | style: { 154 | color: 'white' 155 | } 156 | }, 157 | select: { 158 | fill: '#000003', 159 | stroke: '#000000', 160 | style: { 161 | color: 'white' 162 | } 163 | } 164 | } 165 | }, 166 | inputBoxBorderColor: '#505053', 167 | inputStyle: { 168 | backgroundColor: '#333', 169 | color: 'silver' 170 | }, 171 | labelStyle: { 172 | color: 'silver' 173 | } 174 | }, 175 | 176 | navigator: { 177 | handles: { 178 | backgroundColor: '#666', 179 | borderColor: '#AAA' 180 | }, 181 | outlineColor: '#CCC', 182 | maskFill: 'rgba(255,255,255,0.1)', 183 | series: { 184 | color: '#7798BF', 185 | lineColor: '#A6C7ED' 186 | }, 187 | xAxis: { 188 | gridLineColor: '#505053' 189 | } 190 | }, 191 | 192 | scrollbar: { 193 | barBackgroundColor: '#808083', 194 | barBorderColor: '#808083', 195 | buttonArrowColor: '#CCC', 196 | buttonBackgroundColor: '#606063', 197 | buttonBorderColor: '#606063', 198 | rifleColor: '#FFF', 199 | trackBackgroundColor: '#404043', 200 | trackBorderColor: '#404043' 201 | }, 202 | 203 | // special colors for some of the 204 | legendBackgroundColor: 'rgba(0, 0, 0, 0.5)', 205 | background2: '#505053', 206 | dataLabelsColor: '#B0B0B3', 207 | textColor: '#C0C0C0', 208 | contrastTextColor: '#F0F0F3', 209 | maskColor: 'rgba(255,255,255,0.3)' 210 | }; 211 | 212 | // Apply the theme 213 | Highcharts.setOptions(Highcharts.theme); 214 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/gray.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gray theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | Highcharts.theme = { 7 | colors: ["#DDDF0D", "#7798BF", "#55BF3B", "#DF5353", "#aaeeee", "#ff0066", "#eeaaee", 8 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], 9 | chart: { 10 | backgroundColor: { 11 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 12 | stops: [ 13 | [0, 'rgb(96, 96, 96)'], 14 | [1, 'rgb(16, 16, 16)'] 15 | ] 16 | }, 17 | borderWidth: 0, 18 | borderRadius: 0, 19 | plotBackgroundColor: null, 20 | plotShadow: false, 21 | plotBorderWidth: 0 22 | }, 23 | title: { 24 | style: { 25 | color: '#FFF', 26 | font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 27 | } 28 | }, 29 | subtitle: { 30 | style: { 31 | color: '#DDD', 32 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 33 | } 34 | }, 35 | xAxis: { 36 | gridLineWidth: 0, 37 | lineColor: '#999', 38 | tickColor: '#999', 39 | labels: { 40 | style: { 41 | color: '#999', 42 | fontWeight: 'bold' 43 | } 44 | }, 45 | title: { 46 | style: { 47 | color: '#AAA', 48 | font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 49 | } 50 | } 51 | }, 52 | yAxis: { 53 | alternateGridColor: null, 54 | minorTickInterval: null, 55 | gridLineColor: 'rgba(255, 255, 255, .1)', 56 | minorGridLineColor: 'rgba(255,255,255,0.07)', 57 | lineWidth: 0, 58 | tickWidth: 0, 59 | labels: { 60 | style: { 61 | color: '#999', 62 | fontWeight: 'bold' 63 | } 64 | }, 65 | title: { 66 | style: { 67 | color: '#AAA', 68 | font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 69 | } 70 | } 71 | }, 72 | legend: { 73 | itemStyle: { 74 | color: '#CCC' 75 | }, 76 | itemHoverStyle: { 77 | color: '#FFF' 78 | }, 79 | itemHiddenStyle: { 80 | color: '#333' 81 | } 82 | }, 83 | labels: { 84 | style: { 85 | color: '#CCC' 86 | } 87 | }, 88 | tooltip: { 89 | backgroundColor: { 90 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 91 | stops: [ 92 | [0, 'rgba(96, 96, 96, .8)'], 93 | [1, 'rgba(16, 16, 16, .8)'] 94 | ] 95 | }, 96 | borderWidth: 0, 97 | style: { 98 | color: '#FFF' 99 | } 100 | }, 101 | 102 | 103 | plotOptions: { 104 | series: { 105 | nullColor: '#444444' 106 | }, 107 | line: { 108 | dataLabels: { 109 | color: '#CCC' 110 | }, 111 | marker: { 112 | lineColor: '#333' 113 | } 114 | }, 115 | spline: { 116 | marker: { 117 | lineColor: '#333' 118 | } 119 | }, 120 | scatter: { 121 | marker: { 122 | lineColor: '#333' 123 | } 124 | }, 125 | candlestick: { 126 | lineColor: 'white' 127 | } 128 | }, 129 | 130 | toolbar: { 131 | itemStyle: { 132 | color: '#CCC' 133 | } 134 | }, 135 | 136 | navigation: { 137 | buttonOptions: { 138 | symbolStroke: '#DDDDDD', 139 | hoverSymbolStroke: '#FFFFFF', 140 | theme: { 141 | fill: { 142 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 143 | stops: [ 144 | [0.4, '#606060'], 145 | [0.6, '#333333'] 146 | ] 147 | }, 148 | stroke: '#000000' 149 | } 150 | } 151 | }, 152 | 153 | // scroll charts 154 | rangeSelector: { 155 | buttonTheme: { 156 | fill: { 157 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 158 | stops: [ 159 | [0.4, '#888'], 160 | [0.6, '#555'] 161 | ] 162 | }, 163 | stroke: '#000000', 164 | style: { 165 | color: '#CCC', 166 | fontWeight: 'bold' 167 | }, 168 | states: { 169 | hover: { 170 | fill: { 171 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 172 | stops: [ 173 | [0.4, '#BBB'], 174 | [0.6, '#888'] 175 | ] 176 | }, 177 | stroke: '#000000', 178 | style: { 179 | color: 'white' 180 | } 181 | }, 182 | select: { 183 | fill: { 184 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 185 | stops: [ 186 | [0.1, '#000'], 187 | [0.3, '#333'] 188 | ] 189 | }, 190 | stroke: '#000000', 191 | style: { 192 | color: 'yellow' 193 | } 194 | } 195 | } 196 | }, 197 | inputStyle: { 198 | backgroundColor: '#333', 199 | color: 'silver' 200 | }, 201 | labelStyle: { 202 | color: 'silver' 203 | } 204 | }, 205 | 206 | navigator: { 207 | handles: { 208 | backgroundColor: '#666', 209 | borderColor: '#AAA' 210 | }, 211 | outlineColor: '#CCC', 212 | maskFill: 'rgba(16, 16, 16, 0.5)', 213 | series: { 214 | color: '#7798BF', 215 | lineColor: '#A6C7ED' 216 | } 217 | }, 218 | 219 | scrollbar: { 220 | barBackgroundColor: { 221 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 222 | stops: [ 223 | [0.4, '#888'], 224 | [0.6, '#555'] 225 | ] 226 | }, 227 | barBorderColor: '#CCC', 228 | buttonArrowColor: '#CCC', 229 | buttonBackgroundColor: { 230 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 231 | stops: [ 232 | [0.4, '#888'], 233 | [0.6, '#555'] 234 | ] 235 | }, 236 | buttonBorderColor: '#CCC', 237 | rifleColor: '#FFF', 238 | trackBackgroundColor: { 239 | linearGradient: { x1: 0, y1: 0, x2: 0, y2: 1 }, 240 | stops: [ 241 | [0, '#000'], 242 | [1, '#333'] 243 | ] 244 | }, 245 | trackBorderColor: '#666' 246 | }, 247 | 248 | // special colors for some of the demo examples 249 | legendBackgroundColor: 'rgba(48, 48, 48, 0.8)', 250 | background2: 'rgb(70, 70, 70)', 251 | dataLabelsColor: '#444', 252 | textColor: '#E0E0E0', 253 | maskColor: 'rgba(255,255,255,0.3)' 254 | }; 255 | 256 | // Apply the theme 257 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme); 258 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/grid-light.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Grid-light theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | // Load the fonts 7 | Highcharts.createElement('link', { 8 | href: 'https://fonts.googleapis.com/css?family=Dosis:400,600', 9 | rel: 'stylesheet', 10 | type: 'text/css' 11 | }, null, document.getElementsByTagName('head')[0]); 12 | 13 | Highcharts.theme = { 14 | colors: ["#7cb5ec", "#f7a35c", "#90ee7e", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 15 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], 16 | chart: { 17 | backgroundColor: null, 18 | style: { 19 | fontFamily: "Dosis, sans-serif" 20 | } 21 | }, 22 | title: { 23 | style: { 24 | fontSize: '16px', 25 | fontWeight: 'bold', 26 | textTransform: 'uppercase' 27 | } 28 | }, 29 | tooltip: { 30 | borderWidth: 0, 31 | backgroundColor: 'rgba(219,219,216,0.8)', 32 | shadow: false 33 | }, 34 | legend: { 35 | itemStyle: { 36 | fontWeight: 'bold', 37 | fontSize: '13px' 38 | } 39 | }, 40 | xAxis: { 41 | gridLineWidth: 1, 42 | labels: { 43 | style: { 44 | fontSize: '12px' 45 | } 46 | } 47 | }, 48 | yAxis: { 49 | minorTickInterval: 'auto', 50 | title: { 51 | style: { 52 | textTransform: 'uppercase' 53 | } 54 | }, 55 | labels: { 56 | style: { 57 | fontSize: '12px' 58 | } 59 | } 60 | }, 61 | plotOptions: { 62 | candlestick: { 63 | lineColor: '#404048' 64 | } 65 | }, 66 | 67 | 68 | // General 69 | background2: '#F0F0EA' 70 | 71 | }; 72 | 73 | // Apply the theme 74 | Highcharts.setOptions(Highcharts.theme); 75 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/grid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Grid theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | Highcharts.theme = { 7 | colors: ['#058DC7', '#50B432', '#ED561B', '#DDDF00', '#24CBE5', '#64E572', '#FF9655', '#FFF263', '#6AF9C4'], 8 | chart: { 9 | backgroundColor: { 10 | linearGradient: { x1: 0, y1: 0, x2: 1, y2: 1 }, 11 | stops: [ 12 | [0, 'rgb(255, 255, 255)'], 13 | [1, 'rgb(240, 240, 255)'] 14 | ] 15 | }, 16 | borderWidth: 2, 17 | plotBackgroundColor: 'rgba(255, 255, 255, .9)', 18 | plotShadow: true, 19 | plotBorderWidth: 1 20 | }, 21 | title: { 22 | style: { 23 | color: '#000', 24 | font: 'bold 16px "Trebuchet MS", Verdana, sans-serif' 25 | } 26 | }, 27 | subtitle: { 28 | style: { 29 | color: '#666666', 30 | font: 'bold 12px "Trebuchet MS", Verdana, sans-serif' 31 | } 32 | }, 33 | xAxis: { 34 | gridLineWidth: 1, 35 | lineColor: '#000', 36 | tickColor: '#000', 37 | labels: { 38 | style: { 39 | color: '#000', 40 | font: '11px Trebuchet MS, Verdana, sans-serif' 41 | } 42 | }, 43 | title: { 44 | style: { 45 | color: '#333', 46 | fontWeight: 'bold', 47 | fontSize: '12px', 48 | fontFamily: 'Trebuchet MS, Verdana, sans-serif' 49 | 50 | } 51 | } 52 | }, 53 | yAxis: { 54 | minorTickInterval: 'auto', 55 | lineColor: '#000', 56 | lineWidth: 1, 57 | tickWidth: 1, 58 | tickColor: '#000', 59 | labels: { 60 | style: { 61 | color: '#000', 62 | font: '11px Trebuchet MS, Verdana, sans-serif' 63 | } 64 | }, 65 | title: { 66 | style: { 67 | color: '#333', 68 | fontWeight: 'bold', 69 | fontSize: '12px', 70 | fontFamily: 'Trebuchet MS, Verdana, sans-serif' 71 | } 72 | } 73 | }, 74 | legend: { 75 | itemStyle: { 76 | font: '9pt Trebuchet MS, Verdana, sans-serif', 77 | color: 'black' 78 | 79 | }, 80 | itemHoverStyle: { 81 | color: '#039' 82 | }, 83 | itemHiddenStyle: { 84 | color: 'gray' 85 | } 86 | }, 87 | labels: { 88 | style: { 89 | color: '#99b' 90 | } 91 | }, 92 | 93 | navigation: { 94 | buttonOptions: { 95 | theme: { 96 | stroke: '#CCCCCC' 97 | } 98 | } 99 | } 100 | }; 101 | 102 | // Apply the theme 103 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme); 104 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/sand-signika.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sand-Signika theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | // Load the fonts 7 | Highcharts.createElement('link', { 8 | href: 'https://fonts.googleapis.com/css?family=Signika:400,700', 9 | rel: 'stylesheet', 10 | type: 'text/css' 11 | }, null, document.getElementsByTagName('head')[0]); 12 | 13 | // Add the background image to the container 14 | Highcharts.wrap(Highcharts.Chart.prototype, 'getContainer', function (proceed) { 15 | proceed.call(this); 16 | this.container.style.background = 'url(http://www.highcharts.com/samples/graphics/sand.png)'; 17 | }); 18 | 19 | 20 | Highcharts.theme = { 21 | colors: ["#f45b5b", "#8085e9", "#8d4654", "#7798BF", "#aaeeee", "#ff0066", "#eeaaee", 22 | "#55BF3B", "#DF5353", "#7798BF", "#aaeeee"], 23 | chart: { 24 | backgroundColor: null, 25 | style: { 26 | fontFamily: "Signika, serif" 27 | } 28 | }, 29 | title: { 30 | style: { 31 | color: 'black', 32 | fontSize: '16px', 33 | fontWeight: 'bold' 34 | } 35 | }, 36 | subtitle: { 37 | style: { 38 | color: 'black' 39 | } 40 | }, 41 | tooltip: { 42 | borderWidth: 0 43 | }, 44 | legend: { 45 | itemStyle: { 46 | fontWeight: 'bold', 47 | fontSize: '13px' 48 | } 49 | }, 50 | xAxis: { 51 | labels: { 52 | style: { 53 | color: '#6e6e70' 54 | } 55 | } 56 | }, 57 | yAxis: { 58 | labels: { 59 | style: { 60 | color: '#6e6e70' 61 | } 62 | } 63 | }, 64 | plotOptions: { 65 | series: { 66 | shadow: true 67 | }, 68 | candlestick: { 69 | lineColor: '#404048' 70 | }, 71 | map: { 72 | shadow: false 73 | } 74 | }, 75 | 76 | // Highstock specific 77 | navigator: { 78 | xAxis: { 79 | gridLineColor: '#D0D0D8' 80 | } 81 | }, 82 | rangeSelector: { 83 | buttonTheme: { 84 | fill: 'white', 85 | stroke: '#C0C0C8', 86 | 'stroke-width': 1, 87 | states: { 88 | select: { 89 | fill: '#D0D0D8' 90 | } 91 | } 92 | } 93 | }, 94 | scrollbar: { 95 | trackBorderColor: '#C0C0C8' 96 | }, 97 | 98 | // General 99 | background2: '#E0E0E8' 100 | 101 | }; 102 | 103 | // Apply the theme 104 | Highcharts.setOptions(Highcharts.theme); 105 | -------------------------------------------------------------------------------- /websocket/public/static/js/highcharts/themes/skies.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Skies theme for Highcharts JS 3 | * @author Torstein Honsi 4 | */ 5 | 6 | Highcharts.theme = { 7 | colors: ["#514F78", "#42A07B", "#9B5E4A", "#72727F", "#1F949A", "#82914E", "#86777F", "#42A07B"], 8 | chart: { 9 | className: 'skies', 10 | borderWidth: 0, 11 | plotShadow: true, 12 | plotBackgroundImage: 'http://www.highcharts.com/demo/gfx/skies.jpg', 13 | plotBackgroundColor: { 14 | linearGradient: [0, 0, 250, 500], 15 | stops: [ 16 | [0, 'rgba(255, 255, 255, 1)'], 17 | [1, 'rgba(255, 255, 255, 0)'] 18 | ] 19 | }, 20 | plotBorderWidth: 1 21 | }, 22 | title: { 23 | style: { 24 | color: '#3E576F', 25 | font: '16px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 26 | } 27 | }, 28 | subtitle: { 29 | style: { 30 | color: '#6D869F', 31 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 32 | } 33 | }, 34 | xAxis: { 35 | gridLineWidth: 0, 36 | lineColor: '#C0D0E0', 37 | tickColor: '#C0D0E0', 38 | labels: { 39 | style: { 40 | color: '#666', 41 | fontWeight: 'bold' 42 | } 43 | }, 44 | title: { 45 | style: { 46 | color: '#666', 47 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 48 | } 49 | } 50 | }, 51 | yAxis: { 52 | alternateGridColor: 'rgba(255, 255, 255, .5)', 53 | lineColor: '#C0D0E0', 54 | tickColor: '#C0D0E0', 55 | tickWidth: 1, 56 | labels: { 57 | style: { 58 | color: '#666', 59 | fontWeight: 'bold' 60 | } 61 | }, 62 | title: { 63 | style: { 64 | color: '#666', 65 | font: '12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' 66 | } 67 | } 68 | }, 69 | legend: { 70 | itemStyle: { 71 | font: '9pt Trebuchet MS, Verdana, sans-serif', 72 | color: '#3E576F' 73 | }, 74 | itemHoverStyle: { 75 | color: 'black' 76 | }, 77 | itemHiddenStyle: { 78 | color: 'silver' 79 | } 80 | }, 81 | labels: { 82 | style: { 83 | color: '#3E576F' 84 | } 85 | } 86 | }; 87 | 88 | // Apply the theme 89 | var highchartsOptions = Highcharts.setOptions(Highcharts.theme); 90 | -------------------------------------------------------------------------------- /websocket/public/static/js/reconnect.js: -------------------------------------------------------------------------------- 1 | // MIT License: 2 | // 3 | // Copyright (c) 2010-2012, Joe Walnes 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | /** 24 | * This behaves like a WebSocket in every way, except if it fails to connect, 25 | * or it gets disconnected, it will repeatedly poll until it succesfully connects 26 | * again. 27 | * 28 | * It is API compatible, so when you have: 29 | * ws = new WebSocket('ws://....'); 30 | * you can replace with: 31 | * ws = new ReconnectingWebSocket('ws://....'); 32 | * 33 | * The event stream will typically look like: 34 | * onconnecting 35 | * onopen 36 | * onmessage 37 | * onmessage 38 | * onclose // lost connection 39 | * onconnecting 40 | * onopen // sometime later... 41 | * onmessage 42 | * onmessage 43 | * etc... 44 | * 45 | * It is API compatible with the standard WebSocket API. 46 | * 47 | * Latest version: https://github.com/joewalnes/reconnecting-websocket/ 48 | * - Joe Walnes 49 | */ 50 | function ReconnectingWebSocket(url, protocols) { 51 | protocols = protocols || []; 52 | 53 | // These can be altered by calling code. 54 | this.debug = false; 55 | this.reconnectInterval = 1000; 56 | this.timeoutInterval = 2000; 57 | 58 | var self = this; 59 | var ws; 60 | var forcedClose = false; 61 | var timedOut = false; 62 | 63 | this.url = url; 64 | this.protocols = protocols; 65 | this.readyState = WebSocket.CONNECTING; 66 | this.URL = url; // Public API 67 | 68 | this.onopen = function(event) { 69 | }; 70 | 71 | this.onclose = function(event) { 72 | }; 73 | 74 | this.onconnecting = function(event) { 75 | }; 76 | 77 | this.onmessage = function(event) { 78 | }; 79 | 80 | this.onerror = function(event) { 81 | }; 82 | 83 | function connect(reconnectAttempt) { 84 | ws = new WebSocket(url, protocols); 85 | 86 | self.onconnecting(); 87 | if (self.debug || ReconnectingWebSocket.debugAll) { 88 | console.debug('ReconnectingWebSocket', 'attempt-connect', url); 89 | } 90 | 91 | var localWs = ws; 92 | var timeout = setTimeout(function() { 93 | if (self.debug || ReconnectingWebSocket.debugAll) { 94 | console.debug('ReconnectingWebSocket', 'connection-timeout', url); 95 | } 96 | timedOut = true; 97 | localWs.close(); 98 | timedOut = false; 99 | }, self.timeoutInterval); 100 | 101 | ws.onopen = function(event) { 102 | clearTimeout(timeout); 103 | if (self.debug || ReconnectingWebSocket.debugAll) { 104 | console.debug('ReconnectingWebSocket', 'onopen', url); 105 | } 106 | self.readyState = WebSocket.OPEN; 107 | reconnectAttempt = false; 108 | self.onopen(event); 109 | }; 110 | 111 | ws.onclose = function(event) { 112 | clearTimeout(timeout); 113 | ws = null; 114 | if (forcedClose) { 115 | self.readyState = WebSocket.CLOSED; 116 | self.onclose(event); 117 | } else { 118 | self.readyState = WebSocket.CONNECTING; 119 | self.onconnecting(); 120 | if (!reconnectAttempt && !timedOut) { 121 | if (self.debug || ReconnectingWebSocket.debugAll) { 122 | console.debug('ReconnectingWebSocket', 'onclose', url); 123 | } 124 | self.onclose(event); 125 | } 126 | setTimeout(function() { 127 | connect(true); 128 | }, self.reconnectInterval); 129 | } 130 | }; 131 | ws.onmessage = function(event) { 132 | if (self.debug || ReconnectingWebSocket.debugAll) { 133 | console.debug('ReconnectingWebSocket', 'onmessage', url, event.data); 134 | } 135 | self.onmessage(event); 136 | }; 137 | ws.onerror = function(event) { 138 | if (self.debug || ReconnectingWebSocket.debugAll) { 139 | console.debug('ReconnectingWebSocket', 'onerror', url, event); 140 | } 141 | self.onerror(event); 142 | }; 143 | } 144 | connect(url); 145 | 146 | this.send = function(data) { 147 | if (ws) { 148 | if (self.debug || ReconnectingWebSocket.debugAll) { 149 | console.debug('ReconnectingWebSocket', 'send', url, data); 150 | } 151 | return ws.send(data); 152 | } else { 153 | throw 'INVALID_STATE_ERR : Pausing to reconnect websocket'; 154 | } 155 | }; 156 | 157 | this.close = function() { 158 | if (ws) { 159 | forcedClose = true; 160 | ws.close(); 161 | } 162 | }; 163 | 164 | /** 165 | * Additional public API method to refresh the connection if still open (close, re-open). 166 | * For example, if the app suspects bad data / missed heart beats, it can try to refresh. 167 | */ 168 | this.refresh = function() { 169 | if (ws) { 170 | ws.close(); 171 | } 172 | }; 173 | } 174 | 175 | /** 176 | * Setting this to true is the equivalent of setting all instances of ReconnectingWebSocket.debug to true. 177 | */ 178 | ReconnectingWebSocket.debugAll = false; 179 | -------------------------------------------------------------------------------- /websocket/public/static/js/stats.js: -------------------------------------------------------------------------------- 1 | var descriptions = { 2 | 'Processes': { 3 | 'title' : '进程', 4 | 'items' : { 5 | 'r': '运行进程数', 6 | 'b': '阻塞进程数' 7 | }, 8 | 'unit':'个' 9 | }, 10 | 'Memory': { 11 | 'title' : '内存', 12 | 'items' : { 13 | 'swpd': '已使用虚拟内存', 14 | 'free': '空闲物理内存', 15 | 'buff': '已使用缓存', 16 | 'cache': '缓存大小' 17 | }, 18 | 'unit':'B' 19 | }, 20 | 'Swap': { 21 | 'title':'交换内存', 22 | 'items':{ 23 | 'si': '从磁盘中读入的虚拟内存', 24 | 'so': '从虚拟内存中写入磁盘大小' 25 | }, 26 | 'unit':'B' 27 | }, 28 | 'IO': { 29 | 'title':'IO开销', 30 | 'items':{ 31 | 'bi': '从块设备接收的块大小', 32 | 'bo': '从块设备改善的块大小' 33 | }, 34 | 'unit':'个' 35 | }, 36 | 'System': { 37 | 'title':'系统', 38 | 'items':{ 39 | 'ir': '每秒中断次数', 40 | 'cs': '上下文切换次数' 41 | }, 42 | 'unit':'次' 43 | }, 44 | 'CPU': { 45 | 'title':'CPU', 46 | 'items':{ 47 | 'us': '用户CPU时间', 48 | 'sy': '系统CPU时间', 49 | 'id': '空闲CPU时间', 50 | 'wa': '等待IO CPU时间' 51 | }, 52 | 'unit':'秒' 53 | } 54 | } 55 | 56 | var num = 0; 57 | function streamStats() { 58 | var ws = new ReconnectingWebSocket('ws://' + location.host + '/vmstats'); 59 | ws.onopen = function() { 60 | console.log('connect'); 61 | ws.send('hello'); 62 | }; 63 | 64 | ws.onclose = function() { 65 | console.log('disconnect'); 66 | }; 67 | 68 | ws.onmessage = function(e) { 69 | receiveStats(JSON.parse(e.data)); 70 | }; 71 | } 72 | 73 | function initCharts() { 74 | for(var opt in descriptions) { 75 | var dataList = []; 76 | for (var v in descriptions[opt].items) { 77 | dataList.push({ 78 | name: descriptions[opt]['items'][v], 79 | data: [ 80 | [(new Date()).getTime(),0] 81 | ] 82 | }); 83 | } 84 | Highcharts.setOptions({ 85 | global: { 86 | useUTC: false 87 | } 88 | }); 89 | 90 | $('#'+opt+'-canvas').highcharts({ 91 | chart: { 92 | type: 'spline', 93 | animation: Highcharts.svg, 94 | marginRight: 10 95 | }, 96 | title: { 97 | text: descriptions[opt].title 98 | }, 99 | credits : { 100 | enabled:false 101 | }, 102 | xAxis: { 103 | maxPadding : 0.05, 104 | minPadding : 0.05, 105 | type: 'datetime', 106 | tickWidth:5 107 | }, 108 | yAxis: { 109 | title: { 110 | text: descriptions[opt].unit 111 | }, 112 | plotLines: [{ 113 | value: 0, 114 | width: 1, 115 | color: '#808080' 116 | }] 117 | }, 118 | tooltip: { 119 | formatter: function() { 120 | return ''+ this.series.name +'('+num+')
'+ 121 | Highcharts.dateFormat('%H:%M:%S', this.x) +'
'+ 122 | Highcharts.numberFormat(this.y, 2); 123 | } 124 | }, 125 | legend: { 126 | enabled: true 127 | }, 128 | exporting: { 129 | enabled: false 130 | }, 131 | series: dataList 132 | }); 133 | } 134 | } 135 | 136 | function receiveStats(stats) { 137 | console.log(stats); 138 | //var time = (new Date()).getTime(); 139 | var time = stats.time*1000; 140 | for(var opt in descriptions) { 141 | var chart = $('#'+opt+'-canvas').highcharts(); 142 | var i = 0; 143 | for (var v in descriptions[opt].items) { 144 | chart.series[i].addPoint([time, parseInt(stats[v])], true, (num>120?true:false)); 145 | i++; 146 | } 147 | 148 | } 149 | num++; 150 | } 151 | 152 | $(function() { 153 | initCharts(); 154 | streamStats(); 155 | }); -------------------------------------------------------------------------------- /websocket/readme.md: -------------------------------------------------------------------------------- 1 | #基于lua-resty-websocket实现系统负载监控 2 | 3 | 效果预览图: 4 | 5 | ![](https://github.com/shixinke/openresty-practices/blob/master/websocket/vmstats.png) 6 | -------------------------------------------------------------------------------- /websocket/server.lua: -------------------------------------------------------------------------------- 1 | local server = require "resty.websocket.server" 2 | local shell = require 'resty.shell' 3 | local json = require 'cjson' 4 | 5 | local wb, err = server:new{ 6 | timeout = 5000, -- in milliseconds 7 | max_payload_len = 65535, 8 | } 9 | if not wb then 10 | ngx.log(ngx.ERR, "failed to new websocket: ", err) 11 | return ngx.exit(444) 12 | end 13 | 14 | local data, typ, err = wb:recv_frame() 15 | 16 | if not data then 17 | ngx.log(ngx.ERR, "failed to receive a frame: ", err) 18 | return ngx.exit(444) 19 | end 20 | 21 | if typ == "close" then 22 | -- send a close frame back: 23 | 24 | local bytes, err = wb:send_close(1000, "enough, enough!") 25 | if not bytes then 26 | ngx.log(ngx.ERR, "failed to send the close frame: ", err) 27 | return 28 | end 29 | local code = err 30 | ngx.log(ngx.INFO, "closing with status code ", code, " and message ", data) 31 | return 32 | end 33 | 34 | if typ == "ping" then 35 | -- send a pong frame back: 36 | 37 | local bytes, err = wb:send_pong(data) 38 | if not bytes then 39 | ngx.log(ngx.ERR, "failed to send frame: ", err) 40 | return 41 | end 42 | elseif typ == "pong" then 43 | -- just discard the incoming pong frame 44 | 45 | else 46 | ngx.log(ngx.INFO, "received a frame of type ", typ, " and payload ", data) 47 | end 48 | 49 | local res = shell.vmstat() 50 | if res then 51 | res.time = ngx.time() 52 | local data = json.encode(res) 53 | bytes, err = wb:send_text(data) 54 | if not bytes then 55 | ngx.log(ngx.ERR, "failed to send a text frame: ", err) 56 | return ngx.exit(444) 57 | end 58 | end 59 | 60 | 61 | local bytes, err = wb:send_close(1000, "enough, enough!") 62 | if not bytes then 63 | ngx.log(ngx.ERR, "failed to send the close frame: ", err) 64 | return 65 | end 66 | -------------------------------------------------------------------------------- /websocket/vmstats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shixinke/openresty-practices/c34b2322cc2428586eec45ebd4d4b205bad0377e/websocket/vmstats.png --------------------------------------------------------------------------------