فهرست منبع

echarts-convert

zhuth 6 سال پیش
والد
کامیت
630bd6847a
60فایلهای تغییر یافته به همراه4075 افزوده شده و 0 حذف شده
  1. 204 0
      bi-server/src/main/resources/static/echarts-convert/echarts-convert.js
  2. 401 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/ChangeLog
  3. 22 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/LICENSE.BSD
  4. 29 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/README.md
  5. BIN
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/bin/phantomjs.exe
  6. 14 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/.vscode/launch.json
  7. 10 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/arguments.js
  8. 28 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/child_process-examples.js
  9. 52 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/colorwheel.js
  10. BIN
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/colorwheel.png
  11. 10 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/countdown.js
  12. 60 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/detectsniff.js
  13. 24 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/echoToFile.js
  14. 30 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/features.js
  15. 10 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/fibo.js
  16. 3 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/hello.js
  17. 26 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/injectme.js
  18. 24 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/loadspeed.js
  19. 26 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/loadurlwithoutcss.js
  20. 1406 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/modernizr.js
  21. 5 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/module.js
  22. 26 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/netlog.js
  23. 144 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/netsniff.js
  24. 25 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/openurlwithproxy.js
  25. 17 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/outputEncoding.js
  26. 147 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/page_events.js
  27. 18 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/pagecallback.js
  28. 21 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/phantomwebintro.js
  29. 15 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/post.js
  30. 19 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/postjson.js
  31. 35 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/postserver.js
  32. 10 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/printenv.js
  33. 90 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/printheaderfooter.js
  34. 36 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/printmargins.js
  35. 49 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/rasterize.js
  36. 74 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/render_multi_url.js
  37. 181 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/responsive-screenshot.js
  38. 92 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/run-jasmine.js
  39. 94 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/run-jasmine2.js
  40. 77 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/run-qunit.js
  41. 24 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/scandir.js
  42. 45 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/server.js
  43. 35 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/serverkeepalive.js
  44. 43 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/simpleserver.js
  45. 27 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/sleepsort.js
  46. 19 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/stdin-stdout-stderr.js
  47. 10 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/universe.js
  48. 25 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/unrandomize.js
  49. 15 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/useragent.js
  50. 6 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/version.js
  51. 58 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/waitfor.js
  52. 73 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/walk_through_frames.js
  53. 36 0
      bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/third-party.txt
  54. 103 0
      bi-server/src/main/resources/static/echarts-convert/script/base64util.js
  55. 0 0
      bi-server/src/main/resources/static/echarts-convert/script/echarts.min.js
  56. 2 0
      bi-server/src/main/resources/static/echarts-convert/script/test.js
  57. BIN
      bi-server/src/main/resources/static/echarts-convert/tmp/1561360006221.png
  58. BIN
      bi-server/src/main/resources/static/echarts-convert/tmp/1561360109645.png
  59. BIN
      bi-server/src/main/resources/static/echarts-convert/tmp/1561360361518.png
  60. BIN
      bi-server/src/main/resources/static/echarts-convert/tmp/1561432866404.png

+ 204 - 0
bi-server/src/main/resources/static/echarts-convert/echarts-convert.js

@@ -0,0 +1,204 @@
+(function(window, document, undefined) {
+    "use strict";
+
+    // 引入module
+    var system = require('system'), // 获取参数
+        path = phantom.libraryPath;
+
+    /**
+     * phantomJs 全局异常监听
+     * @param msg
+     * @param trace
+     */
+    phantom.onError = function (msg, trace) {
+        var msgStack = ['Convert ERROR: ' + msg];
+        if (trace && trace.length) {
+            msgStack.push('TRACE:');
+            trace.forEach(function (t) {
+                msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
+            });
+        }
+        console.log(msgStack.join('\n'));
+        phantom.exit(1);
+    };
+
+    // ***********************************
+    // Echarts转换器
+    // ***********************************
+    function Convert(params) {
+        this.params = params; // 参数命令
+        this.external = {
+            ECHARTS3: path + '/script/echarts.min.js',
+        }; // 外部js
+    }
+
+    /**
+     * 初始化
+     */
+    Convert.prototype.init = function () {
+        var params = this.parseArgs(this.params);
+        console.log('params', JSON.stringify(params, null, 4));
+        this.check(params);
+        this.client(JSON.parse(params.opt));
+    };
+
+    /**
+     * 解析参数
+     */
+    Convert.prototype.parseArgs = function(args) {
+        var Base64 = require( path + '/script/base64util.js');
+        var obj = {};
+        if(args.length > 1) {
+            obj['opt'] = Base64.decode(args[1]);
+        }
+        return obj;
+    };
+
+    /**
+     * 参数检查
+     * @param params
+     */
+    Convert.prototype.check = function (params) {
+        if (undefined === params.opt) {
+            this.error("option argument missing -o, --opt <json>");
+        }else {
+            var isJson = this.checkJson(params.opt);
+            if (!isJson) {
+                this.error("--opt <json> args not json string");
+            }
+        }
+    };
+
+    /**
+     * 检查是否是json字符串
+     * @param value
+     * @returns {boolean}
+     */
+    Convert.prototype.checkJson = function (value) {
+        var re = /^\{[\s\S]*\}$|^\[[\s\S]*\]$/;
+        // 类型为string
+        if (typeof value !== 'string') {
+            return false;
+        }
+        // 正则验证
+        if (!re.test(value)) {
+            return false;
+        }
+        // 是否能解析
+        try {
+            JSON.parse(value);
+        } catch (err) {
+            return false;
+        }
+        return true;
+    };
+
+    /**
+     * 访问渲染
+     * @param params
+     * @param fn
+     */
+    Convert.prototype.client = function (option) {
+        var page = require('webpage').create(); // 客户端
+        var convert = this,
+            external = this.external,
+            output,
+            outputPath = path + '/tmp/' + new Date().getTime() + '.png';
+
+        /**
+         * 输出
+         * @param content 内容
+         * @param success 是否成功
+         */
+        output = function (content, success, msg) {
+            console.log(success ? "[SUCCESS]:" : "[ERROR]:" + content);
+            page.close();
+            convert.exit(params);// exit
+        };
+
+        /**
+         * 页面console监听
+         * @param msg
+         * @param lineNum
+         * @param sourceId
+         */
+        page.onConsoleMessage = function (msg, lineNum, sourceId) {
+            console.log(msg);
+        };
+
+        /**
+         * 页面错误监听
+         * @param msg
+         * @param trace
+         */
+        page.onError = function (msg, trace) {
+            output('', false, msg); // 失败,返回错误信息
+        };
+
+        // 空白页
+        page.open("about:blank", function (status) {
+            // 注入依赖js包
+            var hasEchart = page.injectJs(external.ECHARTS3);
+
+            // 检查js是否引用成功
+            if (!hasEchart) {
+                output("Could not found " + external.ECHARTS3, false);
+            }
+
+            // 创建echarts
+            page.evaluate(createEchartsDom, option);
+            // 定义剪切范围,如果定义则截取全屏
+            page.clipRect = {
+                top: 0,
+                left: 0,
+                width: '100%',
+                height: '100%'
+            };
+            page.render(outputPath);
+            convert.exit();
+        });
+    };
+    
+    /**
+     * 创建eCharts Dom层
+     * @param params 参数
+     */
+    function createEchartsDom(options) {
+        console.log('createEchartsDom', JSON.stringify(options));
+        // 取消动画,否则生成图片过快,会出现无数据
+        if (options !== undefined) {
+            options.animation = false;
+        }
+
+        // body背景设置为白色
+        document.body.style.background = '#fff';
+        var container = document.createElement('div');
+        container.id = 'container';
+        container.style.width = '100%';
+        container.style.height = '100%';
+        document.body.appendChild(container);
+
+        var eChart = echarts.init(container);
+        eChart.setOption(options);
+        return eChart.getDataURL();
+    }
+
+    /**
+     * 错误信息打印并退出
+     * @param str 错误信息
+     */
+    Convert.prototype.error = function (str) {
+        console.log("Error:" + str);
+        this.exit();
+    };
+
+    /**
+     * 退出
+     */
+    Convert.prototype.exit = function () {
+        phantom.exit();
+    };
+
+    // 构建,入口
+    new Convert(system.args).init();
+}());

+ 401 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/ChangeLog

@@ -0,0 +1,401 @@
+Please see also http://phantomjs.org/releases.html.
+
+2016-01-23: Version 2.1.0
+
+    New features
+
+      * Upgraded Qt to 5.5.1 (issue #13377)
+      * Added support for SSL Client Authentication (issue #11275)
+      * Added support for context menu event (issue #11429)
+      * Allow remote debugging to use random port assigned by the OS (issue #13432)
+
+    Improvements
+
+      * Allow outer context to access arbitrary URLs (issue #11217)
+      * Fixed --local-storage-path and localStoragePath config option (issue #11596)
+      * Restored --local-url-access=no regression (issue #13412)
+      * Fixed an issue with loading JS modules contains a last-line comment (issue #12868)
+      * Fixed an issue with returning binary content in WebServer module (issue #13026)
+      * Fixed encoded URL loading on Windows (issue #12953)
+      * Fixed building with GCC 5 (issue #13518)
+      * Fixed file upload (issue #12506)
+      * Fixed latest OS detection (issue #13829)
+
+2015-01-23: Version 2.0.0
+
+    New features
+
+      * Switched to Qt 5 and updated WebKit (issue 10448)
+      * Implemented clearing of memory cache (issue 10357)
+      * Added support for HTTP header change for every request (issue 11299)
+
+    Improvements
+
+      * Fixed rendering of CJK text by always linking the codecs (issue 10249)
+      * Ensured onResourceReceived is still fired on an error (issue 11163)
+      * Fixed possible crash in handling network requests (issue 11252)
+      * Removed hardcoded GhostDriver launching message (issue 12681)
+      * Allowed disk cache more than 2 GB (issue 12303)
+
+    Examples
+
+      * Netsniff example should exit when fails to load (issue 11333)
+
+2014-01-25: Version 1.9.7
+
+      * Reverted to GhostDriver 1.1.0 instead of 1.1.1 (issue 11915)
+      * Fixed another warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
+
+2014-01-20: Version 1.9.6
+
+      * Updated GhostDriver to version 1.1.1 (issue 11877, 11893)
+
+2014-01-19: Version 1.9.3
+
+      * Fixed CoreText performance note on OS X 10.9 (issue 11418)
+      * Fixed warning of obsolete userSpaceScaleFactor on OS X 10.9 (issue 11612)
+
+2013-09-06: Version 1.9.2
+
+      * Fixed graphical artifacts with transparent background on Windows (issue 11276, 11007, 11366)
+      * Updated GhostDriver to version 1.0.4 (issue 11452)
+
+2013-06-04: Version 1.9.1
+
+    Critical bug fixes:
+
+      * Fixed problems with specifying proxy server (issue 10811, 11117)
+      * Fixed UTF-8 encoding with system.stdout and system.stderr (issue 11162)
+      * Ensured that onResourceReceived will be always invoked (issue 11163)
+      * Fixed module loading from an absolute path on Windows (issue 11165)
+      * Fixed typo in the command-line option for setting the cache size (11219)
+      * Fixed possible crash when handling network requests (issue 11252, 11338)
+
+2013-03-20: Version 1.9.0 "Sakura"
+
+    New features
+
+      * Added spawn and execFile to execute external programs (issue 10219)
+      * Added the ability to abort network requests (issue 10230)
+      * Added system access to stdin, stdout, and stderr (issue 10333)
+      * Added support for custom CA certificates location (issue 10916)
+      * Added seek function to the File stream (issue 10937)
+      * Implemented file read for a specified number of bytes (issue 10938)
+      * Added a callback to handle network error (issue 10954, 10997)
+      * Added custom encoding support when opening a page (issue 11043)
+      * Implemented require.stub() support for a factory function (issue 11044)
+      * Added page loading indicator and progress (issue 11091)
+      * Added a timeout option for network requests (issue 11129)
+
+    Improvements
+
+      * Fixed the build on FreeBSD (issue 10597)
+      * Ensured a consistent 72 dpi for Linux headless rendering (issue 10659)
+      * Fixed possible PDF error due to invalid CreationDate field (issue 10663)
+      * Fixed crash when uploading non existing files (issue 10941)
+      * Improved the autocomplete internal of the interactive/REPL mode (issue 10943)
+      * Fixed possible crash when accessing inline frames (issue 10947)
+      * Changed Linux binary package setup to be built on CentOS 5 (issue 10963)
+      * Extended SSL ignore setting to synchronous XHR (issue 10985)
+      * Added convenient constants for modifier keys (issue 11056)
+      * Fixed incorrect date handling in the cookies (issue 11068)
+      * Updated GhostDriver to version 1.0.3 (issue 11146)
+
+    Examples
+
+      * Fixed invalid data URI in the netsniff example (issue 10740)
+      * Implemented a new weather example (issue 10794)
+      * Fixed rendering issues in render_multi_url (issue 11021)
+      * Fixed proper event sequence in page_events example (issue 11028)
+      * Miscellanous tweaks (issue 11082)
+
+2013-03-02: Version 1.8.2
+
+    Critical bug fixes:
+
+      * Fixed possible PDF error due to invalid CreationDate field (issue 663)
+      * Fixed crash when uploading non existing files (issue 941)
+      * Fixed possible crash when accessing inline frames (issue 947)
+      * Extended SSL ignore setting to synchronous XHR (issue 985)
+      * Fixed incorrect date handling in the cookies (issue 1068)
+
+2013-01-06: Version 1.8.1
+
+    Critical bug fix:
+
+      * Mac OS X: Fix possible crash when using some TrueType fonts (issue 690)
+
+2012-12-21: Version 1.8.0 "Blue Winter Rose"
+
+    New features
+
+      * Integrated GhostDriver as the WebDriver implementation (issue 49)
+      * Added an option to specify the SSL protocol (issue 174)
+      * Added encoding support for WebServer's response (issue 505)
+      * Added process ID (PID) to the System module (issue 769)
+      * Added properties to obtain page and frame title (issue 799)
+      * Added page navigation methods (issue 808)
+      * Added support for modifier keys in keyboard events (issue 835)
+      * Added onFilePicker callback for more generic file upload API (issue 843)
+      * Added the ability to set the page content and location (issue 909)
+
+    Improvements
+
+      * Fixed date parsing in ISO8601 format (issue 187, 267)
+      * Fixed window.location (issue 530, 632)
+      * Deregistered multiple callback handler (issue 807)
+      * Fixed sending of double-click events (issue 848)
+      * Increases maximum number of redirects (issue 849)
+      * Fixed keycodes sent for lowercase characters (issue 852)
+      * Fixed a regression in table row page break (issue 880)
+      * Completed the CoffeeScript version of the examples (issue 907)
+      * Updated Qt to version 4.8.4 (issue 918)
+      * Fixed potential hang in some example scripts (issue 922)
+
+2012-09-22: Version 1.7.0 "Blazing Star"
+
+    New features
+
+      * Added a module system modelled after CommonJS/Node.js (issue 47)
+      * Added support for window pop-up (issue 151)
+      * Static build on Linux (issue 413)
+      * Added run-time detection of SSL support (issue 484)
+      * Added more events support (issue 492, 712)
+      * Added support for disabling automatic proxy detection (issue 580)
+      * Provided page closing callback (issue 678)
+      * Added methods to access URL, frames URL, frame Content (issue 758)
+      * Added more cookies-related API (issue 761)
+
+    Improvements
+
+      * Refactored command-line options handling (issue 55)
+      * Improved the workflow for producing release builds (issue 599)
+      * Improved cookies API and implementation (issue 603, 761)
+      * Improved frame switching API (issue 654)
+      * Fixed iframe handling regression (issue 683)
+      * Fixed OS version number with Windows 8 and Mountain Lion (issue 684, 688)
+      * Fixed HAR navigation info in the netsniff example (issue 733)
+      * Fixed compile warnings with Visual Studio (issue 744)
+      * Removed hacks for static linking on Windows (issue 753)
+      * Added ICO image handling on Windows (issue 779)
+      * Fixed font antialiasing on Windows (issue 785)
+      * Improved Jasmine test runner for Jasmine 1.2 (issue 792)
+
+2012-07-22: Version 1.6.1
+
+    Bug fixes
+
+      * Don't build the deploy in debug mode (issue 599)
+      * Fixed building on Windows (issue 424)
+      * Fixed remote inspector when building statically (issue 430)
+
+2012-06-20: Version 1.6.0 "Lavender"
+
+    New features
+
+      * Added support for passing arguments to WebPage's evaluate (issue 132)
+      * Added callbacks for JavaScript onConfirm and onPrompt (issue 133)
+      * Added stack trace when error occurs (issue 166)
+      * Added support for local storage path and quota (issue 300)
+      * Added initial support for cookies handling (issue 354)
+      * Added support for header footer when printing the page (issue 410, 512)
+      * Added headers support in the loading request (issue 452)
+      * Added support to render the web page as base64-encoded string (issue 547)
+      * Added hooks for navigation event (issue 562)
+      * Added command-line option to show debug messages (issue 575)
+      * Added support for the zoom factor for web page rendering (issue 579)
+      * Added crash reporter for Mac OS X and Linux, based on Google Breakpad (issue 576)
+      * Added 'os' object to the system module (issue 585)
+      * Added support for asynchronous evaluation (issue 593)
+
+    Improvements
+
+      * Fixed remote debugging to work on Mac OS X and Windows (issue 430)
+      * Fixed web server getting the dropped connection for empty response (issue 451)
+      * Fixed text rendered as boxes (squares) on headless Linux (issue 460)
+      * Updated Qt to version 4.8.2 (issue 495)
+      * Updated CoffeeScript compiler to version 1.3.3 (issue 496)
+      * Fixed the build script to detect and use MAKEFLAGS (issue 503)
+      * Fixed the build script to properly pass Qt config flags (issue 507)
+      * Changed Info.plist to be embedded in Mac OS X executable (issue 528)
+      * Fixed wrong module require in the imagebin example (issue 536)
+      * Fixed example scripts to exit with the right exit code (issue 544)
+      * Fixed build failure with glib 2.31.0+ (issue 559)
+      * Fixed error handler failures in some cases (issue 589)
+      * Fixed Twitter-related examples to work with the new site (issue 609)
+
+2012-03-20: Version 1.5.0 "Ghost Flower"
+
+    New features
+
+      * Added interactive mode, also known as REPL (issue 252)
+      * Added setting for web security, to allow cross domain XHR (issue 28)
+      * Added error handler for WebPage object (issue 166)
+      * Added support for custom HTTP header in the network request (issue 77)
+      * Added support for read write encoding in the file system module (issue 367)
+      * Added remote debugging support on Linux (issue 6)
+      * Added support for proxy authentication (issue 105)
+      * Added System module, to retrieve environment variables (issue 271) and arguments (issue 276)
+      * Added fs.readLink function (issue 329)
+      * Added support for reading and writing binary data (issue 400)
+      * Added support to retrieve request data in the WebServer? module (issue 340)
+      * Added support for individual top/bottom/left/right print margins (issue 388)
+      * Added command-line option --help (issue 347)
+      * Added short command-line options -v and -h (issue 408)
+      * Removed support for Flash and other plugins (issue 418)
+
+    Bug fixes
+
+      * Fixed multiple console.log arguments (issue 36)
+      * Fixed file upload (issue 307)
+      * Fixed the web server instance to be asynchronous (issue 326) and still support Keep Alive (issue 416)
+      * Workaround Qt 4.8.0 crash due to empty URL scheme (issue 365)
+      * Fixed a Content-Type problem where POST does not work (issue 337)
+      * Fixed reading body request in the web server even without specific Content-Type (issue 439)
+      * Fixed Jasmine test runner with Jasmine 1.1 (issue 402)
+      * Fixed request URL formatting in the web server (issue 437)
+      * Don't display debugging and warning messages (issue 323)
+
+2011-12-31: Version 1.4.1
+
+    Bug fixes
+
+      * Fix setting the proxy type (issue 266)
+      * Workaround for file upload regression (issue 307)
+      * Fix extraneous messsages in non-debug mode (issue 323)
+
+2011-12-22: Version 1.4.0 "Glory of the Snow"
+
+    New features
+
+      * Added embedded HTTP server (issue 115)
+      * Added convenient build script for Linux (issue 197)
+      * Added support for SOCKS5 proxy (issue 266)
+      * Updated CoffeeScript compiler to version 1.2 (issue 312)
+
+    Bug fixes
+
+      * Fix potential crash in QUrl with Qt 4.8 (issue 304)
+      * Fix bug in CookieJar with QSettings and string (PyPhantomJS issue 10)
+      * Prevent showing the icon on Mac OS X Dock (issue 281)
+
+    Examples
+
+      * Added a new example to detect browsers sniffing (issue 263)
+      * Added HTTP server example (issue 115)
+
+2011-09-23: Version 1.3.0 "Water Lily"
+
+    Bug fixes
+
+      * Fixed open() and POST method, without specifying the finished handler
+      * Fixed script execution warning dialog (issue 165)
+      * Added WebPage.release() to free the web page from memory (issue 154)
+      * Added special handling of about:blank (issue 235)
+      * Made a separate network access manager for each page (issue 190)
+
+    New features
+
+      * Introduced file system API based on CommonJS Filesystem proposal (issue 129)
+      * Added support for persistent cookies (issue 91)
+      * Added event handling, currently only for mouse events (issue 234)
+      * Added page scroll position (issue 162)
+      * Added HTTP authentication support (issue 45)
+      * Added callback for page initialization (issue 143)
+      * Added support to specify script and output encoding (issue 186)
+      * Added option to allow local content to do cross-domain access (issue 28)
+      * Added support to apply configurations from a JSON file (issue 180)
+      * Added a convenient WebPage initialization construction (issue 206)
+      * Added option to limit the size of disk cache (issue 220)
+
+    Examples
+
+      * Added a new example on using Modernizr to detect features (issue 144)
+      * Fixed pizza.js example to use Mobile Yelp (issue 200)
+      * Fixed netsniff.coffee example due to wrong indentation (issue 225)
+      * Added an example to show live network traffic (issue 227)
+      * Added an example demonstrating different output encodings (issue 186)
+
+2011-06-21: Version 1.2.0 "Birds of Paradise"
+
+    Version 1.2.0 is a major update. It introduces a whole set of new API.
+
+    Bug fixes
+
+      * Fixed rendering a very large web page (issue 54)
+      * Fixed reporting of CoffeeScript compile error (issue 125)
+
+    New features
+
+      * Added callback for console message (issue 12)
+      * Improved security model via WebPage object (issue 41)
+      * Added support for POST, HEAD, PUT, and DELETE (issue 88)
+      * Scripts filename is now passed as phantom.scriptName
+      * Added callback to capture resource requests and responses (issue 2)
+      * Added the ability to load external JavaScript (issue 32)
+
+    Examples
+
+      * Ported examples to use WebPage object
+      * Added a new example to upload an image to imagebin.org
+      * Added a new example to show HTTP POST feature
+      * Added a new example to sniff network traffic and save it in HAR format
+
+
+2011-04-27: Version 1.1.0 "Cherry Blossom"
+
+    Fixed the script loading to use UTF-8 encoding (Yasuhiro Matsumoto).
+
+    Added check for system proxy setting (Yasuhiro Matsumoto).
+
+    Fixed building with Cygwin and Qt 4.5 (John Dalton).
+
+    Added a new example: driver for QUnit tests (Łukasz Korecki).
+
+    Fixed issue #20: problem with JPG transparent color (Alessandro Portale).
+
+    Fixed issue #9: ignore first line starting with #! (Matthias, aka fourplusone).
+
+    Fixed issue #7: support for file upload for form submission (Matthias, aka fourplusone).
+
+    Fixed issue #35: support for disabling images loading (Ariya Hidayat).
+
+    Fixed issue #14: enable or disable plugins (Ariya Hidayat).
+
+    Added a new example: using Canvas to produce the color wheel (Ariya Hidayat).
+
+    Added support for rasterizing as GIF image (Ariya Hidayat).
+
+    Added support for CoffeeScript (Ariya Hidayat).
+
+    Fixed issue #19: option for setting the proxy (Clint Berry, Ariya Hidayat).
+
+    Python implementation using PyQt (James Roe).
+
+    Fixed issue #17: Specify paper size for PDF export (Alessandro Portale).
+
+    Fixed issue #60: Win32 and OS/2 icon files (Salvador Parra Camacho).
+
+    Added clipping rectangle to the render function (Wouter de Bie).
+
+    Added an example on sychronous waiting (Gabor Torok).
+
+    Added command line option to use disk cache (Jon Turner).
+
+    Added text extracting example (Weston Ruter).
+
+    Fixed issue #93: Build with Qt < 4.7 (Ariya Hidayat).
+
+    Ported all examples to CoffeeScript (Robert Gieseke).
+
+2011-01-17: Version 1.0.0
+
+    Initial launch.
+
+    The API is centralized at the 'phantom' object (as child of
+    window object) which has the properties: args, content,
+    loadStatus, state, userAgent, version, viewportSize, and
+    the following functions: exit, open, render, sleep.
+
+    Several examples are included, among others: web page rasterizer,
+    weather service, headless test framework driver, and many others.

+ 22 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/LICENSE.BSD

@@ -0,0 +1,22 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+  * Neither the name of the <organization> nor the
+    names of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 29 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/README.md

@@ -0,0 +1,29 @@
+# [PhantomJS](http://phantomjs.org) - Scriptable Headless WebKit
+
+PhantomJS ([phantomjs.org](http://phantomjs.org)) is a headless WebKit scriptable with JavaScript.  The latest [stable release](http://phantomjs.org/release-2.0.html) is version 2.0.
+
+**Note**: Please **do not** create a GitHub pull request **without** reading the [Contribution Guide](https://github.com/ariya/phantomjs/blob/master/CONTRIBUTING.md) first. Failure to do so may result in the rejection of the pull request.
+
+## Use Cases
+
+- **Headless web testing**. Lightning-fast testing without the browser is now possible!
+- **Page automation**. [Access and manipulate](http://phantomjs.org/page-automation.html) web pages with the standard DOM API, or with usual libraries like jQuery.
+- **Screen capture**. Programmatically [capture web contents](http://phantomjs.org/screen-capture.html), including CSS, SVG and Canvas. Build server-side web graphics apps, from a screenshot service to a vector chart rasterizer.
+- **Network monitoring**. Automate performance analysis, track [page loading](http://phantomjs.org/network-monitoring.html) and export as standard HAR format.
+
+## Features
+
+- **Multiplatform**, available on major operating systems: Windows, Mac OS X, Linux, and other Unices.
+- **Fast and native implementation** of web standards: DOM, CSS, JavaScript, Canvas, and SVG. No emulation!
+- **Pure headless (no X11) on Linux**, ideal for continuous integration systems. Also runs on Amazon EC2, Heroku, and Iron.io.
+- **Easy to install**: [Download](http://phantomjs.org/download.html), unpack, and start having fun in just 5 minutes.
+
+## Questions?
+
+- Explore the complete [documentation](http://phantomjs.org/documentation/).
+- Read tons of [user articles](http://phantomjs.org/buzz.html) on using PhantomJS.
+- Join the [mailing-list](http://groups.google.com/group/phantomjs) and discuss with other PhantomJS fans.
+
+PhantomJS is free software/open source, and is distributed under the [BSD license](http://opensource.org/licenses/BSD-3-Clause). It contains third-party code, see the included `third-party.txt` file for the license information on third-party code.
+
+PhantomJS is created and maintained by [Ariya Hidayat](http://ariya.ofilabs.com/about) (Twitter: [@ariyahidayat](http://twitter.com/ariyahidayat)), with the help of [many contributors](https://github.com/ariya/phantomjs/contributors). Follow the official Twitter stream [@PhantomJS](http://twitter.com/PhantomJS) to get the frequent development updates.

BIN
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/bin/phantomjs.exe


+ 14 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/.vscode/launch.json

@@ -0,0 +1,14 @@
+{
+    // 使用 IntelliSense 了解相关属性。 
+    // 悬停以查看现有属性的描述。
+    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Launch Program",
+            "program": "${workspaceFolder}\\hello.js"
+        }
+    ]
+}

+ 10 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/arguments.js

@@ -0,0 +1,10 @@
+"use strict";
+var system = require('system');
+if (system.args.length === 1) {
+    console.log('Try to pass some args when invoking this script!');
+} else {
+    system.args.forEach(function (arg, i) {
+            console.log(i + ': ' + arg);
+    });
+}
+phantom.exit();

+ 28 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/child_process-examples.js

@@ -0,0 +1,28 @@
+"use strict";
+var spawn = require("child_process").spawn
+var execFile = require("child_process").execFile
+
+var child = spawn("ls", ["-lF", "/rooot"])
+
+child.stdout.on("data", function (data) {
+  console.log("spawnSTDOUT:", JSON.stringify(data))
+})
+
+child.stderr.on("data", function (data) {
+  console.log("spawnSTDERR:", JSON.stringify(data))
+})
+
+child.on("exit", function (code) {
+  console.log("spawnEXIT:", code)
+})
+
+//child.kill("SIGKILL")
+
+execFile("ls", ["-lF", "/usr"], null, function (err, stdout, stderr) {
+  console.log("execFileSTDOUT:", JSON.stringify(stdout))
+  console.log("execFileSTDERR:", JSON.stringify(stderr))
+})
+
+setTimeout(function () {
+  phantom.exit(0)
+}, 2000)

+ 52 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/colorwheel.js

@@ -0,0 +1,52 @@
+"use strict";
+var page = require('webpage').create();
+page.viewportSize = { width: 400, height : 400 };
+page.content = '<html><body><canvas id="surface"></canvas></body></html>';
+page.evaluate(function() {
+    var el = document.getElementById('surface'),
+        context = el.getContext('2d'),
+        width = window.innerWidth,
+        height = window.innerHeight,
+        cx = width / 2,
+        cy = height / 2,
+        radius = width  / 2.3,
+        imageData,
+        pixels,
+        hue, sat, value,
+        i = 0, x, y, rx, ry, d,
+        f, g, p, u, v, w, rgb;
+
+    el.width = width;
+    el.height = height;
+    imageData = context.createImageData(width, height);
+    pixels = imageData.data;
+
+    for (y = 0; y < height; y = y + 1) {
+        for (x = 0; x < width; x = x + 1, i = i + 4) {
+            rx = x - cx;
+            ry = y - cy;
+            d = rx * rx + ry * ry;
+            if (d < radius * radius) {
+                hue = 6 * (Math.atan2(ry, rx) + Math.PI) / (2 * Math.PI);
+                sat = Math.sqrt(d) / radius;
+                g = Math.floor(hue);
+                f = hue - g;
+                u = 255 * (1 - sat);
+                v = 255 * (1 - sat * f);
+                w = 255 * (1 - sat * (1 - f));
+                pixels[i] = [255, v, u, u, w, 255, 255][g];
+                pixels[i + 1] = [w, 255, 255, v, u, u, w][g];
+                pixels[i + 2] = [u, u, w, 255, 255, v, u][g];
+                pixels[i + 3] = 255;
+            }
+        }
+    }
+
+    context.putImageData(imageData, 0, 0);
+    document.body.style.backgroundColor = 'white';
+    document.body.style.margin = '0px';
+});
+
+page.render('colorwheel.png');
+
+phantom.exit();

BIN
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/colorwheel.png


+ 10 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/countdown.js

@@ -0,0 +1,10 @@
+"use strict";
+var t = 10,
+    interval = setInterval(function(){
+        if ( t > 0 ) {
+            console.log(t--);
+        } else {
+            console.log("BLAST OFF!");
+            phantom.exit();
+        }
+    }, 1000);

+ 60 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/detectsniff.js

@@ -0,0 +1,60 @@
+// Detect if a web page sniffs the user agent or not.
+
+"use strict";
+var page = require('webpage').create(),
+    system = require('system'),
+    sniffed,
+    address;
+
+page.onInitialized = function () {
+    page.evaluate(function () {
+
+        (function () {
+            var userAgent = window.navigator.userAgent,
+                platform = window.navigator.platform;
+
+            window.navigator = {
+                appCodeName: 'Mozilla',
+                appName: 'Netscape',
+                cookieEnabled: false,
+                sniffed: false
+            };
+
+            window.navigator.__defineGetter__('userAgent', function () {
+                window.navigator.sniffed = true;
+                return userAgent;
+            });
+
+            window.navigator.__defineGetter__('platform', function () {
+                window.navigator.sniffed = true;
+                return platform;
+            });
+        })();
+    });
+};
+
+if (system.args.length === 1) {
+    console.log('Usage: detectsniff.js <some URL>');
+    phantom.exit(1);
+} else {
+    address = system.args[1];
+    console.log('Checking ' + address + '...');
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('FAIL to load the address');
+            phantom.exit();
+        } else {
+            window.setTimeout(function () {
+                sniffed = page.evaluate(function () {
+                    return navigator.sniffed;
+                });
+                if (sniffed) {
+                    console.log('The page tried to sniff the user agent.');
+                } else {
+                    console.log('The page did not try to sniff the user agent.');
+                }
+                phantom.exit();
+            }, 1500);
+        }
+    });
+}

+ 24 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/echoToFile.js

@@ -0,0 +1,24 @@
+// echoToFile.js - Write in a given file all the parameters passed on the CLI
+"use strict";
+var fs = require('fs'),
+    system = require('system');
+
+if (system.args.length < 3) {
+    console.log("Usage: echoToFile.js DESTINATION_FILE <arguments to echo...>");
+    phantom.exit(1);
+} else {
+    var content = '',
+        f = null,
+        i;
+    for ( i= 2; i < system.args.length; ++i ) {
+        content += system.args[i] + (i === system.args.length-1 ? '' : ' ');
+    }
+
+    try {
+        fs.write(system.args[1], content, 'w');
+    } catch(e) {
+        console.log(e);
+    }
+
+    phantom.exit();
+}

+ 30 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/features.js

@@ -0,0 +1,30 @@
+"use strict";
+var feature, supported = [], unsupported = [];
+
+phantom.injectJs('modernizr.js');
+console.log('Detected features (using Modernizr ' + Modernizr._version + '):');
+for (feature in Modernizr) {
+    if (Modernizr.hasOwnProperty(feature)) {
+        if (feature[0] !== '_' && typeof Modernizr[feature] !== 'function' &&
+            feature !== 'input' && feature !== 'inputtypes') {
+            if (Modernizr[feature]) {
+                supported.push(feature);
+            } else {
+                unsupported.push(feature);
+            }
+        }
+    }
+}
+
+console.log('');
+console.log('Supported:');
+supported.forEach(function (e) {
+    console.log('  ' + e);
+});
+
+console.log('');
+console.log('Not supported:');
+unsupported.forEach(function (e) {
+    console.log('  ' + e);
+});
+phantom.exit();

+ 10 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/fibo.js

@@ -0,0 +1,10 @@
+"use strict";
+var fibs = [0, 1];
+var ticker = window.setInterval(function () {
+    console.log(fibs[fibs.length - 1]);
+    fibs.push(fibs[fibs.length - 1] + fibs[fibs.length - 2]);
+    if (fibs.length > 10) {
+        window.clearInterval(ticker);
+        phantom.exit();
+    }
+}, 300);

+ 3 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/hello.js

@@ -0,0 +1,3 @@
+"use strict";
+console.log('Hello, world!');
+phantom.exit();

+ 26 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/injectme.js

@@ -0,0 +1,26 @@
+// Use 'page.injectJs()' to load the script itself in the Page context
+
+"use strict";
+if ( typeof(phantom) !== "undefined" ) {
+    var page = require('webpage').create();
+
+    // Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
+    page.onConsoleMessage = function(msg) {
+        console.log(msg);
+    };
+
+    page.onAlert = function(msg) {
+        console.log(msg);
+    };
+
+    console.log("* Script running in the Phantom context.");
+    console.log("* Script will 'inject' itself in a page...");
+    page.open("about:blank", function(status) {
+        if ( status === "success" ) {
+            console.log(page.injectJs("injectme.js") ? "... done injecting itself!" : "... fail! Check the $PWD?!");
+        }
+        phantom.exit();
+    });
+} else {
+    alert("* Script running in the Page context.");
+}

+ 24 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/loadspeed.js

@@ -0,0 +1,24 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system'),
+    t, address;
+
+if (system.args.length === 1) {
+    console.log('Usage: loadspeed.js <some URL>');
+    phantom.exit(1);
+} else {
+    t = Date.now();
+    address = system.args[1];
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('FAIL to load the address');
+        } else {
+            t = Date.now() - t;
+            console.log('Page title is ' + page.evaluate(function () {
+                return document.title;
+            }));
+            console.log('Loading time ' + t + ' msec');
+        }
+        phantom.exit();
+    });
+}

+ 26 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/loadurlwithoutcss.js

@@ -0,0 +1,26 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system');
+
+if (system.args.length < 2) {
+    console.log('Usage: loadurlwithoutcss.js URL');
+    phantom.exit();
+}
+
+var address = system.args[1];
+
+page.onResourceRequested = function(requestData, request) {
+    if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData.headers['Content-Type'] == 'text/css') {
+        console.log('The url of the request is matching. Aborting: ' + requestData['url']);
+        request.abort();
+    }
+};
+
+page.open(address, function(status) {
+    if (status === 'success') {
+        phantom.exit();
+    } else {
+        console.log('Unable to load the address!');
+        phantom.exit();
+    }
+});

+ 1406 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/modernizr.js

@@ -0,0 +1,1406 @@
+/*!
+ * Modernizr v2.8.2
+ * www.modernizr.com
+ *
+ * Copyright (c) Faruk Ates, Paul Irish, Alex Sexton
+ * Available under the BSD and MIT licenses: www.modernizr.com/license/
+ */
+
+/*
+ * Modernizr tests which native CSS3 and HTML5 features are available in
+ * the current UA and makes the results available to you in two ways:
+ * as properties on a global Modernizr object, and as classes on the
+ * <html> element. This information allows you to progressively enhance
+ * your pages with a granular level of control over the experience.
+ *
+ * Modernizr has an optional (not included) conditional resource loader
+ * called Modernizr.load(), based on Yepnope.js (yepnopejs.com).
+ * To get a build that includes Modernizr.load(), as well as choosing
+ * which tests to include, go to www.modernizr.com/download/
+ *
+ * Authors        Faruk Ates, Paul Irish, Alex Sexton
+ * Contributors   Ryan Seddon, Ben Alman
+ */
+
+window.Modernizr = (function( window, document, undefined ) {
+
+    var version = '2.8.2',
+
+    Modernizr = {},
+
+    /*>>cssclasses*/
+    // option for enabling the HTML classes to be added
+    enableClasses = true,
+    /*>>cssclasses*/
+
+    docElement = document.documentElement,
+
+    /**
+     * Create our "modernizr" element that we do most feature tests on.
+     */
+    mod = 'modernizr',
+    modElem = document.createElement(mod),
+    mStyle = modElem.style,
+
+    /**
+     * Create the input element for various Web Forms feature tests.
+     */
+    inputElem /*>>inputelem*/ = document.createElement('input') /*>>inputelem*/ ,
+
+    /*>>smile*/
+    smile = ':)',
+    /*>>smile*/
+
+    toString = {}.toString,
+
+    // TODO :: make the prefixes more granular
+    /*>>prefixes*/
+    // List of property values to set for css tests. See ticket #21
+    prefixes = ' -webkit- -moz- -o- -ms- '.split(' '),
+    /*>>prefixes*/
+
+    /*>>domprefixes*/
+    // Following spec is to expose vendor-specific style properties as:
+    //   elem.style.WebkitBorderRadius
+    // and the following would be incorrect:
+    //   elem.style.webkitBorderRadius
+
+    // Webkit ghosts their properties in lowercase but Opera & Moz do not.
+    // Microsoft uses a lowercase `ms` instead of the correct `Ms` in IE8+
+    //   erik.eae.net/archives/2008/03/10/21.48.10/
+
+    // More here: github.com/Modernizr/Modernizr/issues/issue/21
+    omPrefixes = 'Webkit Moz O ms',
+
+    cssomPrefixes = omPrefixes.split(' '),
+
+    domPrefixes = omPrefixes.toLowerCase().split(' '),
+    /*>>domprefixes*/
+
+    /*>>ns*/
+    ns = {'svg': 'http://www.w3.org/2000/svg'},
+    /*>>ns*/
+
+    tests = {},
+    inputs = {},
+    attrs = {},
+
+    classes = [],
+
+    slice = classes.slice,
+
+    featureName, // used in testing loop
+
+
+    /*>>teststyles*/
+    // Inject element with style element and some CSS rules
+    injectElementWithStyles = function( rule, callback, nodes, testnames ) {
+
+      var style, ret, node, docOverflow,
+          div = document.createElement('div'),
+          // After page load injecting a fake body doesn't work so check if body exists
+          body = document.body,
+          // IE6 and 7 won't return offsetWidth or offsetHeight unless it's in the body element, so we fake it.
+          fakeBody = body || document.createElement('body');
+
+      if ( parseInt(nodes, 10) ) {
+          // In order not to give false positives we create a node for each test
+          // This also allows the method to scale for unspecified uses
+          while ( nodes-- ) {
+              node = document.createElement('div');
+              node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
+              div.appendChild(node);
+          }
+      }
+
+      // <style> elements in IE6-9 are considered 'NoScope' elements and therefore will be removed
+      // when injected with innerHTML. To get around this you need to prepend the 'NoScope' element
+      // with a 'scoped' element, in our case the soft-hyphen entity as it won't mess with our measurements.
+      // msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx
+      // Documents served as xml will throw if using &shy; so use xml friendly encoded version. See issue #277
+      style = ['&#173;','<style id="s', mod, '">', rule, '</style>'].join('');
+      div.id = mod;
+      // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
+      // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
+      (body ? div : fakeBody).innerHTML += style;
+      fakeBody.appendChild(div);
+      if ( !body ) {
+          //avoid crashing IE8, if background image is used
+          fakeBody.style.background = '';
+          //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
+          fakeBody.style.overflow = 'hidden';
+          docOverflow = docElement.style.overflow;
+          docElement.style.overflow = 'hidden';
+          docElement.appendChild(fakeBody);
+      }
+
+      ret = callback(div, rule);
+      // If this is done after page load we don't want to remove the body so check if body exists
+      if ( !body ) {
+          fakeBody.parentNode.removeChild(fakeBody);
+          docElement.style.overflow = docOverflow;
+      } else {
+          div.parentNode.removeChild(div);
+      }
+
+      return !!ret;
+
+    },
+    /*>>teststyles*/
+
+    /*>>mq*/
+    // adapted from matchMedia polyfill
+    // by Scott Jehl and Paul Irish
+    // gist.github.com/786768
+    testMediaQuery = function( mq ) {
+
+      var matchMedia = window.matchMedia || window.msMatchMedia;
+      if ( matchMedia ) {
+        return matchMedia(mq) && matchMedia(mq).matches || false;
+      }
+
+      var bool;
+
+      injectElementWithStyles('@media ' + mq + ' { #' + mod + ' { position: absolute; } }', function( node ) {
+        bool = (window.getComputedStyle ?
+                  getComputedStyle(node, null) :
+                  node.currentStyle)['position'] == 'absolute';
+      });
+
+      return bool;
+
+     },
+     /*>>mq*/
+
+
+    /*>>hasevent*/
+    //
+    // isEventSupported determines if a given element supports the given event
+    // kangax.github.com/iseventsupported/
+    //
+    // The following results are known incorrects:
+    //   Modernizr.hasEvent("webkitTransitionEnd", elem) // false negative
+    //   Modernizr.hasEvent("textInput") // in Webkit. github.com/Modernizr/Modernizr/issues/333
+    //   ...
+    isEventSupported = (function() {
+
+      var TAGNAMES = {
+        'select': 'input', 'change': 'input',
+        'submit': 'form', 'reset': 'form',
+        'error': 'img', 'load': 'img', 'abort': 'img'
+      };
+
+      function isEventSupported( eventName, element ) {
+
+        element = element || document.createElement(TAGNAMES[eventName] || 'div');
+        eventName = 'on' + eventName;
+
+        // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
+        var isSupported = eventName in element;
+
+        if ( !isSupported ) {
+          // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
+          if ( !element.setAttribute ) {
+            element = document.createElement('div');
+          }
+          if ( element.setAttribute && element.removeAttribute ) {
+            element.setAttribute(eventName, '');
+            isSupported = is(element[eventName], 'function');
+
+            // If property was created, "remove it" (by setting value to `undefined`)
+            if ( !is(element[eventName], 'undefined') ) {
+              element[eventName] = undefined;
+            }
+            element.removeAttribute(eventName);
+          }
+        }
+
+        element = null;
+        return isSupported;
+      }
+      return isEventSupported;
+    })(),
+    /*>>hasevent*/
+
+    // TODO :: Add flag for hasownprop ? didn't last time
+
+    // hasOwnProperty shim by kangax needed for Safari 2.0 support
+    _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
+
+    if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
+      hasOwnProp = function (object, property) {
+        return _hasOwnProperty.call(object, property);
+      };
+    }
+    else {
+      hasOwnProp = function (object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
+        return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
+      };
+    }
+
+    // Adapted from ES5-shim https://github.com/kriskowal/es5-shim/blob/master/es5-shim.js
+    // es5.github.com/#x15.3.4.5
+
+    if (!Function.prototype.bind) {
+      Function.prototype.bind = function bind(that) {
+
+        var target = this;
+
+        if (typeof target != "function") {
+            throw new TypeError();
+        }
+
+        var args = slice.call(arguments, 1),
+            bound = function () {
+
+            if (this instanceof bound) {
+
+              var F = function(){};
+              F.prototype = target.prototype;
+              var self = new F();
+
+              var result = target.apply(
+                  self,
+                  args.concat(slice.call(arguments))
+              );
+              if (Object(result) === result) {
+                  return result;
+              }
+              return self;
+
+            } else {
+
+              return target.apply(
+                  that,
+                  args.concat(slice.call(arguments))
+              );
+
+            }
+
+        };
+
+        return bound;
+      };
+    }
+
+    /**
+     * setCss applies given styles to the Modernizr DOM node.
+     */
+    function setCss( str ) {
+        mStyle.cssText = str;
+    }
+
+    /**
+     * setCssAll extrapolates all vendor-specific css strings.
+     */
+    function setCssAll( str1, str2 ) {
+        return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
+    }
+
+    /**
+     * is returns a boolean for if typeof obj is exactly type.
+     */
+    function is( obj, type ) {
+        return typeof obj === type;
+    }
+
+    /**
+     * contains returns a boolean for if substr is found within str.
+     */
+    function contains( str, substr ) {
+        return !!~('' + str).indexOf(substr);
+    }
+
+    /*>>testprop*/
+
+    // testProps is a generic CSS / DOM property test.
+
+    // In testing support for a given CSS property, it's legit to test:
+    //    `elem.style[styleName] !== undefined`
+    // If the property is supported it will return an empty string,
+    // if unsupported it will return undefined.
+
+    // We'll take advantage of this quick test and skip setting a style
+    // on our modernizr element, but instead just testing undefined vs
+    // empty string.
+
+    // Because the testing of the CSS property names (with "-", as
+    // opposed to the camelCase DOM properties) is non-portable and
+    // non-standard but works in WebKit and IE (but not Gecko or Opera),
+    // we explicitly reject properties with dashes so that authors
+    // developing in WebKit or IE first don't end up with
+    // browser-specific content by accident.
+
+    function testProps( props, prefixed ) {
+        for ( var i in props ) {
+            var prop = props[i];
+            if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
+                return prefixed == 'pfx' ? prop : true;
+            }
+        }
+        return false;
+    }
+    /*>>testprop*/
+
+    // TODO :: add testDOMProps
+    /**
+     * testDOMProps is a generic DOM property test; if a browser supports
+     *   a certain property, it won't return undefined for it.
+     */
+    function testDOMProps( props, obj, elem ) {
+        for ( var i in props ) {
+            var item = obj[props[i]];
+            if ( item !== undefined) {
+
+                // return the property name as a string
+                if (elem === false) return props[i];
+
+                // let's bind a function
+                if (is(item, 'function')){
+                  // default to autobind unless override
+                  return item.bind(elem || obj);
+                }
+
+                // return the unbound function or obj or value
+                return item;
+            }
+        }
+        return false;
+    }
+
+    /*>>testallprops*/
+    /**
+     * testPropsAll tests a list of DOM properties we want to check against.
+     *   We specify literally ALL possible (known and/or likely) properties on
+     *   the element including the non-vendor prefixed one, for forward-
+     *   compatibility.
+     */
+    function testPropsAll( prop, prefixed, elem ) {
+
+        var ucProp  = prop.charAt(0).toUpperCase() + prop.slice(1),
+            props   = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
+
+        // did they call .prefixed('boxSizing') or are we just testing a prop?
+        if(is(prefixed, "string") || is(prefixed, "undefined")) {
+          return testProps(props, prefixed);
+
+        // otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
+        } else {
+          props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
+          return testDOMProps(props, prefixed, elem);
+        }
+    }
+    /*>>testallprops*/
+
+
+    /**
+     * Tests
+     * -----
+     */
+
+    // The *new* flexbox
+    // dev.w3.org/csswg/css3-flexbox
+
+    tests['flexbox'] = function() {
+      return testPropsAll('flexWrap');
+    };
+
+    // The *old* flexbox
+    // www.w3.org/TR/2009/WD-css3-flexbox-20090723/
+
+    tests['flexboxlegacy'] = function() {
+        return testPropsAll('boxDirection');
+    };
+
+    // On the S60 and BB Storm, getContext exists, but always returns undefined
+    // so we actually have to call getContext() to verify
+    // github.com/Modernizr/Modernizr/issues/issue/97/
+
+    tests['canvas'] = function() {
+        var elem = document.createElement('canvas');
+        return !!(elem.getContext && elem.getContext('2d'));
+    };
+
+    tests['canvastext'] = function() {
+        return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
+    };
+
+    // webk.it/70117 is tracking a legit WebGL feature detect proposal
+
+    // We do a soft detect which may false positive in order to avoid
+    // an expensive context creation: bugzil.la/732441
+
+    tests['webgl'] = function() {
+        return !!window.WebGLRenderingContext;
+    };
+
+    /*
+     * The Modernizr.touch test only indicates if the browser supports
+     *    touch events, which does not necessarily reflect a touchscreen
+     *    device, as evidenced by tablets running Windows 7 or, alas,
+     *    the Palm Pre / WebOS (touch) phones.
+     *
+     * Additionally, Chrome (desktop) used to lie about its support on this,
+     *    but that has since been rectified: crbug.com/36415
+     *
+     * We also test for Firefox 4 Multitouch Support.
+     *
+     * For more info, see: modernizr.github.com/Modernizr/touch.html
+     */
+
+    tests['touch'] = function() {
+        var bool;
+
+        if(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) {
+          bool = true;
+        } else {
+          injectElementWithStyles(['@media (',prefixes.join('touch-enabled),('),mod,')','{#modernizr{top:9px;position:absolute}}'].join(''), function( node ) {
+            bool = node.offsetTop === 9;
+          });
+        }
+
+        return bool;
+    };
+
+
+    // geolocation is often considered a trivial feature detect...
+    // Turns out, it's quite tricky to get right:
+    //
+    // Using !!navigator.geolocation does two things we don't want. It:
+    //   1. Leaks memory in IE9: github.com/Modernizr/Modernizr/issues/513
+    //   2. Disables page caching in WebKit: webk.it/43956
+    //
+    // Meanwhile, in Firefox < 8, an about:config setting could expose
+    // a false positive that would throw an exception: bugzil.la/688158
+
+    tests['geolocation'] = function() {
+        return 'geolocation' in navigator;
+    };
+
+
+    tests['postmessage'] = function() {
+      return !!window.postMessage;
+    };
+
+
+    // Chrome incognito mode used to throw an exception when using openDatabase
+    // It doesn't anymore.
+    tests['websqldatabase'] = function() {
+      return !!window.openDatabase;
+    };
+
+    // Vendors had inconsistent prefixing with the experimental Indexed DB:
+    // - Webkit's implementation is accessible through webkitIndexedDB
+    // - Firefox shipped moz_indexedDB before FF4b9, but since then has been mozIndexedDB
+    // For speed, we don't test the legacy (and beta-only) indexedDB
+    tests['indexedDB'] = function() {
+      return !!testPropsAll("indexedDB", window);
+    };
+
+    // documentMode logic from YUI to filter out IE8 Compat Mode
+    //   which false positives.
+    tests['hashchange'] = function() {
+      return isEventSupported('hashchange', window) && (document.documentMode === undefined || document.documentMode > 7);
+    };
+
+    // Per 1.6:
+    // This used to be Modernizr.historymanagement but the longer
+    // name has been deprecated in favor of a shorter and property-matching one.
+    // The old API is still available in 1.6, but as of 2.0 will throw a warning,
+    // and in the first release thereafter disappear entirely.
+    tests['history'] = function() {
+      return !!(window.history && history.pushState);
+    };
+
+    tests['draganddrop'] = function() {
+        var div = document.createElement('div');
+        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
+    };
+
+    // FF3.6 was EOL'ed on 4/24/12, but the ESR version of FF10
+    // will be supported until FF19 (2/12/13), at which time, ESR becomes FF17.
+    // FF10 still uses prefixes, so check for it until then.
+    // for more ESR info, see: mozilla.org/en-US/firefox/organizations/faq/
+    tests['websockets'] = function() {
+        return 'WebSocket' in window || 'MozWebSocket' in window;
+    };
+
+
+    // css-tricks.com/rgba-browser-support/
+    tests['rgba'] = function() {
+        // Set an rgba() color and check the returned value
+
+        setCss('background-color:rgba(150,255,150,.5)');
+
+        return contains(mStyle.backgroundColor, 'rgba');
+    };
+
+    tests['hsla'] = function() {
+        // Same as rgba(), in fact, browsers re-map hsla() to rgba() internally,
+        //   except IE9 who retains it as hsla
+
+        setCss('background-color:hsla(120,40%,100%,.5)');
+
+        return contains(mStyle.backgroundColor, 'rgba') || contains(mStyle.backgroundColor, 'hsla');
+    };
+
+    tests['multiplebgs'] = function() {
+        // Setting multiple images AND a color on the background shorthand property
+        //  and then querying the style.background property value for the number of
+        //  occurrences of "url(" is a reliable method for detecting ACTUAL support for this!
+
+        setCss('background:url(https://),url(https://),red url(https://)');
+
+        // If the UA supports multiple backgrounds, there should be three occurrences
+        //   of the string "url(" in the return value for elemStyle.background
+
+        return (/(url\s*\(.*?){3}/).test(mStyle.background);
+    };
+
+
+
+    // this will false positive in Opera Mini
+    //   github.com/Modernizr/Modernizr/issues/396
+
+    tests['backgroundsize'] = function() {
+        return testPropsAll('backgroundSize');
+    };
+
+    tests['borderimage'] = function() {
+        return testPropsAll('borderImage');
+    };
+
+
+    // Super comprehensive table about all the unique implementations of
+    // border-radius: muddledramblings.com/table-of-css3-border-radius-compliance
+
+    tests['borderradius'] = function() {
+        return testPropsAll('borderRadius');
+    };
+
+    // WebOS unfortunately false positives on this test.
+    tests['boxshadow'] = function() {
+        return testPropsAll('boxShadow');
+    };
+
+    // FF3.0 will false positive on this test
+    tests['textshadow'] = function() {
+        return document.createElement('div').style.textShadow === '';
+    };
+
+
+    tests['opacity'] = function() {
+        // Browsers that actually have CSS Opacity implemented have done so
+        //  according to spec, which means their return values are within the
+        //  range of [0.0,1.0] - including the leading zero.
+
+        setCssAll('opacity:.55');
+
+        // The non-literal . in this regex is intentional:
+        //   German Chrome returns this value as 0,55
+        // github.com/Modernizr/Modernizr/issues/#issue/59/comment/516632
+        return (/^0.55$/).test(mStyle.opacity);
+    };
+
+
+    // Note, Android < 4 will pass this test, but can only animate
+    //   a single property at a time
+    //   goo.gl/v3V4Gp
+    tests['cssanimations'] = function() {
+        return testPropsAll('animationName');
+    };
+
+
+    tests['csscolumns'] = function() {
+        return testPropsAll('columnCount');
+    };
+
+
+    tests['cssgradients'] = function() {
+        /**
+         * For CSS Gradients syntax, please see:
+         * webkit.org/blog/175/introducing-css-gradients/
+         * developer.mozilla.org/en/CSS/-moz-linear-gradient
+         * developer.mozilla.org/en/CSS/-moz-radial-gradient
+         * dev.w3.org/csswg/css3-images/#gradients-
+         */
+
+        var str1 = 'background-image:',
+            str2 = 'gradient(linear,left top,right bottom,from(#9f9),to(white));',
+            str3 = 'linear-gradient(left top,#9f9, white);';
+
+        setCss(
+             // legacy webkit syntax (FIXME: remove when syntax not in use anymore)
+              (str1 + '-webkit- '.split(' ').join(str2 + str1) +
+             // standard syntax             // trailing 'background-image:'
+              prefixes.join(str3 + str1)).slice(0, -str1.length)
+        );
+
+        return contains(mStyle.backgroundImage, 'gradient');
+    };
+
+
+    tests['cssreflections'] = function() {
+        return testPropsAll('boxReflect');
+    };
+
+
+    tests['csstransforms'] = function() {
+        return !!testPropsAll('transform');
+    };
+
+
+    tests['csstransforms3d'] = function() {
+
+        var ret = !!testPropsAll('perspective');
+
+        // Webkit's 3D transforms are passed off to the browser's own graphics renderer.
+        //   It works fine in Safari on Leopard and Snow Leopard, but not in Chrome in
+        //   some conditions. As a result, Webkit typically recognizes the syntax but
+        //   will sometimes throw a false positive, thus we must do a more thorough check:
+        if ( ret && 'webkitPerspective' in docElement.style ) {
+
+          // Webkit allows this media query to succeed only if the feature is enabled.
+          // `@media (transform-3d),(-webkit-transform-3d){ ... }`
+          injectElementWithStyles('@media (transform-3d),(-webkit-transform-3d){#modernizr{left:9px;position:absolute;height:3px;}}', function( node, rule ) {
+            ret = node.offsetLeft === 9 && node.offsetHeight === 3;
+          });
+        }
+        return ret;
+    };
+
+
+    tests['csstransitions'] = function() {
+        return testPropsAll('transition');
+    };
+
+
+    /*>>fontface*/
+    // @font-face detection routine by Diego Perini
+    // javascript.nwbox.com/CSSSupport/
+
+    // false positives:
+    //   WebOS github.com/Modernizr/Modernizr/issues/342
+    //   WP7   github.com/Modernizr/Modernizr/issues/538
+    tests['fontface'] = function() {
+        var bool;
+
+        injectElementWithStyles('@font-face {font-family:"font";src:url("https://")}', function( node, rule ) {
+          var style = document.getElementById('smodernizr'),
+              sheet = style.sheet || style.styleSheet,
+              cssText = sheet ? (sheet.cssRules && sheet.cssRules[0] ? sheet.cssRules[0].cssText : sheet.cssText || '') : '';
+
+          bool = /src/i.test(cssText) && cssText.indexOf(rule.split(' ')[0]) === 0;
+        });
+
+        return bool;
+    };
+    /*>>fontface*/
+
+    // CSS generated content detection
+    tests['generatedcontent'] = function() {
+        var bool;
+
+        injectElementWithStyles(['#',mod,'{font:0/0 a}#',mod,':after{content:"',smile,'";visibility:hidden;font:3px/1 a}'].join(''), function( node ) {
+          bool = node.offsetHeight >= 3;
+        });
+
+        return bool;
+    };
+
+
+
+    // These tests evaluate support of the video/audio elements, as well as
+    // testing what types of content they support.
+    //
+    // We're using the Boolean constructor here, so that we can extend the value
+    // e.g.  Modernizr.video     // true
+    //       Modernizr.video.ogg // 'probably'
+    //
+    // Codec values from : github.com/NielsLeenheer/html5test/blob/9106a8/index.html#L845
+    //                     thx to NielsLeenheer and zcorpan
+
+    // Note: in some older browsers, "no" was a return value instead of empty string.
+    //   It was live in FF3.5.0 and 3.5.1, but fixed in 3.5.2
+    //   It was also live in Safari 4.0.0 - 4.0.4, but fixed in 4.0.5
+
+    tests['video'] = function() {
+        var elem = document.createElement('video'),
+            bool = false;
+
+        // IE9 Running on Windows Server SKU can cause an exception to be thrown, bug #224
+        try {
+            if ( bool = !!elem.canPlayType ) {
+                bool      = new Boolean(bool);
+                bool.ogg  = elem.canPlayType('video/ogg; codecs="theora"')      .replace(/^no$/,'');
+
+                // Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
+                bool.h264 = elem.canPlayType('video/mp4; codecs="avc1.42E01E"') .replace(/^no$/,'');
+
+                bool.webm = elem.canPlayType('video/webm; codecs="vp8, vorbis"').replace(/^no$/,'');
+            }
+
+        } catch(e) { }
+
+        return bool;
+    };
+
+    tests['audio'] = function() {
+        var elem = document.createElement('audio'),
+            bool = false;
+
+        try {
+            if ( bool = !!elem.canPlayType ) {
+                bool      = new Boolean(bool);
+                bool.ogg  = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
+                bool.mp3  = elem.canPlayType('audio/mpeg;')               .replace(/^no$/,'');
+
+                // Mimetypes accepted:
+                //   developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
+                //   bit.ly/iphoneoscodecs
+                bool.wav  = elem.canPlayType('audio/wav; codecs="1"')     .replace(/^no$/,'');
+                bool.m4a  = ( elem.canPlayType('audio/x-m4a;')            ||
+                              elem.canPlayType('audio/aac;'))             .replace(/^no$/,'');
+            }
+        } catch(e) { }
+
+        return bool;
+    };
+
+
+    // In FF4, if disabled, window.localStorage should === null.
+
+    // Normally, we could not test that directly and need to do a
+    //   `('localStorage' in window) && ` test first because otherwise Firefox will
+    //   throw bugzil.la/365772 if cookies are disabled
+
+    // Also in iOS5 Private Browsing mode, attempting to use localStorage.setItem
+    // will throw the exception:
+    //   QUOTA_EXCEEDED_ERRROR DOM Exception 22.
+    // Peculiarly, getItem and removeItem calls do not throw.
+
+    // Because we are forced to try/catch this, we'll go aggressive.
+
+    // Just FWIW: IE8 Compat mode supports these features completely:
+    //   www.quirksmode.org/dom/html5.html
+    // But IE8 doesn't support either with local files
+
+    tests['localstorage'] = function() {
+        try {
+            localStorage.setItem(mod, mod);
+            localStorage.removeItem(mod);
+            return true;
+        } catch(e) {
+            return false;
+        }
+    };
+
+    tests['sessionstorage'] = function() {
+        try {
+            sessionStorage.setItem(mod, mod);
+            sessionStorage.removeItem(mod);
+            return true;
+        } catch(e) {
+            return false;
+        }
+    };
+
+
+    tests['webworkers'] = function() {
+        return !!window.Worker;
+    };
+
+
+    tests['applicationcache'] = function() {
+        return !!window.applicationCache;
+    };
+
+
+    // Thanks to Erik Dahlstrom
+    tests['svg'] = function() {
+        return !!document.createElementNS && !!document.createElementNS(ns.svg, 'svg').createSVGRect;
+    };
+
+    // specifically for SVG inline in HTML, not within XHTML
+    // test page: paulirish.com/demo/inline-svg
+    tests['inlinesvg'] = function() {
+      var div = document.createElement('div');
+      div.innerHTML = '<svg/>';
+      return (div.firstChild && div.firstChild.namespaceURI) == ns.svg;
+    };
+
+    // SVG SMIL animation
+    tests['smil'] = function() {
+        return !!document.createElementNS && /SVGAnimate/.test(toString.call(document.createElementNS(ns.svg, 'animate')));
+    };
+
+    // This test is only for clip paths in SVG proper, not clip paths on HTML content
+    // demo: srufaculty.sru.edu/david.dailey/svg/newstuff/clipPath4.svg
+
+    // However read the comments to dig into applying SVG clippaths to HTML content here:
+    //   github.com/Modernizr/Modernizr/issues/213#issuecomment-1149491
+    tests['svgclippaths'] = function() {
+        return !!document.createElementNS && /SVGClipPath/.test(toString.call(document.createElementNS(ns.svg, 'clipPath')));
+    };
+
+    /*>>webforms*/
+    // input features and input types go directly onto the ret object, bypassing the tests loop.
+    // Hold this guy to execute in a moment.
+    function webforms() {
+        /*>>input*/
+        // Run through HTML5's new input attributes to see if the UA understands any.
+        // We're using f which is the <input> element created early on
+        // Mike Taylr has created a comprehensive resource for testing these attributes
+        //   when applied to all input types:
+        //   miketaylr.com/code/input-type-attr.html
+        // spec: www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#input-type-attr-summary
+
+        // Only input placeholder is tested while textarea's placeholder is not.
+        // Currently Safari 4 and Opera 11 have support only for the input placeholder
+        // Both tests are available in feature-detects/forms-placeholder.js
+        Modernizr['input'] = (function( props ) {
+            for ( var i = 0, len = props.length; i < len; i++ ) {
+                attrs[ props[i] ] = !!(props[i] in inputElem);
+            }
+            if (attrs.list){
+              // safari false positive's on datalist: webk.it/74252
+              // see also github.com/Modernizr/Modernizr/issues/146
+              attrs.list = !!(document.createElement('datalist') && window.HTMLDataListElement);
+            }
+            return attrs;
+        })('autocomplete autofocus list placeholder max min multiple pattern required step'.split(' '));
+        /*>>input*/
+
+        /*>>inputtypes*/
+        // Run through HTML5's new input types to see if the UA understands any.
+        //   This is put behind the tests runloop because it doesn't return a
+        //   true/false like all the other tests; instead, it returns an object
+        //   containing each input type with its corresponding true/false value
+
+        // Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
+        Modernizr['inputtypes'] = (function(props) {
+
+            for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
+
+                inputElem.setAttribute('type', inputElemType = props[i]);
+                bool = inputElem.type !== 'text';
+
+                // We first check to see if the type we give it sticks..
+                // If the type does, we feed it a textual value, which shouldn't be valid.
+                // If the value doesn't stick, we know there's input sanitization which infers a custom UI
+                if ( bool ) {
+
+                    inputElem.value         = smile;
+                    inputElem.style.cssText = 'position:absolute;visibility:hidden;';
+
+                    if ( /^range$/.test(inputElemType) && inputElem.style.WebkitAppearance !== undefined ) {
+
+                      docElement.appendChild(inputElem);
+                      defaultView = document.defaultView;
+
+                      // Safari 2-4 allows the smiley as a value, despite making a slider
+                      bool =  defaultView.getComputedStyle &&
+                              defaultView.getComputedStyle(inputElem, null).WebkitAppearance !== 'textfield' &&
+                              // Mobile android web browser has false positive, so must
+                              // check the height to see if the widget is actually there.
+                              (inputElem.offsetHeight !== 0);
+
+                      docElement.removeChild(inputElem);
+
+                    } else if ( /^(search|tel)$/.test(inputElemType) ){
+                      // Spec doesn't define any special parsing or detectable UI
+                      //   behaviors so we pass these through as true
+
+                      // Interestingly, opera fails the earlier test, so it doesn't
+                      //  even make it here.
+
+                    } else if ( /^(url|email)$/.test(inputElemType) ) {
+                      // Real url and email support comes with prebaked validation.
+                      bool = inputElem.checkValidity && inputElem.checkValidity() === false;
+
+                    } else {
+                      // If the upgraded input compontent rejects the :) text, we got a winner
+                      bool = inputElem.value != smile;
+                    }
+                }
+
+                inputs[ props[i] ] = !!bool;
+            }
+            return inputs;
+        })('search tel url email datetime date month week time datetime-local number range color'.split(' '));
+        /*>>inputtypes*/
+    }
+    /*>>webforms*/
+
+
+    // End of test definitions
+    // -----------------------
+
+
+
+    // Run through all tests and detect their support in the current UA.
+    // todo: hypothetically we could be doing an array of tests and use a basic loop here.
+    for ( var feature in tests ) {
+        if ( hasOwnProp(tests, feature) ) {
+            // run the test, throw the return value into the Modernizr,
+            //   then based on that boolean, define an appropriate className
+            //   and push it into an array of classes we'll join later.
+            featureName  = feature.toLowerCase();
+            Modernizr[featureName] = tests[feature]();
+
+            classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
+        }
+    }
+
+    /*>>webforms*/
+    // input tests need to run.
+    Modernizr.input || webforms();
+    /*>>webforms*/
+
+
+    /**
+     * addTest allows the user to define their own feature tests
+     * the result will be added onto the Modernizr object,
+     * as well as an appropriate className set on the html element
+     *
+     * @param feature - String naming the feature
+     * @param test - Function returning true if feature is supported, false if not
+     */
+     Modernizr.addTest = function ( feature, test ) {
+       if ( typeof feature == 'object' ) {
+         for ( var key in feature ) {
+           if ( hasOwnProp( feature, key ) ) {
+             Modernizr.addTest( key, feature[ key ] );
+           }
+         }
+       } else {
+
+         feature = feature.toLowerCase();
+
+         if ( Modernizr[feature] !== undefined ) {
+           // we're going to quit if you're trying to overwrite an existing test
+           // if we were to allow it, we'd do this:
+           //   var re = new RegExp("\\b(no-)?" + feature + "\\b");
+           //   docElement.className = docElement.className.replace( re, '' );
+           // but, no rly, stuff 'em.
+           return Modernizr;
+         }
+
+         test = typeof test == 'function' ? test() : test;
+
+         if (typeof enableClasses !== "undefined" && enableClasses) {
+           docElement.className += ' ' + (test ? '' : 'no-') + feature;
+         }
+         Modernizr[feature] = test;
+
+       }
+
+       return Modernizr; // allow chaining.
+     };
+
+
+    // Reset modElem.cssText to nothing to reduce memory footprint.
+    setCss('');
+    modElem = inputElem = null;
+
+    /*>>shiv*/
+    /**
+     * @preserve HTML5 Shiv prev3.7.1 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
+     */
+    ;(function(window, document) {
+        /*jshint evil:true */
+        /** version */
+        var version = '3.7.0';
+
+        /** Preset options */
+        var options = window.html5 || {};
+
+        /** Used to skip problem elements */
+        var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
+
+        /** Not all elements can be cloned in IE **/
+        var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
+
+        /** Detect whether the browser supports default html5 styles */
+        var supportsHtml5Styles;
+
+        /** Name of the expando, to work with multiple documents or to re-shiv one document */
+        var expando = '_html5shiv';
+
+        /** The id for the the documents expando */
+        var expanID = 0;
+
+        /** Cached data for each document */
+        var expandoData = {};
+
+        /** Detect whether the browser supports unknown elements */
+        var supportsUnknownElements;
+
+        (function() {
+          try {
+            var a = document.createElement('a');
+            a.innerHTML = '<xyz></xyz>';
+            //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
+            supportsHtml5Styles = ('hidden' in a);
+
+            supportsUnknownElements = a.childNodes.length == 1 || (function() {
+              // assign a false positive if unable to shiv
+              (document.createElement)('a');
+              var frag = document.createDocumentFragment();
+              return (
+                typeof frag.cloneNode == 'undefined' ||
+                typeof frag.createDocumentFragment == 'undefined' ||
+                typeof frag.createElement == 'undefined'
+              );
+            }());
+          } catch(e) {
+            // assign a false positive if detection fails => unable to shiv
+            supportsHtml5Styles = true;
+            supportsUnknownElements = true;
+          }
+
+        }());
+
+        /*--------------------------------------------------------------------------*/
+
+        /**
+         * Creates a style sheet with the given CSS text and adds it to the document.
+         * @private
+         * @param {Document} ownerDocument The document.
+         * @param {String} cssText The CSS text.
+         * @returns {StyleSheet} The style element.
+         */
+        function addStyleSheet(ownerDocument, cssText) {
+          var p = ownerDocument.createElement('p'),
+          parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
+
+          p.innerHTML = 'x<style>' + cssText + '</style>';
+          return parent.insertBefore(p.lastChild, parent.firstChild);
+        }
+
+        /**
+         * Returns the value of `html5.elements` as an array.
+         * @private
+         * @returns {Array} An array of shived element node names.
+         */
+        function getElements() {
+          var elements = html5.elements;
+          return typeof elements == 'string' ? elements.split(' ') : elements;
+        }
+
+        /**
+         * Returns the data associated to the given document
+         * @private
+         * @param {Document} ownerDocument The document.
+         * @returns {Object} An object of data.
+         */
+        function getExpandoData(ownerDocument) {
+          var data = expandoData[ownerDocument[expando]];
+          if (!data) {
+            data = {};
+            expanID++;
+            ownerDocument[expando] = expanID;
+            expandoData[expanID] = data;
+          }
+          return data;
+        }
+
+        /**
+         * returns a shived element for the given nodeName and document
+         * @memberOf html5
+         * @param {String} nodeName name of the element
+         * @param {Document} ownerDocument The context document.
+         * @returns {Object} The shived element.
+         */
+        function createElement(nodeName, ownerDocument, data){
+          if (!ownerDocument) {
+            ownerDocument = document;
+          }
+          if(supportsUnknownElements){
+            return ownerDocument.createElement(nodeName);
+          }
+          if (!data) {
+            data = getExpandoData(ownerDocument);
+          }
+          var node;
+
+          if (data.cache[nodeName]) {
+            node = data.cache[nodeName].cloneNode();
+          } else if (saveClones.test(nodeName)) {
+            node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
+          } else {
+            node = data.createElem(nodeName);
+          }
+
+          // Avoid adding some elements to fragments in IE < 9 because
+          // * Attributes like `name` or `type` cannot be set/changed once an element
+          //   is inserted into a document/fragment
+          // * Link elements with `src` attributes that are inaccessible, as with
+          //   a 403 response, will cause the tab/window to crash
+          // * Script elements appended to fragments will execute when their `src`
+          //   or `text` property is set
+          return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
+        }
+
+        /**
+         * returns a shived DocumentFragment for the given document
+         * @memberOf html5
+         * @param {Document} ownerDocument The context document.
+         * @returns {Object} The shived DocumentFragment.
+         */
+        function createDocumentFragment(ownerDocument, data){
+          if (!ownerDocument) {
+            ownerDocument = document;
+          }
+          if(supportsUnknownElements){
+            return ownerDocument.createDocumentFragment();
+          }
+          data = data || getExpandoData(ownerDocument);
+          var clone = data.frag.cloneNode(),
+          i = 0,
+          elems = getElements(),
+          l = elems.length;
+          for(;i<l;i++){
+            clone.createElement(elems[i]);
+          }
+          return clone;
+        }
+
+        /**
+         * Shivs the `createElement` and `createDocumentFragment` methods of the document.
+         * @private
+         * @param {Document|DocumentFragment} ownerDocument The document.
+         * @param {Object} data of the document.
+         */
+        function shivMethods(ownerDocument, data) {
+          if (!data.cache) {
+            data.cache = {};
+            data.createElem = ownerDocument.createElement;
+            data.createFrag = ownerDocument.createDocumentFragment;
+            data.frag = data.createFrag();
+          }
+
+
+          ownerDocument.createElement = function(nodeName) {
+            //abort shiv
+            if (!html5.shivMethods) {
+              return data.createElem(nodeName);
+            }
+            return createElement(nodeName, ownerDocument, data);
+          };
+
+          ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
+                                                          'var n=f.cloneNode(),c=n.createElement;' +
+                                                          'h.shivMethods&&(' +
+                                                          // unroll the `createElement` calls
+                                                          getElements().join().replace(/[\w\-]+/g, function(nodeName) {
+            data.createElem(nodeName);
+            data.frag.createElement(nodeName);
+            return 'c("' + nodeName + '")';
+          }) +
+            ');return n}'
+                                                         )(html5, data.frag);
+        }
+
+        /*--------------------------------------------------------------------------*/
+
+        /**
+         * Shivs the given document.
+         * @memberOf html5
+         * @param {Document} ownerDocument The document to shiv.
+         * @returns {Document} The shived document.
+         */
+        function shivDocument(ownerDocument) {
+          if (!ownerDocument) {
+            ownerDocument = document;
+          }
+          var data = getExpandoData(ownerDocument);
+
+          if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
+            data.hasCSS = !!addStyleSheet(ownerDocument,
+                                          // corrects block display not defined in IE6/7/8/9
+                                          'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
+                                            // adds styling not present in IE6/7/8/9
+                                            'mark{background:#FF0;color:#000}' +
+                                            // hides non-rendered elements
+                                            'template{display:none}'
+                                         );
+          }
+          if (!supportsUnknownElements) {
+            shivMethods(ownerDocument, data);
+          }
+          return ownerDocument;
+        }
+
+        /*--------------------------------------------------------------------------*/
+
+        /**
+         * The `html5` object is exposed so that more elements can be shived and
+         * existing shiving can be detected on iframes.
+         * @type Object
+         * @example
+         *
+         * // options can be changed before the script is included
+         * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
+         */
+        var html5 = {
+
+          /**
+           * An array or space separated string of node names of the elements to shiv.
+           * @memberOf html5
+           * @type Array|String
+           */
+          'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video',
+
+          /**
+           * current version of html5shiv
+           */
+          'version': version,
+
+          /**
+           * A flag to indicate that the HTML5 style sheet should be inserted.
+           * @memberOf html5
+           * @type Boolean
+           */
+          'shivCSS': (options.shivCSS !== false),
+
+          /**
+           * Is equal to true if a browser supports creating unknown/HTML5 elements
+           * @memberOf html5
+           * @type boolean
+           */
+          'supportsUnknownElements': supportsUnknownElements,
+
+          /**
+           * A flag to indicate that the document's `createElement` and `createDocumentFragment`
+           * methods should be overwritten.
+           * @memberOf html5
+           * @type Boolean
+           */
+          'shivMethods': (options.shivMethods !== false),
+
+          /**
+           * A string to describe the type of `html5` object ("default" or "default print").
+           * @memberOf html5
+           * @type String
+           */
+          'type': 'default',
+
+          // shivs the document according to the specified `html5` object options
+          'shivDocument': shivDocument,
+
+          //creates a shived element
+          createElement: createElement,
+
+          //creates a shived documentFragment
+          createDocumentFragment: createDocumentFragment
+        };
+
+        /*--------------------------------------------------------------------------*/
+
+        // expose html5
+        window.html5 = html5;
+
+        // shiv the document
+        shivDocument(document);
+
+    }(this, document));
+    /*>>shiv*/
+
+    // Assign private properties to the return object with prefix
+    Modernizr._version      = version;
+
+    // expose these for the plugin API. Look in the source for how to join() them against your input
+    /*>>prefixes*/
+    Modernizr._prefixes     = prefixes;
+    /*>>prefixes*/
+    /*>>domprefixes*/
+    Modernizr._domPrefixes  = domPrefixes;
+    Modernizr._cssomPrefixes  = cssomPrefixes;
+    /*>>domprefixes*/
+
+    /*>>mq*/
+    // Modernizr.mq tests a given media query, live against the current state of the window
+    // A few important notes:
+    //   * If a browser does not support media queries at all (eg. oldIE) the mq() will always return false
+    //   * A max-width or orientation query will be evaluated against the current state, which may change later.
+    //   * You must specify values. Eg. If you are testing support for the min-width media query use:
+    //       Modernizr.mq('(min-width:0)')
+    // usage:
+    // Modernizr.mq('only screen and (max-width:768)')
+    Modernizr.mq            = testMediaQuery;
+    /*>>mq*/
+
+    /*>>hasevent*/
+    // Modernizr.hasEvent() detects support for a given event, with an optional element to test on
+    // Modernizr.hasEvent('gesturestart', elem)
+    Modernizr.hasEvent      = isEventSupported;
+    /*>>hasevent*/
+
+    /*>>testprop*/
+    // Modernizr.testProp() investigates whether a given style property is recognized
+    // Note that the property names must be provided in the camelCase variant.
+    // Modernizr.testProp('pointerEvents')
+    Modernizr.testProp      = function(prop){
+        return testProps([prop]);
+    };
+    /*>>testprop*/
+
+    /*>>testallprops*/
+    // Modernizr.testAllProps() investigates whether a given style property,
+    //   or any of its vendor-prefixed variants, is recognized
+    // Note that the property names must be provided in the camelCase variant.
+    // Modernizr.testAllProps('boxSizing')
+    Modernizr.testAllProps  = testPropsAll;
+    /*>>testallprops*/
+
+
+    /*>>teststyles*/
+    // Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
+    // Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
+    Modernizr.testStyles    = injectElementWithStyles;
+    /*>>teststyles*/
+
+
+    /*>>prefixed*/
+    // Modernizr.prefixed() returns the prefixed or nonprefixed property name variant of your input
+    // Modernizr.prefixed('boxSizing') // 'MozBoxSizing'
+
+    // Properties must be passed as dom-style camelcase, rather than `box-sizing` hypentated style.
+    // Return values will also be the camelCase variant, if you need to translate that to hypenated style use:
+    //
+    //     str.replace(/([A-Z])/g, function(str,m1){ return '-' + m1.toLowerCase(); }).replace(/^ms-/,'-ms-');
+
+    // If you're trying to ascertain which transition end event to bind to, you might do something like...
+    //
+    //     var transEndEventNames = {
+    //       'WebkitTransition' : 'webkitTransitionEnd',
+    //       'MozTransition'    : 'transitionend',
+    //       'OTransition'      : 'oTransitionEnd',
+    //       'msTransition'     : 'MSTransitionEnd',
+    //       'transition'       : 'transitionend'
+    //     },
+    //     transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
+
+    Modernizr.prefixed      = function(prop, obj, elem){
+      if(!obj) {
+        return testPropsAll(prop, 'pfx');
+      } else {
+        // Testing DOM property e.g. Modernizr.prefixed('requestAnimationFrame', window) // 'mozRequestAnimationFrame'
+        return testPropsAll(prop, obj, elem);
+      }
+    };
+    /*>>prefixed*/
+
+
+    /*>>cssclasses*/
+    // Remove "no-js" class from <html> element, if it exists:
+    docElement.className = docElement.className.replace(/(^|\s)no-js(\s|$)/, '$1$2') +
+
+                            // Add the new classes to the <html> element.
+                            (enableClasses ? ' js ' + classes.join(' ') : '');
+    /*>>cssclasses*/
+
+    return Modernizr;
+
+})(this, this.document);

+ 5 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/module.js

@@ -0,0 +1,5 @@
+"use strict";
+var universe = require('./universe');
+universe.start();
+console.log('The answer is ' + universe.answer);
+phantom.exit();

+ 26 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/netlog.js

@@ -0,0 +1,26 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system'),
+    address;
+
+if (system.args.length === 1) {
+    console.log('Usage: netlog.js <some URL>');
+    phantom.exit(1);
+} else {
+    address = system.args[1];
+
+    page.onResourceRequested = function (req) {
+        console.log('requested: ' + JSON.stringify(req, undefined, 4));
+    };
+
+    page.onResourceReceived = function (res) {
+        console.log('received: ' + JSON.stringify(res, undefined, 4));
+    };
+
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('FAIL to load the address');
+        }
+        phantom.exit();
+    });
+}

+ 144 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/netsniff.js

@@ -0,0 +1,144 @@
+"use strict";
+if (!Date.prototype.toISOString) {
+    Date.prototype.toISOString = function () {
+        function pad(n) { return n < 10 ? '0' + n : n; }
+        function ms(n) { return n < 10 ? '00'+ n : n < 100 ? '0' + n : n }
+        return this.getFullYear() + '-' +
+            pad(this.getMonth() + 1) + '-' +
+            pad(this.getDate()) + 'T' +
+            pad(this.getHours()) + ':' +
+            pad(this.getMinutes()) + ':' +
+            pad(this.getSeconds()) + '.' +
+            ms(this.getMilliseconds()) + 'Z';
+    }
+}
+
+function createHAR(address, title, startTime, resources)
+{
+    var entries = [];
+
+    resources.forEach(function (resource) {
+        var request = resource.request,
+            startReply = resource.startReply,
+            endReply = resource.endReply;
+
+        if (!request || !startReply || !endReply) {
+            return;
+        }
+
+        // Exclude Data URI from HAR file because
+        // they aren't included in specification
+        if (request.url.match(/(^data:image\/.*)/i)) {
+            return;
+	}
+
+        entries.push({
+            startedDateTime: request.time.toISOString(),
+            time: endReply.time - request.time,
+            request: {
+                method: request.method,
+                url: request.url,
+                httpVersion: "HTTP/1.1",
+                cookies: [],
+                headers: request.headers,
+                queryString: [],
+                headersSize: -1,
+                bodySize: -1
+            },
+            response: {
+                status: endReply.status,
+                statusText: endReply.statusText,
+                httpVersion: "HTTP/1.1",
+                cookies: [],
+                headers: endReply.headers,
+                redirectURL: "",
+                headersSize: -1,
+                bodySize: startReply.bodySize,
+                content: {
+                    size: startReply.bodySize,
+                    mimeType: endReply.contentType
+                }
+            },
+            cache: {},
+            timings: {
+                blocked: 0,
+                dns: -1,
+                connect: -1,
+                send: 0,
+                wait: startReply.time - request.time,
+                receive: endReply.time - startReply.time,
+                ssl: -1
+            },
+            pageref: address
+        });
+    });
+
+    return {
+        log: {
+            version: '1.2',
+            creator: {
+                name: "PhantomJS",
+                version: phantom.version.major + '.' + phantom.version.minor +
+                    '.' + phantom.version.patch
+            },
+            pages: [{
+                startedDateTime: startTime.toISOString(),
+                id: address,
+                title: title,
+                pageTimings: {
+                    onLoad: page.endTime - page.startTime
+                }
+            }],
+            entries: entries
+        }
+    };
+}
+
+var page = require('webpage').create(),
+    system = require('system');
+
+if (system.args.length === 1) {
+    console.log('Usage: netsniff.js <some URL>');
+    phantom.exit(1);
+} else {
+
+    page.address = system.args[1];
+    page.resources = [];
+
+    page.onLoadStarted = function () {
+        page.startTime = new Date();
+    };
+
+    page.onResourceRequested = function (req) {
+        page.resources[req.id] = {
+            request: req,
+            startReply: null,
+            endReply: null
+        };
+    };
+
+    page.onResourceReceived = function (res) {
+        if (res.stage === 'start') {
+            page.resources[res.id].startReply = res;
+        }
+        if (res.stage === 'end') {
+            page.resources[res.id].endReply = res;
+        }
+    };
+
+    page.open(page.address, function (status) {
+        var har;
+        if (status !== 'success') {
+            console.log('FAIL to load the address');
+            phantom.exit(1);
+        } else {
+            page.endTime = new Date();
+            page.title = page.evaluate(function () {
+                return document.title;
+            });
+            har = createHAR(page.address, page.title, page.startTime, page.resources);
+            console.log(JSON.stringify(har, undefined, 4));
+            phantom.exit();
+        }
+    });
+}

+ 25 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/openurlwithproxy.js

@@ -0,0 +1,25 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system'),
+    host, port, address;
+
+if (system.args.length < 4) {
+    console.log('Usage: openurlwithproxy.js <proxyHost> <proxyPort> <URL>');
+    phantom.exit(1);
+} else {
+    host = system.args[1];
+    port = system.args[2];
+    address = system.args[3];
+    phantom.setProxy(host, port, 'manual', '', '');
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('FAIL to load the address "' +
+                address + '" using proxy "' + host + ':' + port + '"');
+        } else {
+            console.log('Page title is ' + page.evaluate(function () {
+                return document.title;
+            }));
+        }
+        phantom.exit();
+    });
+}

+ 17 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/outputEncoding.js

@@ -0,0 +1,17 @@
+"use strict";
+function helloWorld() {
+	console.log(phantom.outputEncoding + ": こんにちは、世界!");
+}
+
+console.log("Using default encoding...");
+helloWorld();
+
+console.log("\nUsing other encodings...");
+
+var encodings = ["euc-jp", "sjis", "utf8", "System"];
+for (var i = 0; i < encodings.length; i++) {
+    phantom.outputEncoding = encodings[i];
+    helloWorld();
+}
+
+phantom.exit()

+ 147 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/page_events.js

@@ -0,0 +1,147 @@
+// The purpose of this is to show how and when events fire, considering 5 steps
+// happening as follows:
+//
+//      1. Load URL
+//      2. Load same URL, but adding an internal FRAGMENT to it
+//      3. Click on an internal Link, that points to another internal FRAGMENT
+//      4. Click on an external Link, that will send the page somewhere else
+//      5. Close page
+//
+// Take particular care when going through the output, to understand when
+// things happen (and in which order). Particularly, notice what DOESN'T
+// happen during step 3.
+//
+// If invoked with "-v" it will print out the Page Resources as they are
+// Requested and Received.
+//
+// NOTE.1: The "onConsoleMessage/onAlert/onPrompt/onConfirm" events are
+// registered but not used here. This is left for you to have fun with.
+// NOTE.2: This script is not here to teach you ANY JavaScript. It's aweful!
+// NOTE.3: Main audience for this are people new to PhantomJS.
+
+"use strict";
+var sys = require("system"),
+    page = require("webpage").create(),
+    logResources = false,
+    step1url = "http://en.wikipedia.org/wiki/DOM_events",
+    step2url = "http://en.wikipedia.org/wiki/DOM_events#Event_flow";
+
+if (sys.args.length > 1 && sys.args[1] === "-v") {
+    logResources = true;
+}
+
+function printArgs() {
+    var i, ilen;
+    for (i = 0, ilen = arguments.length; i < ilen; ++i) {
+        console.log("    arguments[" + i + "] = " + JSON.stringify(arguments[i]));
+    }
+    console.log("");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+page.onInitialized = function() {
+    console.log("page.onInitialized");
+    printArgs.apply(this, arguments);
+};
+page.onLoadStarted = function() {
+    console.log("page.onLoadStarted");
+    printArgs.apply(this, arguments);
+};
+page.onLoadFinished = function() {
+    console.log("page.onLoadFinished");
+    printArgs.apply(this, arguments);
+};
+page.onUrlChanged = function() {
+    console.log("page.onUrlChanged");
+    printArgs.apply(this, arguments);
+};
+page.onNavigationRequested = function() {
+    console.log("page.onNavigationRequested");
+    printArgs.apply(this, arguments);
+};
+page.onRepaintRequested = function() {
+    console.log("page.onRepaintRequested");
+    printArgs.apply(this, arguments);
+};
+
+if (logResources === true) {
+    page.onResourceRequested = function() {
+        console.log("page.onResourceRequested");
+        printArgs.apply(this, arguments);
+    };
+    page.onResourceReceived = function() {
+        console.log("page.onResourceReceived");
+        printArgs.apply(this, arguments);
+    };
+}
+
+page.onClosing = function() {
+    console.log("page.onClosing");
+    printArgs.apply(this, arguments);
+};
+
+// window.console.log(msg);
+page.onConsoleMessage = function() {
+    console.log("page.onConsoleMessage");
+    printArgs.apply(this, arguments);
+};
+
+// window.alert(msg);
+page.onAlert = function() {
+    console.log("page.onAlert");
+    printArgs.apply(this, arguments);
+};
+// var confirmed = window.confirm(msg);
+page.onConfirm = function() {
+    console.log("page.onConfirm");
+    printArgs.apply(this, arguments);
+};
+// var user_value = window.prompt(msg, default_value);
+page.onPrompt = function() {
+    console.log("page.onPrompt");
+    printArgs.apply(this, arguments);
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+setTimeout(function() {
+    console.log("");
+    console.log("### STEP 1: Load '" + step1url + "'");
+    page.open(step1url);
+}, 0);
+
+setTimeout(function() {
+    console.log("");
+    console.log("### STEP 2: Load '" + step2url + "' (load same URL plus FRAGMENT)");
+    page.open(step2url);
+}, 5000);
+
+setTimeout(function() {
+    console.log("");
+    console.log("### STEP 3: Click on page internal link (aka FRAGMENT)");
+    page.evaluate(function() {
+        var ev = document.createEvent("MouseEvents");
+        ev.initEvent("click", true, true);
+        document.querySelector("a[href='#Event_object']").dispatchEvent(ev);
+    });
+}, 10000);
+
+setTimeout(function() {
+    console.log("");
+    console.log("### STEP 4: Click on page external link");
+    page.evaluate(function() {
+        var ev = document.createEvent("MouseEvents");
+        ev.initEvent("click", true, true);
+        document.querySelector("a[title='JavaScript']").dispatchEvent(ev);
+    });
+}, 15000);
+
+setTimeout(function() {
+    console.log("");
+    console.log("### STEP 5: Close page and shutdown (with a delay)");
+    page.close();
+    setTimeout(function(){
+        phantom.exit();
+    }, 100);
+}, 20000);

+ 18 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/pagecallback.js

@@ -0,0 +1,18 @@
+"use strict";
+var p = require("webpage").create();
+
+p.onConsoleMessage = function(msg) { console.log(msg); };
+
+// Calls to "callPhantom" within the page 'p' arrive here
+p.onCallback = function(msg) {
+    console.log("Received by the 'phantom' main context: "+msg);
+    return "Hello there, I'm coming to you from the 'phantom' context instead";
+};
+
+p.evaluate(function() {
+    // Return-value of the "onCallback" handler arrive here
+    var callbackResponse = window.callPhantom("Hello, I'm coming to you from the 'page' context");
+    console.log("Received by the 'page' context: "+callbackResponse);
+});
+
+phantom.exit();

+ 21 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/phantomwebintro.js

@@ -0,0 +1,21 @@
+// Read the Phantom webpage '#intro' element text using jQuery and "includeJs"
+
+"use strict";
+var page = require('webpage').create();
+
+page.onConsoleMessage = function(msg) {
+    console.log(msg);
+};
+
+page.open("http://phantomjs.org/", function(status) {
+    if (status === "success") {
+        page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
+            page.evaluate(function() {
+                console.log("$(\".explanation\").text() -> " + $(".explanation").text());
+            });
+            phantom.exit(0);
+        });
+    } else {
+      phantom.exit(1);
+    }
+});

+ 15 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/post.js

@@ -0,0 +1,15 @@
+// Example using HTTP POST operation
+
+"use strict";
+var page = require('webpage').create(),
+    server = 'http://posttestserver.com/post.php?dump',
+    data = 'universe=expanding&answer=42';
+
+page.open(server, 'post', data, function (status) {
+    if (status !== 'success') {
+        console.log('Unable to post!');
+    } else {
+        console.log(page.content);
+    }
+    phantom.exit();
+});

+ 19 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/postjson.js

@@ -0,0 +1,19 @@
+// Example using HTTP POST operation
+
+"use strict";
+var page = require('webpage').create(),
+    server = 'http://posttestserver.com/post.php?dump',
+    data = '{"universe": "expanding", "answer": 42}';
+
+var headers = {
+    "Content-Type": "application/json"
+}
+
+page.open(server, 'post', data, headers, function (status) {
+    if (status !== 'success') {
+        console.log('Unable to post!');
+    } else {
+        console.log(page.content);
+    }
+    phantom.exit();
+});

+ 35 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/postserver.js

@@ -0,0 +1,35 @@
+// Example using HTTP POST operation
+
+"use strict";
+var page = require('webpage').create(),
+    server = require('webserver').create(),
+    system = require('system'),
+    data = 'universe=expanding&answer=42';
+
+if (system.args.length !== 2) {
+    console.log('Usage: postserver.js <portnumber>');
+    phantom.exit(1);
+}
+
+var port = system.args[1];
+
+service = server.listen(port, function (request, response) {
+    console.log('Request received at ' + new Date());
+
+    response.statusCode = 200;
+    response.headers = {
+        'Cache': 'no-cache',
+        'Content-Type': 'text/plain;charset=utf-8'
+    };
+    response.write(JSON.stringify(request, null, 4));
+    response.close();
+});
+
+page.open('http://localhost:' + port + '/', 'post', data, function (status) {
+    if (status !== 'success') {
+        console.log('Unable to post!');
+    } else {
+        console.log(page.plainText);
+    }
+    phantom.exit();
+});

+ 10 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/printenv.js

@@ -0,0 +1,10 @@
+var system = require('system'),
+    env = system.env,
+    key;
+
+for (key in env) {
+    if (env.hasOwnProperty(key)) {
+        console.log(key + '=' + env[key]);
+    }
+}
+phantom.exit();

+ 90 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/printheaderfooter.js

@@ -0,0 +1,90 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system');
+
+function someCallback(pageNum, numPages) {
+    return "<h1> someCallback: " + pageNum + " / " + numPages + "</h1>";
+}
+
+if (system.args.length < 3) {
+    console.log('Usage: printheaderfooter.js URL filename');
+    phantom.exit(1);
+} else {
+    var address = system.args[1];
+    var output = system.args[2];
+    page.viewportSize = { width: 600, height: 600 };
+    page.paperSize = {
+        format: 'A4',
+        margin: "1cm",
+        /* default header/footer for pages that don't have custom overwrites (see below) */
+        header: {
+            height: "1cm",
+            contents: phantom.callback(function(pageNum, numPages) {
+                if (pageNum == 1) {
+                    return "";
+                }
+                return "<h1>Header <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
+            })
+        },
+        footer: {
+            height: "1cm",
+            contents: phantom.callback(function(pageNum, numPages) {
+                if (pageNum == numPages) {
+                    return "";
+                }
+                return "<h1>Footer <span style='float:right'>" + pageNum + " / " + numPages + "</span></h1>";
+            })
+        }
+    };
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('Unable to load the address!');
+        } else {
+            /* check whether the loaded page overwrites the header/footer setting,
+               i.e. whether a PhantomJSPriting object exists. Use that then instead
+               of our defaults above.
+
+               example:
+               <html>
+                 <head>
+                   <script type="text/javascript">
+                     var PhantomJSPrinting = {
+                        header: {
+                            height: "1cm",
+                            contents: function(pageNum, numPages) { return pageNum + "/" + numPages; }
+                        },
+                        footer: {
+                            height: "1cm",
+                            contents: function(pageNum, numPages) { return pageNum + "/" + numPages; }
+                        }
+                     };
+                   </script>
+                 </head>
+                 <body><h1>asdfadsf</h1><p>asdfadsfycvx</p></body>
+              </html>
+            */
+            if (page.evaluate(function(){return typeof PhantomJSPrinting == "object";})) {
+                paperSize = page.paperSize;
+                paperSize.header.height = page.evaluate(function() {
+                    return PhantomJSPrinting.header.height;
+                });
+                paperSize.header.contents = phantom.callback(function(pageNum, numPages) {
+                    return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.header.contents(pageNum, numPages);}, pageNum, numPages);
+                });
+                paperSize.footer.height = page.evaluate(function() {
+                    return PhantomJSPrinting.footer.height;
+                });
+                paperSize.footer.contents = phantom.callback(function(pageNum, numPages) {
+                    return page.evaluate(function(pageNum, numPages){return PhantomJSPrinting.footer.contents(pageNum, numPages);}, pageNum, numPages);
+                });
+                page.paperSize = paperSize;
+                console.log(page.paperSize.header.height);
+                console.log(page.paperSize.footer.height);
+            }
+            window.setTimeout(function () {
+                page.render(output);
+                phantom.exit();
+            }, 200);
+        }
+    });
+}

+ 36 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/printmargins.js

@@ -0,0 +1,36 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system');
+
+if (system.args.length < 7) {
+    console.log('Usage: printmargins.js URL filename LEFT TOP RIGHT BOTTOM');
+    console.log('  margin examples: "1cm", "10px", "7mm", "5in"');
+    phantom.exit(1);
+} else {
+    var address = system.args[1];
+    var output = system.args[2];
+    var marginLeft = system.args[3];
+    var marginTop = system.args[4];
+    var marginRight = system.args[5];
+    var marginBottom = system.args[6];
+    page.viewportSize = { width: 600, height: 600 };
+    page.paperSize = {
+        format: 'A4',
+        margin: {
+            left: marginLeft,
+            top: marginTop,
+            right: marginRight,
+            bottom: marginBottom
+        }
+    };
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('Unable to load the address!');
+        } else {
+            window.setTimeout(function () {
+                page.render(output);
+                phantom.exit();
+            }, 200);
+        }
+    });
+}

+ 49 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/rasterize.js

@@ -0,0 +1,49 @@
+"use strict";
+var page = require('webpage').create(),
+    system = require('system'),
+    address, output, size;
+
+if (system.args.length < 3 || system.args.length > 5) {
+    console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]');
+    console.log('  paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"');
+    console.log('  image (png/jpg output) examples: "1920px" entire page, window width 1920px');
+    console.log('                                   "800px*600px" window, clipped to 800x600');
+    phantom.exit(1);
+} else {
+    address = system.args[1];
+    output = system.args[2];
+    page.viewportSize = { width: 600, height: 600 };
+    if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") {
+        size = system.args[3].split('*');
+        page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' }
+                                           : { format: system.args[3], orientation: 'portrait', margin: '1cm' };
+    } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") {
+        size = system.args[3].split('*');
+        if (size.length === 2) {
+            pageWidth = parseInt(size[0], 10);
+            pageHeight = parseInt(size[1], 10);
+            page.viewportSize = { width: pageWidth, height: pageHeight };
+            page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight };
+        } else {
+            console.log("size:", system.args[3]);
+            pageWidth = parseInt(system.args[3], 10);
+            pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any
+            console.log ("pageHeight:",pageHeight);
+            page.viewportSize = { width: pageWidth, height: pageHeight };
+        }
+    }
+    if (system.args.length > 4) {
+        page.zoomFactor = system.args[4];
+    }
+    page.open(address, function (status) {
+        if (status !== 'success') {
+            console.log('Unable to load the address!');
+            phantom.exit(1);
+        } else {
+            window.setTimeout(function () {
+                page.render(output);
+                phantom.exit();
+            }, 200);
+        }
+    });
+}

+ 74 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/render_multi_url.js

@@ -0,0 +1,74 @@
+// Render Multiple URLs to file
+
+"use strict";
+var RenderUrlsToFile, arrayOfUrls, system;
+
+system = require("system");
+
+/*
+Render given urls
+@param array of URLs to render
+@param callbackPerUrl Function called after finishing each URL, including the last URL
+@param callbackFinal Function called after finishing everything
+*/
+RenderUrlsToFile = function(urls, callbackPerUrl, callbackFinal) {
+    var getFilename, next, page, retrieve, urlIndex, webpage;
+    urlIndex = 0;
+    webpage = require("webpage");
+    page = null;
+    getFilename = function() {
+        return "rendermulti-" + urlIndex + ".png";
+    };
+    next = function(status, url, file) {
+        page.close();
+        callbackPerUrl(status, url, file);
+        return retrieve();
+    };
+    retrieve = function() {
+        var url;
+        if (urls.length > 0) {
+            url = urls.shift();
+            urlIndex++;
+            page = webpage.create();
+            page.viewportSize = {
+                width: 800,
+                height: 600
+            };
+            page.settings.userAgent = "Phantom.js bot";
+            return page.open("http://" + url, function(status) {
+                var file;
+                file = getFilename();
+                if (status === "success") {
+                    return window.setTimeout((function() {
+                        page.render(file);
+                        return next(status, url, file);
+                    }), 200);
+                } else {
+                    return next(status, url, file);
+                }
+            });
+        } else {
+            return callbackFinal();
+        }
+    };
+    return retrieve();
+};
+
+arrayOfUrls = null;
+
+if (system.args.length > 1) {
+    arrayOfUrls = Array.prototype.slice.call(system.args, 1);
+} else {
+    console.log("Usage: phantomjs render_multi_url.js [domain.name1, domain.name2, ...]");
+    arrayOfUrls = ["www.google.com", "www.bbc.co.uk", "phantomjs.org"];
+}
+
+RenderUrlsToFile(arrayOfUrls, (function(status, url, file) {
+    if (status !== "success") {
+        return console.log("Unable to render '" + url + "'");
+    } else {
+        return console.log("Rendered '" + url + "' at '" + file + "'");
+    }
+}), function() {
+    return phantom.exit();
+});

+ 181 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/responsive-screenshot.js

@@ -0,0 +1,181 @@
+/**
+ * Captures the full height document even if it's not showing on the screen or captures with the provided range of screen sizes.
+ *
+ * A basic example for taking a screen shot using phantomjs which is sampled for https://nodejs-dersleri.github.io/
+ *
+ * usage : phantomjs responsive-screenshot.js {url} [output format] [doClipping]
+ *
+ * examples >
+ *      phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/
+ *      phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ pdf
+ *      phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ true
+ *      phantomjs responsive-screenshot.js https://nodejs-dersleri.github.io/ png true
+ *
+ * @author Salih sagdilek <salihsagdilek@gmail.com>
+ */
+
+/**
+ * http://phantomjs.org/api/system/property/args.html
+ *
+ * Queries and returns a list of the command-line arguments.
+ * The first one is always the script name, which is then followed by the subsequent arguments.
+ */
+var args = require('system').args;
+/**
+ * http://phantomjs.org/api/fs/
+ *
+ * file system api
+ */
+var fs = require('fs');
+
+/**
+ * http://phantomjs.org/api/webpage/
+ *
+ * Web page api
+ */
+var page = new WebPage();
+
+/**
+ * if url address does not exist, exit phantom
+ */
+if ( 1 === args.length ) {
+    console.log('Url address is required');
+    phantom.exit();
+}
+
+/**
+ *  setup url address (second argument);
+ */
+var urlAddress = args[1].toLowerCase();
+
+
+/**
+ * set output extension format
+ * @type {*}
+ */
+var ext = getFileExtension();
+
+/**
+ * set if clipping ?
+ * @type {boolean}
+ */
+var clipping = getClipping();
+
+/**
+ * setup viewports
+ */
+var viewports = [
+    {
+        width : 1200,
+        height : 800
+    },
+    {
+        width : 1024,
+        height : 768
+    },
+    {
+        width : 768,
+        height : 1024
+    },
+    {
+        width : 480,
+        height : 640
+    },
+    {
+        width : 320,
+        height : 480
+    }
+];
+
+page.open(urlAddress, function (status) {
+    if ( 'success' !== status ) {
+        console.log('Unable to load the url address!');
+    } else {
+        var folder = urlToDir(urlAddress);
+        var output, key;
+
+        function render(n) {
+            if ( !!n ) {
+                key = n - 1;
+                page.viewportSize = viewports[key];
+                if ( clipping ) {
+                    page.clipRect = viewports[key];
+                }
+                output = folder + "/" + getFileName(viewports[key]);
+                console.log('Saving ' + output);
+                page.render(output);
+                render(key);
+            }
+        }
+
+        render(viewports.length);
+    }
+    phantom.exit();
+});
+
+/**
+ * filename generator helper
+ * @param viewport
+ * @returns {string}
+ */
+function getFileName(viewport) {
+    var d = new Date();
+    var date = [
+        d.getUTCFullYear(),
+        d.getUTCMonth() + 1,
+        d.getUTCDate()
+    ];
+    var time = [
+        d.getHours() <= 9 ? '0' + d.getHours() : d.getHours(),
+        d.getMinutes() <= 9 ? '0' + d.getMinutes() : d.getMinutes(),
+        d.getSeconds() <= 9 ? '0' + d.getSeconds() : d.getSeconds(),
+        d.getMilliseconds()
+    ];
+    var resolution = viewport.width + (clipping ? "x" + viewport.height : '');
+
+    return date.join('-') + '_' + time.join('-') + "_" + resolution + ext;
+}
+
+/**
+ * output extension format helper
+ *
+ * @returns {*}
+ */
+function getFileExtension() {
+    if ( 'true' != args[2] && !!args[2] ) {
+        return '.' + args[2];
+    }
+    return '.png';
+}
+
+/**
+ * check if clipping
+ *
+ * @returns {boolean}
+ */
+function getClipping() {
+    if ( 'true' == args[3] ) {
+        return !!args[3];
+    } else if ( 'true' == args[2] ) {
+        return !!args[2];
+    }
+    return false;
+}
+
+/**
+ * url to directory helper
+ *
+ * @param url
+ * @returns {string}
+ */
+function urlToDir(url) {
+    var dir = url
+        .replace(/^(http|https):\/\//, '')
+        .replace(/\/$/, '');
+
+    if ( !fs.makeTree(dir) ) {
+        console.log('"' + dir + '" is NOT created.');
+        phantom.exit();
+    }
+    return dir;
+}

+ 92 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/run-jasmine.js

@@ -0,0 +1,92 @@
+"use strict";
+var system = require('system');
+
+/**
+ * Wait until the test condition is true or a timeout occurs. Useful for waiting
+ * on a server response or for a ui change (fadeIn, etc.) to occur.
+ *
+ * @param testFx javascript condition that evaluates to a boolean,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param onReady what to do when testFx condition is fulfilled,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
+ */
+function waitFor(testFx, onReady, timeOutMillis) {
+    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
+        start = new Date().getTime(),
+        condition = false,
+        interval = setInterval(function() {
+            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
+                // If not time-out yet and condition not yet fulfilled
+                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
+            } else {
+                if(!condition) {
+                    // If condition still not fulfilled (timeout but condition is 'false')
+                    console.log("'waitFor()' timeout");
+                    phantom.exit(1);
+                } else {
+                    // Condition fulfilled (timeout and/or condition is 'true')
+                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
+                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
+                    clearInterval(interval); //< Stop this interval
+                }
+            }
+        }, 100); //< repeat check every 100ms
+};
+
+
+if (system.args.length !== 2) {
+    console.log('Usage: run-jasmine.js URL');
+    phantom.exit(1);
+}
+
+var page = require('webpage').create();
+
+// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
+page.onConsoleMessage = function(msg) {
+    console.log(msg);
+};
+
+page.open(system.args[1], function(status){
+    if (status !== "success") {
+        console.log("Unable to open " + system.args[1]);
+        phantom.exit(1);
+    } else {
+        waitFor(function(){
+            return page.evaluate(function(){
+                return document.body.querySelector('.symbolSummary .pending') === null
+            });
+        }, function(){
+            var exitCode = page.evaluate(function(){
+                try {
+                    console.log('');
+                    console.log(document.body.querySelector('.description').innerText);
+                    var list = document.body.querySelectorAll('.results > #details > .specDetail.failed');
+                    if (list && list.length > 0) {
+                      console.log('');
+                      console.log(list.length + ' test(s) FAILED:');
+                      for (i = 0; i < list.length; ++i) {
+                          var el = list[i],
+                              desc = el.querySelector('.description'),
+                              msg = el.querySelector('.resultMessage.fail');
+                          console.log('');
+                          console.log(desc.innerText);
+                          console.log(msg.innerText);
+                          console.log('');
+                      }
+                      return 1;
+                    } else {
+                      console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText);
+                      return 0;
+                    }
+                } catch (ex) {
+                    console.log(ex);
+                    return 1;
+                }
+            });
+            phantom.exit(exitCode);
+        });
+    }
+});

+ 94 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/run-jasmine2.js

@@ -0,0 +1,94 @@
+"use strict";
+var system = require('system');
+
+/**
+ * Wait until the test condition is true or a timeout occurs. Useful for waiting
+ * on a server response or for a ui change (fadeIn, etc.) to occur.
+ *
+ * @param testFx javascript condition that evaluates to a boolean,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param onReady what to do when testFx condition is fulfilled,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
+ */
+function waitFor(testFx, onReady, timeOutMillis) {
+    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timeout is 3s
+        start = new Date().getTime(),
+        condition = false,
+        interval = setInterval(function() {
+            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
+                // If not time-out yet and condition not yet fulfilled
+                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
+            } else {
+                if(!condition) {
+                    // If condition still not fulfilled (timeout but condition is 'false')
+                    console.log("'waitFor()' timeout");
+                    phantom.exit(1);
+                } else {
+                    // Condition fulfilled (timeout and/or condition is 'true')
+                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
+                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
+                    clearInterval(interval); //< Stop this interval
+                }
+            }
+        }, 100); //< repeat check every 100ms
+};
+
+
+if (system.args.length !== 2) {
+    console.log('Usage: run-jasmine2.js URL');
+    phantom.exit(1);
+}
+
+var page = require('webpage').create();
+
+// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
+page.onConsoleMessage = function(msg) {
+    console.log(msg);
+};
+
+page.open(system.args[1], function(status){
+    if (status !== "success") {
+        console.log("Unable to access network");
+        phantom.exit();
+    } else {
+        waitFor(function(){
+            return page.evaluate(function(){
+                return (document.body.querySelector('.symbolSummary .pending') === null &&
+                        document.body.querySelector('.duration') !== null);
+            });
+        }, function(){
+            var exitCode = page.evaluate(function(){
+                console.log('');
+
+                var title = 'Jasmine';
+                var version = document.body.querySelector('.version').innerText;
+                var duration = document.body.querySelector('.duration').innerText;
+                var banner = title + ' ' + version + ' ' + duration;
+                console.log(banner);
+
+                var list = document.body.querySelectorAll('.results > .failures > .spec-detail.failed');
+                if (list && list.length > 0) {
+                  console.log('');
+                  console.log(list.length + ' test(s) FAILED:');
+                  for (i = 0; i < list.length; ++i) {
+                      var el = list[i],
+                          desc = el.querySelector('.description'),
+                          msg = el.querySelector('.messages > .result-message');
+                      console.log('');
+                      console.log(desc.innerText);
+                      console.log(msg.innerText);
+                      console.log('');
+                  }
+                  return 1;
+                } else {
+                  console.log(document.body.querySelector('.alert > .bar.passed,.alert > .bar.skipped').innerText);
+                  return 0;
+                }
+            });
+            phantom.exit(exitCode);
+        });
+    }
+});

+ 77 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/run-qunit.js

@@ -0,0 +1,77 @@
+"use strict";
+var system = require('system');
+
+/**
+ * Wait until the test condition is true or a timeout occurs. Useful for waiting
+ * on a server response or for a ui change (fadeIn, etc.) to occur.
+ *
+ * @param testFx javascript condition that evaluates to a boolean,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param onReady what to do when testFx condition is fulfilled,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
+ */
+function waitFor(testFx, onReady, timeOutMillis) {
+    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s
+        start = new Date().getTime(),
+        condition = false,
+        interval = setInterval(function() {
+            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
+                // If not time-out yet and condition not yet fulfilled
+                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
+            } else {
+                if(!condition) {
+                    // If condition still not fulfilled (timeout but condition is 'false')
+                    console.log("'waitFor()' timeout");
+                    phantom.exit(1);
+                } else {
+                    // Condition fulfilled (timeout and/or condition is 'true')
+                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
+                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
+                    clearInterval(interval); //< Stop this interval
+                }
+            }
+        }, 100); //< repeat check every 250ms
+};
+
+
+if (system.args.length !== 2) {
+    console.log('Usage: run-qunit.js URL');
+    phantom.exit(1);
+}
+
+var page = require('webpage').create();
+
+// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
+page.onConsoleMessage = function(msg) {
+    console.log(msg);
+};
+
+page.open(system.args[1], function(status){
+    if (status !== "success") {
+        console.log("Unable to access network");
+        phantom.exit(1);
+    } else {
+        waitFor(function(){
+            return page.evaluate(function(){
+                var el = document.getElementById('qunit-testresult');
+                if (el && el.innerText.match('completed')) {
+                    return true;
+                }
+                return false;
+            });
+        }, function(){
+            var failedNum = page.evaluate(function(){
+                var el = document.getElementById('qunit-testresult');
+                console.log(el.innerText);
+                try {
+                    return el.getElementsByClassName('failed')[0].innerHTML;
+                } catch (e) { }
+                return 10000;
+            });
+            phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);
+        });
+    }
+});

+ 24 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/scandir.js

@@ -0,0 +1,24 @@
+// List all the files in a Tree of Directories
+
+"use strict";
+var system = require('system');
+
+if (system.args.length !== 2) {
+    console.log("Usage: phantomjs scandir.js DIRECTORY_TO_SCAN");
+    phantom.exit(1);
+}
+
+var scanDirectory = function (path) {
+    var fs = require('fs');
+    if (fs.exists(path) && fs.isFile(path)) {
+        console.log(path);
+    } else if (fs.isDirectory(path)) {
+        fs.list(path).forEach(function (e) {
+            if ( e !== "." && e !== ".." ) {    //< Avoid loops
+                scanDirectory(path + '/' + e);
+            }
+        });
+    }
+};
+scanDirectory(system.args[1]);
+phantom.exit();

+ 45 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/server.js

@@ -0,0 +1,45 @@
+"use strict";
+var page = require('webpage').create();
+var server = require('webserver').create();
+var system = require('system');
+var host, port;
+
+console.log(system.args);
+if (system.args.length !== 2) {
+    console.log('Usage: server.js <some port>');
+    phantom.exit(1);
+} else {
+    port = system.args[1];
+    var listening = server.listen(port, function (request, response) {
+        console.log("GOT HTTP REQUEST");
+        console.log(JSON.stringify(request, null, 4));
+
+        // we set the headers here
+        response.statusCode = 200;
+        response.headers = {"Cache": "no-cache", "Content-Type": "text/html"};
+        // this is also possible:
+        response.setHeader("foo", "bar");
+        // now we write the body
+        // note: the headers above will now be sent implictly
+        response.write("<html><head><title>YES!</title></head>");
+        // note: writeBody can be called multiple times
+        response.write("<body><p>pretty cool :)</body></html>");
+        response.close();
+    });
+    if (!listening) {
+        console.log("could not create web server listening on port " + port);
+        phantom.exit();
+    }
+    var url = "http://localhost:" + port + "/foo/bar.php?asdf=true";
+    console.log("SENDING REQUEST TO:");
+    console.log(url);
+    page.open(url, function (status) {
+        if (status !== 'success') {
+            console.log('FAIL to load the address');
+        } else {
+            console.log("GOT REPLY FROM SERVER:");
+            console.log(page.content);
+        }
+        phantom.exit();
+    });
+}

+ 35 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/serverkeepalive.js

@@ -0,0 +1,35 @@
+"use strict";
+var port, server, service,
+    system = require('system');
+
+if (system.args.length !== 2) {
+    console.log('Usage: serverkeepalive.js <portnumber>');
+    phantom.exit(1);
+} else {
+    port = system.args[1];
+    server = require('webserver').create();
+
+    service = server.listen(port, { keepAlive: true }, function (request, response) {
+        console.log('Request at ' + new Date());
+        console.log(JSON.stringify(request, null, 4));
+
+        var body = JSON.stringify(request, null, 4);
+        response.statusCode = 200;
+        response.headers = {
+            'Cache': 'no-cache',
+            'Content-Type': 'text/plain',
+            'Connection': 'Keep-Alive',
+            'Keep-Alive': 'timeout=5, max=100',
+            'Content-Length': 3
+        };
+        response.write('abc');
+        response.close();
+    });
+
+    if (service) {
+        console.log('Web server running on port ' + port);
+    } else {
+        console.log('Error: Could not create web server listening on port ' + port);
+        phantom.exit();
+    }
+}

+ 43 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/simpleserver.js

@@ -0,0 +1,43 @@
+"use strict";
+var port, server, service,
+    system = require('system');
+
+if (system.args.length !== 2) {
+    console.log('Usage: simpleserver.js <portnumber>');
+    phantom.exit(1);
+} else {
+    port = system.args[1];
+    server = require('webserver').create();
+
+    service = server.listen(port, function (request, response) {
+
+        console.log('Request at ' + new Date());
+        console.log(JSON.stringify(request, null, 4));
+
+        response.statusCode = 200;
+        response.headers = {
+            'Cache': 'no-cache',
+            'Content-Type': 'text/html'
+        };
+        response.write('<html>');
+        response.write('<head>');
+        response.write('<title>Hello, world!</title>');
+        response.write('</head>');
+        response.write('<body>');
+        response.write('<p>This is from PhantomJS web server.</p>');
+        response.write('<p>Request data:</p>');
+        response.write('<pre>');
+        response.write(JSON.stringify(request, null, 4));
+        response.write('</pre>');
+        response.write('</body>');
+        response.write('</html>');
+        response.close();
+    });
+
+    if (service) {
+        console.log('Web server running on port ' + port);
+    } else {
+        console.log('Error: Could not create web server listening on port ' + port);
+        phantom.exit();
+    }
+}

+ 27 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/sleepsort.js

@@ -0,0 +1,27 @@
+// sleepsort.js - Sort integers from the commandline in a very ridiculous way: leveraging timeouts :P
+
+"use strict";
+var system = require('system');
+
+function sleepSort(array, callback) {
+    var sortedCount = 0,
+        i, len;
+    for ( i = 0, len = array.length; i < len; ++i ) {
+        setTimeout((function(j){
+            return function() {
+                console.log(array[j]);
+                ++sortedCount;
+                (len === sortedCount) && callback();
+            };
+        }(i)), array[i]);
+    }
+}
+
+if ( system.args.length < 2 ) {
+    console.log("Usage: phantomjs sleepsort.js PUT YOUR INTEGERS HERE SEPARATED BY SPACES");
+    phantom.exit(1);
+} else {
+    sleepSort(system.args.slice(1), function() {
+        phantom.exit();
+    });
+}

+ 19 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/stdin-stdout-stderr.js

@@ -0,0 +1,19 @@
+"use strict";
+var system = require('system');
+
+system.stdout.write('Hello, system.stdout.write!');
+system.stdout.writeLine('\nHello, system.stdout.writeLine!');
+
+system.stderr.write('Hello, system.stderr.write!');
+system.stderr.writeLine('\nHello, system.stderr.writeLine!');
+
+system.stdout.writeLine('system.stdin.readLine(): ');
+var line = system.stdin.readLine();
+system.stdout.writeLine(JSON.stringify(line));
+
+// This is essentially a `readAll`
+system.stdout.writeLine('system.stdin.read(5): (ctrl+D to end)');
+var input = system.stdin.read(5);
+system.stdout.writeLine(JSON.stringify(input));
+
+phantom.exit(0);

+ 10 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/universe.js

@@ -0,0 +1,10 @@
+// This is to be used by "module.js" (and "module.coffee") example(s).
+// There should NOT be a "universe.coffee" as only 1 of the 2 would
+//  ever be loaded unless the file extension was specified.
+
+"use strict";
+exports.answer = 42;
+
+exports.start = function () {
+    console.log('Starting the universe....');
+}

+ 25 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/unrandomize.js

@@ -0,0 +1,25 @@
+// Modify global object at the page initialization.
+// In this example, effectively Math.random() always returns 0.42.
+
+"use strict";
+var page = require('webpage').create();
+
+page.onInitialized = function () {
+    page.evaluate(function () {
+        Math.random = function() {
+            return 42 / 100;
+        };
+    });
+};
+
+page.open('http://ariya.github.com/js/random/', function (status) {
+    var result;
+    if (status !== 'success') {
+        console.log('Network error.');
+    } else {
+        console.log(page.evaluate(function () {
+            return document.getElementById('numbers').textContent;
+        }));
+    }
+    phantom.exit();
+});

+ 15 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/useragent.js

@@ -0,0 +1,15 @@
+"use strict";
+var page = require('webpage').create();
+console.log('The default user agent is ' + page.settings.userAgent);
+page.settings.userAgent = 'SpecialAgent';
+page.open('http://www.httpuseragent.org', function (status) {
+    if (status !== 'success') {
+        console.log('Unable to access network');
+    } else {
+        var ua = page.evaluate(function () {
+            return document.getElementById('myagent').innerText;
+        });
+        console.log(ua);
+    }
+    phantom.exit();
+});

+ 6 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/version.js

@@ -0,0 +1,6 @@
+"use strict";
+console.log('using PhantomJS version ' +
+  phantom.version.major + '.' +
+  phantom.version.minor + '.' +
+  phantom.version.patch);
+phantom.exit();

+ 58 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/waitfor.js

@@ -0,0 +1,58 @@
+/**
+ * Wait until the test condition is true or a timeout occurs. Useful for waiting
+ * on a server response or for a ui change (fadeIn, etc.) to occur.
+ *
+ * @param testFx javascript condition that evaluates to a boolean,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param onReady what to do when testFx condition is fulfilled,
+ * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
+ * as a callback function.
+ * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
+ */
+
+"use strict";
+function waitFor(testFx, onReady, timeOutMillis) {
+    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
+        start = new Date().getTime(),
+        condition = false,
+        interval = setInterval(function() {
+            if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
+                // If not time-out yet and condition not yet fulfilled
+                condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
+            } else {
+                if(!condition) {
+                    // If condition still not fulfilled (timeout but condition is 'false')
+                    console.log("'waitFor()' timeout");
+                    phantom.exit(1);
+                } else {
+                    // Condition fulfilled (timeout and/or condition is 'true')
+                    console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
+                    typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
+                    clearInterval(interval); //< Stop this interval
+                }
+            }
+        }, 250); //< repeat check every 250ms
+};
+
+
+var page = require('webpage').create();
+
+// Open Twitter on 'sencha' profile and, onPageLoad, do...
+page.open("http://twitter.com/#!/sencha", function (status) {
+    // Check for page load success
+    if (status !== "success") {
+        console.log("Unable to access network");
+    } else {
+        // Wait for 'signin-dropdown' to be visible
+        waitFor(function() {
+            // Check in the page if a specific element is now visible
+            return page.evaluate(function() {
+                return $("#signin-dropdown").is(":visible");
+            });
+        }, function() {
+           console.log("The sign-in dialog should be visible now.");
+           phantom.exit();
+        });
+    }
+});

+ 73 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/examples/walk_through_frames.js

@@ -0,0 +1,73 @@
+"use strict";
+var p = require("webpage").create();
+
+function pageTitle(page) {
+    return page.evaluate(function(){
+        return window.document.title;
+    });
+}
+
+function setPageTitle(page, newTitle) {
+    page.evaluate(function(newTitle){
+        window.document.title = newTitle;
+    }, newTitle);
+}
+
+p.open("../test/webpage-spec-frames/index.html", function(status) {
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    console.log("p.switchToChildFrame(\"frame1\"): "+p.switchToChildFrame("frame1"));
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    console.log("p.switchToChildFrame(\"frame1-2\"): "+p.switchToChildFrame("frame1-2"));
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    console.log("p.switchToParentFrame(): "+p.switchToParentFrame());
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    console.log("p.switchToChildFrame(0): "+p.switchToChildFrame(0));
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    console.log("p.switchToMainFrame()"); p.switchToMainFrame();
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    console.log("p.switchToChildFrame(\"frame2\"): "+p.switchToChildFrame("frame2"));
+    console.log("pageTitle(): " + pageTitle(p));
+    console.log("currentFrameName(): "+p.currentFrameName());
+    console.log("childFramesCount(): "+p.childFramesCount());
+    console.log("childFramesName(): "+p.childFramesName());
+    console.log("setPageTitle(CURRENT TITLE+'-visited')"); setPageTitle(p, pageTitle(p) + "-visited");
+    console.log("");
+
+    phantom.exit();
+});

+ 36 - 0
bi-server/src/main/resources/static/echarts-convert/phantomjs-2.1.1-windows/third-party.txt

@@ -0,0 +1,36 @@
+This document contains the list of Third Party Software included with
+PhantomJS, along with the license information.
+
+Third Party Software may impose additional restrictions and it is the
+user's responsibility to ensure that they have met the licensing
+requirements of PhantomJS and the relevant license of the Third Party
+Software they are using.
+
+Qt - http://qt-project.org/
+License: GNU Lesser General Public License (LGPL) version 2.1.
+Reference: http://qt-project.org/doc/qt-4.8/lgpl.html.
+
+WebKit - http://www.webkit.org/
+License: GNU Lesser General Public License (LGPL) version 2.1 and BSD.
+Reference: http://www.webkit.org/coding/lgpl-license.html and
+http://www.webkit.org/coding/bsd-license.html.
+
+Mongoose - https://github.com/cesanta/mongoose
+License: MIT
+Reference: https://github.com/cesanta/mongoose/commit/abbf27338ef554cce0281ac157aa71a9c1b82a55
+
+OpenSSL - http://www.openssl.org/
+License: OpenSSL License, SSLeay License.
+Reference: http://www.openssl.org/source/license.html.
+
+Linenoise - https://github.com/tadmarshall/linenoise
+License: BSD.
+Reference: https://github.com/tadmarshall/linenoise/blob/master/linenoise.h.
+
+QCommandLine - http://xf.iksaif.net/dev/qcommandline.html
+License: GNU Lesser General Public License (LGPL) version 2.1.
+Reference: http://dev.iksaif.net/projects/qcommandline/repository/revisions/master/entry/COPYING
+
+wkhtmlpdf - http://code.google.com/p/wkhtmltopdf/
+License: GNU Lesser General Public License (LGPL)
+Reference: http://code.google.com/p/wkhtmltopdf/

+ 103 - 0
bi-server/src/main/resources/static/echarts-convert/script/base64util.js

@@ -0,0 +1,103 @@
+exports = module.exports = new Base64();
+
+exports.Base64 = Base64;
+
+function Base64() {
+    // private property
+    this._keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+}
+
+Base64.prototype.decode = function(input) {
+    var output = "";
+    var keyStr = this._keyStr;
+    var chr1, chr2, chr3;
+    var enc1, enc2, enc3, enc4;
+    var i = 0;
+    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+    while (i < input.length) {
+        enc1 = keyStr.indexOf(input.charAt(i++));
+        enc2 = keyStr.indexOf(input.charAt(i++));
+        enc3 = keyStr.indexOf(input.charAt(i++));
+        enc4 = keyStr.indexOf(input.charAt(i++));
+        chr1 = (enc1 << 2) | (enc2 >> 4);
+        chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+        chr3 = ((enc3 & 3) << 6) | enc4;
+        output = output + String.fromCharCode(chr1);
+        if (enc3 != 64) {
+            output = output + String.fromCharCode(chr2);
+        }
+        if (enc4 != 64) {
+            output = output + String.fromCharCode(chr3);
+        }
+    }
+    output = this._utf8_decode(output);
+    return output;
+}
+
+Base64.prototype.encode = function (input) {
+    var output = "";
+    var keyStr = this._keyStr;
+    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+    var i = 0;
+    input = this._utf8_encode(input);
+    while (i < input.length) {
+        chr1 = input.charCodeAt(i++);
+        chr2 = input.charCodeAt(i++);
+        chr3 = input.charCodeAt(i++);
+        enc1 = chr1 >> 2;
+        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+        enc4 = chr3 & 63;
+        if (isNaN(chr2)) {
+            enc3 = enc4 = 64;
+        } else if (isNaN(chr3)) {
+            enc4 = 64;
+        }
+        output = output +
+        keyStr.charAt(enc1) + keyStr.charAt(enc2) +
+        keyStr.charAt(enc3) + keyStr.charAt(enc4);
+    }
+    return output;
+}
+
+Base64.prototype._utf8_encode = function (string) {
+    string = string.replace(/\r\n/g,"\n");
+    var utftext = "";
+    for (var n = 0; n < string.length; n++) {
+        var c = string.charCodeAt(n);
+        if (c < 128) {
+            utftext += String.fromCharCode(c);
+        } else if((c > 127) && (c < 2048)) {
+            utftext += String.fromCharCode((c >> 6) | 192);
+            utftext += String.fromCharCode((c & 63) | 128);
+        } else {
+            utftext += String.fromCharCode((c >> 12) | 224);
+            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+            utftext += String.fromCharCode((c & 63) | 128);
+        }
+    }
+    return utftext;
+}
+
+Base64.prototype._utf8_decode = function (utftext) {
+    var string = "";
+    var i = 0;
+    var c = c1 = c2 = 0;
+    while ( i < utftext.length ) {
+        c = utftext.charCodeAt(i);
+        if (c < 128) {
+            string += String.fromCharCode(c);
+            i++;
+        } else if((c > 191) && (c < 224)) {
+            c2 = utftext.charCodeAt(i+1);
+            string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+            i += 2;
+        } else {
+            c2 = utftext.charCodeAt(i+1);
+            c3 = utftext.charCodeAt(i+2);
+            string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+            i += 3;
+        }
+    }
+    return string;
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
bi-server/src/main/resources/static/echarts-convert/script/echarts.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2 - 0
bi-server/src/main/resources/static/echarts-convert/script/test.js


BIN
bi-server/src/main/resources/static/echarts-convert/tmp/1561360006221.png


BIN
bi-server/src/main/resources/static/echarts-convert/tmp/1561360109645.png


BIN
bi-server/src/main/resources/static/echarts-convert/tmp/1561360361518.png


BIN
bi-server/src/main/resources/static/echarts-convert/tmp/1561432866404.png


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است