diff --git a/dist/McuClient.js b/dist/McuClient.js
new file mode 100644
index 0000000..92fe42b
--- /dev/null
+++ b/dist/McuClient.js
@@ -0,0 +1,32410 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory();
+ else if(typeof define === 'function' && define.amd)
+ define([], factory);
+ else if(typeof exports === 'object')
+ exports["MCUClientEngine"] = factory();
+ else
+ root["MCUClientEngine"] = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ var parentHotUpdateCallback = this["webpackHotUpdateMCUClientEngine"];
+/******/ this["webpackHotUpdateMCUClientEngine"] = function webpackHotUpdateCallback(chunkId, moreModules) { // eslint-disable-line no-unused-vars
+/******/ hotAddUpdateChunk(chunkId, moreModules);
+/******/ if(parentHotUpdateCallback) parentHotUpdateCallback(chunkId, moreModules);
+/******/ }
+
+/******/ function hotDownloadUpdateChunk(chunkId) { // eslint-disable-line no-unused-vars
+/******/ var head = document.getElementsByTagName("head")[0];
+/******/ var script = document.createElement("script");
+/******/ script.type = "text/javascript";
+/******/ script.charset = "utf-8";
+/******/ script.src = __webpack_require__.p + "" + chunkId + "." + hotCurrentHash + ".hot-update.js";
+/******/ head.appendChild(script);
+/******/ }
+
+/******/ function hotDownloadManifest(callback) { // eslint-disable-line no-unused-vars
+/******/ if(typeof XMLHttpRequest === "undefined")
+/******/ return callback(new Error("No browser support"));
+/******/ try {
+/******/ var request = new XMLHttpRequest();
+/******/ var requestPath = __webpack_require__.p + "" + hotCurrentHash + ".hot-update.json";
+/******/ request.open("GET", requestPath, true);
+/******/ request.timeout = 10000;
+/******/ request.send(null);
+/******/ } catch(err) {
+/******/ return callback(err);
+/******/ }
+/******/ request.onreadystatechange = function() {
+/******/ if(request.readyState !== 4) return;
+/******/ if(request.status === 0) {
+/******/ // timeout
+/******/ callback(new Error("Manifest request to " + requestPath + " timed out."));
+/******/ } else if(request.status === 404) {
+/******/ // no update available
+/******/ callback();
+/******/ } else if(request.status !== 200 && request.status !== 304) {
+/******/ // other failure
+/******/ callback(new Error("Manifest request to " + requestPath + " failed."));
+/******/ } else {
+/******/ // success
+/******/ try {
+/******/ var update = JSON.parse(request.responseText);
+/******/ } catch(e) {
+/******/ callback(e);
+/******/ return;
+/******/ }
+/******/ callback(null, update);
+/******/ }
+/******/ };
+/******/ }
+
+
+/******/ // Copied from https://github.com/facebook/react/blob/bef45b0/src/shared/utils/canDefineProperty.js
+/******/ var canDefineProperty = false;
+/******/ try {
+/******/ Object.defineProperty({}, "x", {
+/******/ get: function() {}
+/******/ });
+/******/ canDefineProperty = true;
+/******/ } catch(x) {
+/******/ // IE will fail on defineProperty
+/******/ }
+
+/******/ var hotApplyOnUpdate = true;
+/******/ var hotCurrentHash = "c52c58ad9c6e306d2b34"; // eslint-disable-line no-unused-vars
+/******/ var hotCurrentModuleData = {};
+/******/ var hotCurrentParents = []; // eslint-disable-line no-unused-vars
+
+/******/ function hotCreateRequire(moduleId) { // eslint-disable-line no-unused-vars
+/******/ var me = installedModules[moduleId];
+/******/ if(!me) return __webpack_require__;
+/******/ var fn = function(request) {
+/******/ if(me.hot.active) {
+/******/ if(installedModules[request]) {
+/******/ if(installedModules[request].parents.indexOf(moduleId) < 0)
+/******/ installedModules[request].parents.push(moduleId);
+/******/ if(me.children.indexOf(request) < 0)
+/******/ me.children.push(request);
+/******/ } else hotCurrentParents = [moduleId];
+/******/ } else {
+/******/ console.warn("[HMR] unexpected require(" + request + ") from disposed module " + moduleId);
+/******/ hotCurrentParents = [];
+/******/ }
+/******/ return __webpack_require__(request);
+/******/ };
+/******/ for(var name in __webpack_require__) {
+/******/ if(Object.prototype.hasOwnProperty.call(__webpack_require__, name)) {
+/******/ if(canDefineProperty) {
+/******/ Object.defineProperty(fn, name, (function(name) {
+/******/ return {
+/******/ configurable: true,
+/******/ enumerable: true,
+/******/ get: function() {
+/******/ return __webpack_require__[name];
+/******/ },
+/******/ set: function(value) {
+/******/ __webpack_require__[name] = value;
+/******/ }
+/******/ };
+/******/ }(name)));
+/******/ } else {
+/******/ fn[name] = __webpack_require__[name];
+/******/ }
+/******/ }
+/******/ }
+
+/******/ function ensure(chunkId, callback) {
+/******/ if(hotStatus === "ready")
+/******/ hotSetStatus("prepare");
+/******/ hotChunksLoading++;
+/******/ __webpack_require__.e(chunkId, function() {
+/******/ try {
+/******/ callback.call(null, fn);
+/******/ } finally {
+/******/ finishChunkLoading();
+/******/ }
+
+/******/ function finishChunkLoading() {
+/******/ hotChunksLoading--;
+/******/ if(hotStatus === "prepare") {
+/******/ if(!hotWaitingFilesMap[chunkId]) {
+/******/ hotEnsureUpdateChunk(chunkId);
+/******/ }
+/******/ if(hotChunksLoading === 0 && hotWaitingFiles === 0) {
+/******/ hotUpdateDownloaded();
+/******/ }
+/******/ }
+/******/ }
+/******/ });
+/******/ }
+/******/ if(canDefineProperty) {
+/******/ Object.defineProperty(fn, "e", {
+/******/ enumerable: true,
+/******/ value: ensure
+/******/ });
+/******/ } else {
+/******/ fn.e = ensure;
+/******/ }
+/******/ return fn;
+/******/ }
+
+/******/ function hotCreateModule(moduleId) { // eslint-disable-line no-unused-vars
+/******/ var hot = {
+/******/ // private stuff
+/******/ _acceptedDependencies: {},
+/******/ _declinedDependencies: {},
+/******/ _selfAccepted: false,
+/******/ _selfDeclined: false,
+/******/ _disposeHandlers: [],
+
+/******/ // Module API
+/******/ active: true,
+/******/ accept: function(dep, callback) {
+/******/ if(typeof dep === "undefined")
+/******/ hot._selfAccepted = true;
+/******/ else if(typeof dep === "function")
+/******/ hot._selfAccepted = dep;
+/******/ else if(typeof dep === "object")
+/******/ for(var i = 0; i < dep.length; i++)
+/******/ hot._acceptedDependencies[dep[i]] = callback;
+/******/ else
+/******/ hot._acceptedDependencies[dep] = callback;
+/******/ },
+/******/ decline: function(dep) {
+/******/ if(typeof dep === "undefined")
+/******/ hot._selfDeclined = true;
+/******/ else if(typeof dep === "number")
+/******/ hot._declinedDependencies[dep] = true;
+/******/ else
+/******/ for(var i = 0; i < dep.length; i++)
+/******/ hot._declinedDependencies[dep[i]] = true;
+/******/ },
+/******/ dispose: function(callback) {
+/******/ hot._disposeHandlers.push(callback);
+/******/ },
+/******/ addDisposeHandler: function(callback) {
+/******/ hot._disposeHandlers.push(callback);
+/******/ },
+/******/ removeDisposeHandler: function(callback) {
+/******/ var idx = hot._disposeHandlers.indexOf(callback);
+/******/ if(idx >= 0) hot._disposeHandlers.splice(idx, 1);
+/******/ },
+
+/******/ // Management API
+/******/ check: hotCheck,
+/******/ apply: hotApply,
+/******/ status: function(l) {
+/******/ if(!l) return hotStatus;
+/******/ hotStatusHandlers.push(l);
+/******/ },
+/******/ addStatusHandler: function(l) {
+/******/ hotStatusHandlers.push(l);
+/******/ },
+/******/ removeStatusHandler: function(l) {
+/******/ var idx = hotStatusHandlers.indexOf(l);
+/******/ if(idx >= 0) hotStatusHandlers.splice(idx, 1);
+/******/ },
+
+/******/ //inherit from previous dispose call
+/******/ data: hotCurrentModuleData[moduleId]
+/******/ };
+/******/ return hot;
+/******/ }
+
+/******/ var hotStatusHandlers = [];
+/******/ var hotStatus = "idle";
+
+/******/ function hotSetStatus(newStatus) {
+/******/ hotStatus = newStatus;
+/******/ for(var i = 0; i < hotStatusHandlers.length; i++)
+/******/ hotStatusHandlers[i].call(null, newStatus);
+/******/ }
+
+/******/ // while downloading
+/******/ var hotWaitingFiles = 0;
+/******/ var hotChunksLoading = 0;
+/******/ var hotWaitingFilesMap = {};
+/******/ var hotRequestedFilesMap = {};
+/******/ var hotAvailibleFilesMap = {};
+/******/ var hotCallback;
+
+/******/ // The update info
+/******/ var hotUpdate, hotUpdateNewHash;
+
+/******/ function toModuleId(id) {
+/******/ var isNumber = (+id) + "" === id;
+/******/ return isNumber ? +id : id;
+/******/ }
+
+/******/ function hotCheck(apply, callback) {
+/******/ if(hotStatus !== "idle") throw new Error("check() is only allowed in idle status");
+/******/ if(typeof apply === "function") {
+/******/ hotApplyOnUpdate = false;
+/******/ callback = apply;
+/******/ } else {
+/******/ hotApplyOnUpdate = apply;
+/******/ callback = callback || function(err) {
+/******/ if(err) throw err;
+/******/ };
+/******/ }
+/******/ hotSetStatus("check");
+/******/ hotDownloadManifest(function(err, update) {
+/******/ if(err) return callback(err);
+/******/ if(!update) {
+/******/ hotSetStatus("idle");
+/******/ callback(null, null);
+/******/ return;
+/******/ }
+
+/******/ hotRequestedFilesMap = {};
+/******/ hotAvailibleFilesMap = {};
+/******/ hotWaitingFilesMap = {};
+/******/ for(var i = 0; i < update.c.length; i++)
+/******/ hotAvailibleFilesMap[update.c[i]] = true;
+/******/ hotUpdateNewHash = update.h;
+
+/******/ hotSetStatus("prepare");
+/******/ hotCallback = callback;
+/******/ hotUpdate = {};
+/******/ var chunkId = 0;
+/******/ { // eslint-disable-line no-lone-blocks
+/******/ /*globals chunkId */
+/******/ hotEnsureUpdateChunk(chunkId);
+/******/ }
+/******/ if(hotStatus === "prepare" && hotChunksLoading === 0 && hotWaitingFiles === 0) {
+/******/ hotUpdateDownloaded();
+/******/ }
+/******/ });
+/******/ }
+
+/******/ function hotAddUpdateChunk(chunkId, moreModules) { // eslint-disable-line no-unused-vars
+/******/ if(!hotAvailibleFilesMap[chunkId] || !hotRequestedFilesMap[chunkId])
+/******/ return;
+/******/ hotRequestedFilesMap[chunkId] = false;
+/******/ for(var moduleId in moreModules) {
+/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
+/******/ hotUpdate[moduleId] = moreModules[moduleId];
+/******/ }
+/******/ }
+/******/ if(--hotWaitingFiles === 0 && hotChunksLoading === 0) {
+/******/ hotUpdateDownloaded();
+/******/ }
+/******/ }
+
+/******/ function hotEnsureUpdateChunk(chunkId) {
+/******/ if(!hotAvailibleFilesMap[chunkId]) {
+/******/ hotWaitingFilesMap[chunkId] = true;
+/******/ } else {
+/******/ hotRequestedFilesMap[chunkId] = true;
+/******/ hotWaitingFiles++;
+/******/ hotDownloadUpdateChunk(chunkId);
+/******/ }
+/******/ }
+
+/******/ function hotUpdateDownloaded() {
+/******/ hotSetStatus("ready");
+/******/ var callback = hotCallback;
+/******/ hotCallback = null;
+/******/ if(!callback) return;
+/******/ if(hotApplyOnUpdate) {
+/******/ hotApply(hotApplyOnUpdate, callback);
+/******/ } else {
+/******/ var outdatedModules = [];
+/******/ for(var id in hotUpdate) {
+/******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
+/******/ outdatedModules.push(toModuleId(id));
+/******/ }
+/******/ }
+/******/ callback(null, outdatedModules);
+/******/ }
+/******/ }
+
+/******/ function hotApply(options, callback) {
+/******/ if(hotStatus !== "ready") throw new Error("apply() is only allowed in ready status");
+/******/ if(typeof options === "function") {
+/******/ callback = options;
+/******/ options = {};
+/******/ } else if(options && typeof options === "object") {
+/******/ callback = callback || function(err) {
+/******/ if(err) throw err;
+/******/ };
+/******/ } else {
+/******/ options = {};
+/******/ callback = callback || function(err) {
+/******/ if(err) throw err;
+/******/ };
+/******/ }
+
+/******/ function getAffectedStuff(module) {
+/******/ var outdatedModules = [module];
+/******/ var outdatedDependencies = {};
+
+/******/ var queue = outdatedModules.slice();
+/******/ while(queue.length > 0) {
+/******/ var moduleId = queue.pop();
+/******/ var module = installedModules[moduleId];
+/******/ if(!module || module.hot._selfAccepted)
+/******/ continue;
+/******/ if(module.hot._selfDeclined) {
+/******/ return new Error("Aborted because of self decline: " + moduleId);
+/******/ }
+/******/ if(moduleId === 0) {
+/******/ return;
+/******/ }
+/******/ for(var i = 0; i < module.parents.length; i++) {
+/******/ var parentId = module.parents[i];
+/******/ var parent = installedModules[parentId];
+/******/ if(parent.hot._declinedDependencies[moduleId]) {
+/******/ return new Error("Aborted because of declined dependency: " + moduleId + " in " + parentId);
+/******/ }
+/******/ if(outdatedModules.indexOf(parentId) >= 0) continue;
+/******/ if(parent.hot._acceptedDependencies[moduleId]) {
+/******/ if(!outdatedDependencies[parentId])
+/******/ outdatedDependencies[parentId] = [];
+/******/ addAllToSet(outdatedDependencies[parentId], [moduleId]);
+/******/ continue;
+/******/ }
+/******/ delete outdatedDependencies[parentId];
+/******/ outdatedModules.push(parentId);
+/******/ queue.push(parentId);
+/******/ }
+/******/ }
+
+/******/ return [outdatedModules, outdatedDependencies];
+/******/ }
+
+/******/ function addAllToSet(a, b) {
+/******/ for(var i = 0; i < b.length; i++) {
+/******/ var item = b[i];
+/******/ if(a.indexOf(item) < 0)
+/******/ a.push(item);
+/******/ }
+/******/ }
+
+/******/ // at begin all updates modules are outdated
+/******/ // the "outdated" status can propagate to parents if they don't accept the children
+/******/ var outdatedDependencies = {};
+/******/ var outdatedModules = [];
+/******/ var appliedUpdate = {};
+/******/ for(var id in hotUpdate) {
+/******/ if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
+/******/ var moduleId = toModuleId(id);
+/******/ var result = getAffectedStuff(moduleId);
+/******/ if(!result) {
+/******/ if(options.ignoreUnaccepted)
+/******/ continue;
+/******/ hotSetStatus("abort");
+/******/ return callback(new Error("Aborted because " + moduleId + " is not accepted"));
+/******/ }
+/******/ if(result instanceof Error) {
+/******/ hotSetStatus("abort");
+/******/ return callback(result);
+/******/ }
+/******/ appliedUpdate[moduleId] = hotUpdate[moduleId];
+/******/ addAllToSet(outdatedModules, result[0]);
+/******/ for(var moduleId in result[1]) {
+/******/ if(Object.prototype.hasOwnProperty.call(result[1], moduleId)) {
+/******/ if(!outdatedDependencies[moduleId])
+/******/ outdatedDependencies[moduleId] = [];
+/******/ addAllToSet(outdatedDependencies[moduleId], result[1][moduleId]);
+/******/ }
+/******/ }
+/******/ }
+/******/ }
+
+/******/ // Store self accepted outdated modules to require them later by the module system
+/******/ var outdatedSelfAcceptedModules = [];
+/******/ for(var i = 0; i < outdatedModules.length; i++) {
+/******/ var moduleId = outdatedModules[i];
+/******/ if(installedModules[moduleId] && installedModules[moduleId].hot._selfAccepted)
+/******/ outdatedSelfAcceptedModules.push({
+/******/ module: moduleId,
+/******/ errorHandler: installedModules[moduleId].hot._selfAccepted
+/******/ });
+/******/ }
+
+/******/ // Now in "dispose" phase
+/******/ hotSetStatus("dispose");
+/******/ var queue = outdatedModules.slice();
+/******/ while(queue.length > 0) {
+/******/ var moduleId = queue.pop();
+/******/ var module = installedModules[moduleId];
+/******/ if(!module) continue;
+
+/******/ var data = {};
+
+/******/ // Call dispose handlers
+/******/ var disposeHandlers = module.hot._disposeHandlers;
+/******/ for(var j = 0; j < disposeHandlers.length; j++) {
+/******/ var cb = disposeHandlers[j];
+/******/ cb(data);
+/******/ }
+/******/ hotCurrentModuleData[moduleId] = data;
+
+/******/ // disable module (this disables requires from this module)
+/******/ module.hot.active = false;
+
+/******/ // remove module from cache
+/******/ delete installedModules[moduleId];
+
+/******/ // remove "parents" references from all children
+/******/ for(var j = 0; j < module.children.length; j++) {
+/******/ var child = installedModules[module.children[j]];
+/******/ if(!child) continue;
+/******/ var idx = child.parents.indexOf(moduleId);
+/******/ if(idx >= 0) {
+/******/ child.parents.splice(idx, 1);
+/******/ }
+/******/ }
+/******/ }
+
+/******/ // remove outdated dependency from module children
+/******/ for(var moduleId in outdatedDependencies) {
+/******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
+/******/ var module = installedModules[moduleId];
+/******/ var moduleOutdatedDependencies = outdatedDependencies[moduleId];
+/******/ for(var j = 0; j < moduleOutdatedDependencies.length; j++) {
+/******/ var dependency = moduleOutdatedDependencies[j];
+/******/ var idx = module.children.indexOf(dependency);
+/******/ if(idx >= 0) module.children.splice(idx, 1);
+/******/ }
+/******/ }
+/******/ }
+
+/******/ // Not in "apply" phase
+/******/ hotSetStatus("apply");
+
+/******/ hotCurrentHash = hotUpdateNewHash;
+
+/******/ // insert new code
+/******/ for(var moduleId in appliedUpdate) {
+/******/ if(Object.prototype.hasOwnProperty.call(appliedUpdate, moduleId)) {
+/******/ modules[moduleId] = appliedUpdate[moduleId];
+/******/ }
+/******/ }
+
+/******/ // call accept handlers
+/******/ var error = null;
+/******/ for(var moduleId in outdatedDependencies) {
+/******/ if(Object.prototype.hasOwnProperty.call(outdatedDependencies, moduleId)) {
+/******/ var module = installedModules[moduleId];
+/******/ var moduleOutdatedDependencies = outdatedDependencies[moduleId];
+/******/ var callbacks = [];
+/******/ for(var i = 0; i < moduleOutdatedDependencies.length; i++) {
+/******/ var dependency = moduleOutdatedDependencies[i];
+/******/ var cb = module.hot._acceptedDependencies[dependency];
+/******/ if(callbacks.indexOf(cb) >= 0) continue;
+/******/ callbacks.push(cb);
+/******/ }
+/******/ for(var i = 0; i < callbacks.length; i++) {
+/******/ var cb = callbacks[i];
+/******/ try {
+/******/ cb(outdatedDependencies);
+/******/ } catch(err) {
+/******/ if(!error)
+/******/ error = err;
+/******/ }
+/******/ }
+/******/ }
+/******/ }
+
+/******/ // Load self accepted modules
+/******/ for(var i = 0; i < outdatedSelfAcceptedModules.length; i++) {
+/******/ var item = outdatedSelfAcceptedModules[i];
+/******/ var moduleId = item.module;
+/******/ hotCurrentParents = [moduleId];
+/******/ try {
+/******/ __webpack_require__(moduleId);
+/******/ } catch(err) {
+/******/ if(typeof item.errorHandler === "function") {
+/******/ try {
+/******/ item.errorHandler(err);
+/******/ } catch(err) {
+/******/ if(!error)
+/******/ error = err;
+/******/ }
+/******/ } else if(!error)
+/******/ error = err;
+/******/ }
+/******/ }
+
+/******/ // handle errors in accept handlers and self accepted module load
+/******/ if(error) {
+/******/ hotSetStatus("fail");
+/******/ return callback(error);
+/******/ }
+
+/******/ hotSetStatus("idle");
+/******/ callback(null, outdatedModules);
+/******/ }
+
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false,
+/******/ hot: hotCreateModule(moduleId),
+/******/ parents: hotCurrentParents,
+/******/ children: []
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, hotCreateRequire(moduleId));
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // __webpack_hash__
+/******/ __webpack_require__.h = function() { return hotCurrentHash; };
+
+/******/ // Load entry module and return exports
+/******/ return hotCreateRequire(0)(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ module.exports = __webpack_require__(1);
+
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ exports.MessageTypes = undefined;
+ exports.createMcuClient = createMcuClient;
+
+ var _EngineEntrance = __webpack_require__(2);
+
+ var _EngineEntrance2 = _interopRequireDefault(_EngineEntrance);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ //对外暴露的对象
+
+
+ var MCU_CLIENT = new _EngineEntrance2.default(); //入口文件
+
+ function createMcuClient() {
+ return MCU_CLIENT;
+ }
+
+ //监听是事件名和异常定义
+ exports.MessageTypes = _MessageTypes2.default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(MCU_CLIENT, 'MCU_CLIENT', 'D:/work/McuClient/src/McuClientEngine.js');
+
+ __REACT_HOT_LOADER__.register(createMcuClient, 'createMcuClient', 'D:/work/McuClient/src/McuClientEngine.js');
+ }();
+
+ ;
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Emiter2 = __webpack_require__(3);
+
+ var _Emiter3 = _interopRequireDefault(_Emiter2);
+
+ var _Sass = __webpack_require__(4);
+
+ var _Sass2 = _interopRequireDefault(_Sass);
+
+ var _ServerCheck = __webpack_require__(21);
+
+ var _ServerCheck2 = _interopRequireDefault(_ServerCheck);
+
+ var _mcu2 = __webpack_require__(23);
+
+ var _mcu3 = _interopRequireDefault(_mcu2);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _ConferApe = __webpack_require__(36);
+
+ var _ConferApe2 = _interopRequireDefault(_ConferApe);
+
+ var _ChatApe = __webpack_require__(41);
+
+ var _ChatApe2 = _interopRequireDefault(_ChatApe);
+
+ var _VideoApe = __webpack_require__(42);
+
+ var _VideoApe2 = _interopRequireDefault(_VideoApe);
+
+ var _AudioApe = __webpack_require__(44);
+
+ var _AudioApe2 = _interopRequireDefault(_AudioApe);
+
+ var _DocApe = __webpack_require__(45);
+
+ var _DocApe2 = _interopRequireDefault(_DocApe);
+
+ var _WhiteBoardApe = __webpack_require__(46);
+
+ var _WhiteBoardApe2 = _interopRequireDefault(_WhiteBoardApe);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _base64Js = __webpack_require__(10);
+
+ var _base64Js2 = _interopRequireDefault(_base64Js);
+
+ var _ArrayBufferUtil = __webpack_require__(38);
+
+ var _ArrayBufferUtil2 = _interopRequireDefault(_ArrayBufferUtil);
+
+ var _utf = __webpack_require__(11);
+
+ var _utf2 = _interopRequireDefault(_utf);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+ __webpack_require__(47).polyfill();
+ __webpack_require__(49);
+ __webpack_require__(50);
+ __webpack_require__(13);
+
+ var loger = _Loger2.default.getLoger('MessageEntrance');
+ var _sdkInfo = { "version": "v.1.0.1", "author": "www.3mang.com" };
+
+ //APE
+ var _sass = void 0;
+ var _serverCheck = void 0;
+ var _mcu = void 0;
+ var _confer_ape = void 0;
+ var _chat_ape = void 0;
+ var _video_ape = void 0;
+ var _audio_ape = void 0;
+ var _doc_ape = void 0;
+ var _whiteboard_ape = void 0;
+
+ //MCUClient 外部实例化主类
+
+ var MessageEntrance = function (_Emiter) {
+ _inherits(MessageEntrance, _Emiter);
+
+ function MessageEntrance() {
+ _classCallCheck(this, MessageEntrance);
+
+ //sdk 信息
+ var _this = _possibleConstructorReturn(this, (MessageEntrance.__proto__ || Object.getPrototypeOf(MessageEntrance)).call(this));
+
+ _this.sdkInfo = _sdkInfo;
+ loger.log(_this.sdkInfo);
+
+ //初始化状态
+ _GlobalConfig2.default.setCurrentStatus(_GlobalConfig2.default.statusCode_0);
+
+ //全局的Error处理
+ _this.on(_MessageTypes2.default.MCU_ERROR, _this._mcuErrorHandler.bind(_this));
+
+ // Sass平台层
+ _sass = _Sass2.default;
+ _sass.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ _sass.on(_sass.SUCCESS, _this._sassJoinSuccessHandler.bind(_this)); //通过SASS平台验证(密码和MD5)
+ _sass.on(_sass.CLASS_INIT_SUCCESS, _this._sassInitSuccessHandler.bind(_this)); //获取会议初始化信息
+ //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息
+ _sass.on(_sass.CLASS_GET_CLASS_PARAM, _this._sassGetClassParamSuccessHandler.bind(_this)); //获取会议的最全信息和历史保存的数据
+
+ _sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, _this._sassSaveClassStatusInfoSuccessHandler.bind(_this)); //保存会议状态信息
+ _sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _this._sassSaveClassRecordInfoSuccessHandler.bind(_this)); //保存会议录制信息
+ _sass.on(_sass.DELETE_DOCUMENT_SUCCESS, _this._sassDeleteDocumentSuccess.bind(_this)); //sass删除文档成功
+
+ //ServerCheck ip
+ _serverCheck = _ServerCheck2.default;
+ _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, _this._serverCheckBestIpSuccessHandler.bind(_this)); //ip选点,获取最佳ip完成
+
+
+ // 底层MCU消息层
+ _mcu = _mcu3.default;
+ _mcu.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ _mcu.on(_MessageTypes2.default.CLASS_JOIN_MCU_SUCCESS, _this._mcuJoinMCUClassSuccessHandler.bind(_this)); //加入MCU会议完成
+
+
+ // 注册所有应用Ape
+ _confer_ape = new _ConferApe2.default();
+ _confer_ape.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ _confer_ape.on(_MessageTypes2.default.CLASS_EXIT, _this._doClassExit.bind(_this)); //监听自己的关闭事件
+ _confer_ape.on(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE, _this._onClassStatusInfoChange.bind(_this)); //当前会议状态信息发生改变
+ _confer_ape.on(_MessageTypes2.default.CLASS_DELETE_ROSTER, _this._onClassDeleteRoster.bind(_this)); //当前会议人员离开
+ _confer_ape.on(_MessageTypes2.default.CLASS_NONENTITY_ROSTER, _this._onClassNonentityRoster.bind(_this)); //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在
+ _confer_ape.on(_MessageTypes2.default.CLASS_RECORD_START, _this._onClassRecordStart.bind(_this)); //会议开始录制
+
+
+ _chat_ape = new _ChatApe2.default();
+ _chat_ape.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+
+ _video_ape = new _VideoApe2.default();
+ _video_ape.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ _video_ape.on(_MessageTypes2.default.VIDEO_UPDATE, _this.videoUpdate.bind(_this)); //这个监听事件不能删除,需要通知会议模块,检查channel占用
+
+
+ _audio_ape = new _AudioApe2.default();
+ _audio_ape.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ _audio_ape.on(_MessageTypes2.default.AUDIO_UPDATE, _this.audioUpdate.bind(_this)); //这个监听事件不能删除,需要通知会议模块,检查channel占用
+
+ _whiteboard_ape = new _WhiteBoardApe2.default();
+ _whiteboard_ape.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ //_whiteboard_ape.on(MessageTypes.WHITEBOARD_ANNOTATION_UPDATE, this.annoUpdateHandler.bind(this));
+
+ _doc_ape = new _DocApe2.default();
+ _doc_ape.on('*', function (type, data) {
+ return _this._emit(type, data);
+ });
+ _doc_ape.on(_MessageTypes2.default.DOC_UPDATE, _this.docUpdateHandler.bind(_this));
+ _doc_ape.on(_MessageTypes2.default.DOC_DELETE, _this.docDeleteHandler.bind(_this));
+ _doc_ape.on(_DocApe2.default.DOC_JOIN_CHANNEL_SUCCESS, _this.docJoinChannelSuccess.bind(_this));
+
+ //公开外部调用的方法
+ //class
+ _this.init = _this._init.bind(_this);
+ _this.joinClass = _this._joinClass.bind(_this);
+ _this.leaveClass = _this._leaveClass.bind(_this);
+ _this.getMcuClientStatus = _this._getMcuClientStatus.bind(_this);
+ //this.getClassDetail = this._getClassDetail;//停用
+ _this.getClassStatusInfo = _this._getClassStatusInfo.bind(_this);
+ _this.sendStartClass = _this._sendStartClass.bind(_this);
+ _this.sendPauseClass = _this._sendPauseClass.bind(_this);
+ _this.sendCloseClass = _this._sendCloseClass.bind(_this);
+
+ //chatApe
+ _this.sendChatMsg = _this._sendChatMsg.bind(_this);
+
+ //videoApe
+ //this.getVideoPlayPath = this._getVideoPlayPath.bind(this);
+ _this.getVideoPublishPath = _this._getVideoPublishPath.bind(_this);
+ _this.getVideoAllChannelInfo = _this._getVideoAllChannelInfo.bind(_this);
+ _this.publishVideo = _this._publishVideo.bind(_this);
+ _this.stopPublishVideo = _this._stopPublishVideo.bind(_this);
+ _this.sendVideoBroadcastMsg = _this._sendVideoBroadcastMsg.bind(_this);
+
+ //audioApe
+ //this.getAudioPlayPath = this._getPlayAudioPath.bind(this);
+ _this.getAudioPublishPath = _this._getPublishAudioPath.bind(_this);
+ _this.getAudioAllChannelInfo = _this._getAudioAllChannelInfo.bind(_this);
+ _this.publishAudio = _this._publishAudio.bind(_this);
+ _this.stopPublishAudio = _this._stopPublishAudio.bind(_this);
+ _this.sendAudioBroadcastMsg = _this.sendAudioCommandMsg.bind(_this);
+
+ //whiteBoradApe
+ _this.sendInsertAnnotaion = _this._sendInsertAnnotaion.bind(_this);
+ //this.sendDeleteAnnotaion=this._sendDeleteAnnotaion;
+ _this.sendDeleteAllAnnotation = _this._sendDeleteAllAnnotation.bind(_this);
+ _this.sendDeleteCurPageAnnotation = _this._sendDeleteCurPageAnnotation.bind(_this);
+ _this.sendGotoPrev = _this._sendGotoPrev.bind(_this);
+
+ //DocApe
+ _this.sendDocumentUpload = _this._sendDocumentUpload.bind(_this); //上传文档
+ _this.sendDocumentSwitchDoc = _this._sendDocumentSwitchDoc.bind(_this); //切换文档
+ _this.sendDocumentSwitchPage = _this._sendDocumentSwitchPage.bind(_this); //翻页
+ _this.sendDocumentDelete = _this._sassDeleteDocument.bind(_this);; //删除文档,先通过Sass删除,sass删除成功之后再同步mcu
+ //this.sendDocumentDeleteAll= this._documentDeleteAll;//删除所有文档
+ _this.sendDocumentCommand = _this._sendDocumentCommand.bind(_this);; //操作文档(翻页、缩放、滚动...)
+ _this.getDocImageFullPath = _this._getDocImageFullPath.bind(_this);; //获取文档图片的完整路径
+ _this.getDocPDFFullPath = _this._getDocPDFFullPath.bind(_this);; //获取文档的完整路径
+ return _this;
+ }
+
+ //mcu异常监听
+
+
+ _createClass(MessageEntrance, [{
+ key: '_mcuErrorHandler',
+ value: function _mcuErrorHandler(_data, _option) {
+ var option = _option || "";
+ var errorMessage = { "code": _data, "reson": _MessageTypes2.default.ErrorReson[_data] + " " + option };
+ loger.error("MCU_ERROR", errorMessage);
+
+ this._emit(_MessageTypes2.default.ERROR_EVENT, errorMessage);
+
+ /* if (_mcuErrorCallBackFun) {
+ _mcuErrorCallBackFun(errorMessage);
+ }*/
+ }
+
+ //获取当前的状态
+
+ }, {
+ key: '_getMcuClientStatus',
+ value: function _getMcuClientStatus() {
+ return _GlobalConfig2.default.getCurrentStatus();
+ }
+
+ //获取会议信息
+
+ }, {
+ key: '_getClassDetail',
+ value: function _getClassDetail() {
+ return _GlobalConfig2.default.getClassDetail();
+ }
+
+ //获取当前会议的状态信息
+
+ }, {
+ key: '_getClassStatusInfo',
+ value: function _getClassStatusInfo() {
+ return _GlobalConfig2.default.classStatusInfo;
+ }
+ //关闭会议,所有人都退出
+
+ }, {
+ key: '_doClassClose',
+ value: function _doClassClose(_param) {
+ this._leaveClass();
+ }
+
+ //离开会议,断开连接
+
+ }, {
+ key: '_doClassExit',
+ value: function _doClassExit() {
+ this._leaveClass();
+ }
+
+ //当前的会议状态信息发生改变,需要保存会议状态到Sass
+
+ }, {
+ key: '_onClassStatusInfoChange',
+ value: function _onClassStatusInfoChange(_param) {
+ //如果MCU连接已经断开,不发送
+ if (_GlobalConfig2.default.getCurrentStatus().code != _GlobalConfig2.default.statusCode_2.code) {
+ loger.warn("不能保存会议状态", _GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ this._sassSaveClassStatusInfo();
+ }
+
+ //如果是第一次点击开始上课,需要创建录制时的文件名
+
+ }, {
+ key: '_onClassRecordStart',
+ value: function _onClassRecordStart(_param) {
+ if (_GlobalConfig2.default.getCurrentStatus().code != _GlobalConfig2.default.statusCode_2.code) {
+ loger.warn("不能保存会议状态", _GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_sass) {
+ _sass.saveClassRecordContrlInfo(_param);
+ }
+ }
+
+ //有人员离开
+
+ }, {
+ key: '_onClassDeleteRoster',
+ value: function _onClassDeleteRoster(_data) {}
+ //{"nodeId":nodeId}
+ //当有人员离开的时候,如果离开的人员已经推流,那么需要停止推流,然后释放channel;
+ /* if(_data!=null&&_data.nodeId!=null){
+ loger.log("有人员离开,检查一下离开的人员是否关闭推流");
+ if(_video_ape){
+ _video_ape.stopPublishVideo(_data);
+ }
+ if(_audio_ape){
+ _audio_ape.stopPublishAudio(_data);
+ }
+ }*/
+
+
+ //当前会议中视频或音频占用channel的nodeId ,在人员列表中不存在,这种情况是占用channel的人员掉线或离开的时候没有释放channel
+ //的占用状态导致,对于这种情况,需要释放掉
+
+ }, {
+ key: '_onClassNonentityRoster',
+ value: function _onClassNonentityRoster(_param) {
+ if (_param == null || _param.nodeId == null) {
+ loger.warn("onClassNonentityRoster.参数错误");
+ return;
+ }
+ var data = { "nodeId": _param.nodeId };
+ if (_video_ape) {
+ _video_ape.stopPublishVideo(data);
+ }
+ if (_audio_ape) {
+ _audio_ape.stopPublishAudio(data);
+ }
+ }
+
+ //Sass
+ //初始化
+
+ }, {
+ key: '_init',
+ value: function _init(_param) {
+ //{"classId":"1653304953","portal":"112.126.80.182:80","userRole":"normal","userId":0}
+ //判断传入的参数是否存在
+ if (_param == null || _EngineUtils2.default.isEmptyObject(_param)) {
+ loger.error('init初始化失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_PARAM);
+ return;
+ }
+ //判断必要的参数字段值
+ if (_param.classId == null || isNaN(_param.classId) || _param.portal == null || _param.portal == "") {
+ loger.error('init初始化失败', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_PARAM);
+ return;
+ }
+ loger.log('init', _param);
+
+ //保存参数
+ _GlobalConfig2.default.classId = parseInt(_param.classId);
+ _GlobalConfig2.default.portal = _param.portal;
+ _GlobalConfig2.default.userRole = _param.userRole || _ApeConsts2.default.normal;
+ _GlobalConfig2.default.userId = _param.userId || "0";
+ _GlobalConfig2.default.userName = _param.userName || "";
+
+ //获取课堂校验信息
+ if (_sass) {
+ _sass.getJoinParams(_GlobalConfig2.default.getClassInfo());
+ }
+ }
+
+ //外部请求加入会议
+
+ }, {
+ key: '_joinClass',
+ value: function _joinClass(_param) {
+ //_joinClassSuccessCallBackFun = _onSuccess;
+ //{"userName":"名字","password":""}
+ if (_param == null || _EngineUtils2.default.isEmptyObject(_param)) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_PARAM);
+ loger.log('不能进入会议,传递的参数不对.', _param);
+ return;
+ }
+ //判断userName
+ if (_param.userName == null || _param.userName == "") {
+ loger.log('不能进入会议,传递的参数不对.名字不能为空');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_PARAM);
+ return;
+ }
+
+ if (_GlobalConfig2.default.userName == null || _GlobalConfig2.default.userName == "") {
+ _GlobalConfig2.default.userName = _param.userName;
+ }
+ _GlobalConfig2.default.password = _param.password || "";
+ _GlobalConfig2.default.hasCamera = typeof _param.hasCamera == "boolean" ? _param.hasCamera : false;
+ _GlobalConfig2.default.hasMicrophone = typeof _param.hasMicrophone == "boolean" ? _param.hasMicrophone : false;
+
+ //debugger;
+ //开始校验
+ if (_sass) {
+ _sass.passwordAndMd5Checking(_GlobalConfig2.default.getClassInfo());
+ }
+ }
+
+ // 用classId向SASS平台获取入会验证信息成功
+
+ }, {
+ key: '_sassInitSuccessHandler',
+ value: function _sassInitSuccessHandler(_data) {
+ //{"siteId":"h5test","passwordRequired":true,"md5":"de399d5540b3da2fbc1eb0a770d4fd66","code":0,"msType":1}
+ //储存数据
+ _GlobalConfig2.default.md5 = _data.md5 || ""; //这个暂时用假数据,后台接口写完就有数据了
+ _GlobalConfig2.default.msType = _data.msType || 1;
+ _GlobalConfig2.default.siteId = _data.siteId || "";
+ _GlobalConfig2.default.classType = _data.meetingType || 0;
+
+ //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
+ _GlobalConfig2.default.passwordRequired = _data.passwordRequired || false; //md5验证的时候需要Sass返回的值,不能更改
+
+ loger.log('SASS平台获取入会验证信息成功.');
+
+ //设置当前的会议状态
+ _GlobalConfig2.default.setCurrentStatus(_GlobalConfig2.default.statusCode_1);
+ //返回给客户端初始化成功的数据
+ var initSuccessCallBackData = {};
+ initSuccessCallBackData.siteId = _GlobalConfig2.default.siteId;
+ initSuccessCallBackData.classId = _GlobalConfig2.default.classId;
+ initSuccessCallBackData.userRole = _GlobalConfig2.default.userRole;
+ initSuccessCallBackData.userId = _GlobalConfig2.default.userId;
+ initSuccessCallBackData.userName = _GlobalConfig2.default.userName;
+ initSuccessCallBackData.classType = _GlobalConfig2.default.classType;
+
+ //host默认需要密码,Sass服务器只判断学生是否需要密码,没有判断老师的
+ if (_GlobalConfig2.default.userRole == _ApeConsts2.default.host) {
+ initSuccessCallBackData.passwordRequired = true;
+ } else {
+ initSuccessCallBackData.passwordRequired = _GlobalConfig2.default.passwordRequired;
+ }
+
+ this._emit(_MessageTypes2.default.CLASS_INIT_SUCCESS, initSuccessCallBackData);
+
+ /* if (_initSuccessCallBackFun) {
+ _initSuccessCallBackFun(initSuccessCallBackData);
+ }*/
+ }
+
+ // 通过SASS平台验证(密码和MD5)
+
+ }, {
+ key: '_sassJoinSuccessHandler',
+ value: function _sassJoinSuccessHandler(_data) {
+ //返回值
+ /* flag 数值型 无 True:成功
+ Flag:失败
+ h5_mcu_list 字符串 H5muc列表
+ maxVideoChannels 数值型 最大视频路数
+ maxAudioChannels 数值型 最大音频路数
+ h5Module 数值型 H5开关
+ ms 字符串 Ms列表
+ mcu 字符串 Mcu列表
+ rs 字符串 Rs列表
+ doc 字符串 Doc列表*/
+ //获取会议最完整的数据
+ if (_sass) {
+ _sass.getClassParam();
+ }
+ }
+
+ //获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
+
+ }, {
+ key: '_sassGetClassParamSuccessHandler',
+ value: function _sassGetClassParamSuccessHandler(_data) {
+ //console.log(GlobalConfig.classStatusInfo)
+ loger.log('获取课堂会议的完整信息完成.');
+ // console.log(_data);
+ //包含整个会议最全的信息,储存数据
+ if (_data) {
+ _GlobalConfig2.default.mcuDelay = _data.mcuDelay || 60; //mcu消息延迟,用于文档模块
+ _GlobalConfig2.default.className = _data.meetingName || "";
+ _GlobalConfig2.default.classBeginTime = _data.beginTime || "";
+ _GlobalConfig2.default.classEndTime = _data.endTime || "";
+ _GlobalConfig2.default.userIp = _data.userIp || "";
+
+ _GlobalConfig2.default.maxVideoChannels = _data.maxVideoChannels;
+ _GlobalConfig2.default.maxAudioChannels = _data.maxAudioChannels;
+
+ _GlobalConfig2.default.setDocListPrepare(_data.docListPrepare); //提前上传的文档列表
+ _GlobalConfig2.default.setRecordList(_data.recordList); //录制回放地址
+ _GlobalConfig2.default.setDocList(_data.docList); //文档地址
+ _GlobalConfig2.default.setMsList(_data.msList); //推流播流服务器地址
+ _GlobalConfig2.default.setRsList(_data.rsList); //播放m3u8格式的地址
+ _GlobalConfig2.default.setMcuList(_data.mcuList); //mcu
+ _GlobalConfig2.default.setMusicList(_data.musicList); //
+ _GlobalConfig2.default.setMusicListPrepare(_data.musicListPrepare); //提前上传的声音文件列表
+
+
+ if (_data.mcuList) {
+ //MCU地址默认使用第一个
+ _GlobalConfig2.default.MCUServerIP = _data.mcuList[0].ip || "";
+ _GlobalConfig2.default.MCUServerPort = _data.mcuList[0].port || "";
+ }
+
+ //视频推流播流地址
+ if (_data.msList) {
+ //MS地址默认使用第一个
+ _GlobalConfig2.default.MSServerIP = _data.msList[0].ip || "";
+ _GlobalConfig2.default.MSServerPort = _data.msList[0].port || "";
+ }
+
+ //m3u8播流地址
+ if (_data.rsList) {
+ //RS地址默认使用第一个
+ _GlobalConfig2.default.RSServerIP = _data.rsList[0].ip || "";
+ _GlobalConfig2.default.RSServerPort = _data.rsList[0].port || "";
+ }
+
+ //文档地址
+ if (_data.docList) {
+ //doc地址默认使用第一个
+ _GlobalConfig2.default.DOCServerIP = _data.docList[0].ip || "";
+ _GlobalConfig2.default.DOCServerPort = _data.docList[0].port || "";
+ }
+
+ //record
+ if (_data.recordList) {
+ //地址默认使用第一个
+ _GlobalConfig2.default.RecordServerIP = _data.recordList[0].ip || "";
+ _GlobalConfig2.default.RecordServerPort = _data.recordList[0].port || "";
+ }
+ }
+
+ if (_data.currentInfo) {
+ //根据从Sass获取的数据信息,同步最后一次保存的会议状态信息
+ loger.log("同步最后一次保存过的会议状态信息");
+ _GlobalConfig2.default.setClassStatusInfo(_data.currentInfo);
+ console.log(_GlobalConfig2.default.classStatusInfo);
+ } else {
+ loger.log("还没有保存过会议状信息");
+ }
+
+ //根据用户的userIp获取信息
+ this.getUserIpInfo();
+ }
+ //根据UserIp获取ip信息
+
+ }, {
+ key: 'getUserIpInfo',
+ value: function getUserIpInfo() {
+ if (_serverCheck) {
+ _serverCheck.getUserIpInfo("", _GlobalConfig2.default.userIp);
+ }
+ }
+ //MCU MS ip选点完成,开加入MCU
+
+ }, {
+ key: '_serverCheckBestIpSuccessHandler',
+ value: function _serverCheckBestIpSuccessHandler(_data) {
+ loger.log("_serverCheckBestIpSuccessHandler,IP选点结束");
+ this._joinMCU();
+ }
+
+ //保存会议状态信息
+
+ }, {
+ key: '_sassSaveClassStatusInfo',
+ value: function _sassSaveClassStatusInfo() {
+ if (_GlobalConfig2.default.isHost) {
+ //只有加入会议之后才能保存数据
+ if (_GlobalConfig2.default.getCurrentStatus().code == _GlobalConfig2.default.statusCode_2.code) {
+ //POST 保存数据
+ _sass.saveClassStatusInfo({ "classStatusInfo": _GlobalConfig2.default.classStatusInfo }); //保存会议状态信息
+ } else {
+ loger.error("不能保存会议数据", _GlobalConfig2.default.getCurrentStatus());
+ }
+ } else {
+ loger.log("没有保存会议状态信息的权限 isHost", _GlobalConfig2.default.isHost);
+ }
+ }
+
+ //保存会态信息成功
+
+ }, {
+ key: '_sassSaveClassStatusInfoSuccessHandler',
+ value: function _sassSaveClassStatusInfoSuccessHandler(_data) {
+ loger.log('保存会议状态信息成功.');
+ console.log(_data);
+ }
+ }, {
+ key: '_sassSaveClassRecordInfoSuccessHandler',
+ value: function _sassSaveClassRecordInfoSuccessHandler(_data) {
+ loger.log('保存会议录制信息成功.');
+ console.log(_data);
+ }
+
+ //Sass校验流程结束之后,开始加入MCU
+
+ }, {
+ key: '_joinMCU',
+ value: function _joinMCU() {
+ loger.log('加入底层MCU会议.');
+ if (_mcu) {
+ _mcu.joinMCU(_GlobalConfig2.default.getClassInfo());
+ }
+ }
+
+ // MCU 会议成功
+
+ }, {
+ key: '_mcuJoinMCUClassSuccessHandler',
+ value: function _mcuJoinMCUClassSuccessHandler(_data) {
+ loger.log('MCU 会议成功.');
+ _GlobalConfig2.default.setCurrentStatus(_GlobalConfig2.default.statusCode_2);
+
+ //返回给客户端初始化成功的数据
+ var joinClassSuccessCallBackData = {};
+
+ joinClassSuccessCallBackData.DOCServerIP = _GlobalConfig2.default.DOCServerIP;
+ joinClassSuccessCallBackData.DOCServerPort = _GlobalConfig2.default.DOCServerPort;
+
+ joinClassSuccessCallBackData.classId = _GlobalConfig2.default.classId;
+ joinClassSuccessCallBackData.className = _GlobalConfig2.default.className;
+ joinClassSuccessCallBackData.h5Module = _GlobalConfig2.default.h5Module;
+ joinClassSuccessCallBackData.isHost = _GlobalConfig2.default.isHost;
+ joinClassSuccessCallBackData.maxAudioChannels = _GlobalConfig2.default.maxAudioChannels;
+ joinClassSuccessCallBackData.maxVideoChannels = _GlobalConfig2.default.maxVideoChannels;
+ joinClassSuccessCallBackData.mcuDelay = _GlobalConfig2.default.mcuDelay;
+
+ joinClassSuccessCallBackData.msType = _GlobalConfig2.default.msType;
+ joinClassSuccessCallBackData.nodeId = _GlobalConfig2.default.nodeId;
+ joinClassSuccessCallBackData.password = _GlobalConfig2.default.password;
+ joinClassSuccessCallBackData.passwordRequired = _GlobalConfig2.default.passwordRequired; // 老师的默认是true
+ //GlobalConfig.passwordRequired 老师的默认是true
+ //GlobalConfig.portal=_data.portal;
+ joinClassSuccessCallBackData.role = _GlobalConfig2.default.role;
+ joinClassSuccessCallBackData.siteId = _GlobalConfig2.default.siteId;
+ joinClassSuccessCallBackData.topNodeID = _GlobalConfig2.default.topNodeID;
+ joinClassSuccessCallBackData.userId = _GlobalConfig2.default.userId;
+ joinClassSuccessCallBackData.userName = _GlobalConfig2.default.userName;
+ joinClassSuccessCallBackData.userRole = _GlobalConfig2.default.userRole;
+ joinClassSuccessCallBackData.userType = _GlobalConfig2.default.userType;
+
+ joinClassSuccessCallBackData.siteId = _GlobalConfig2.default.siteId;
+ joinClassSuccessCallBackData.classId = _GlobalConfig2.default.classId;
+ joinClassSuccessCallBackData.userRole = _GlobalConfig2.default.userRole;
+ joinClassSuccessCallBackData.userId = _GlobalConfig2.default.userId;
+ joinClassSuccessCallBackData.passwordRequired = _GlobalConfig2.default.passwordRequired;
+ joinClassSuccessCallBackData.classType = _GlobalConfig2.default.classType || _ApeConsts2.default.CLASS_TYPE_INTERACT;
+
+ joinClassSuccessCallBackData.country = _GlobalConfig2.default.country; //国家
+ joinClassSuccessCallBackData.city = _GlobalConfig2.default.city; //城市
+ joinClassSuccessCallBackData.province = _GlobalConfig2.default.province; //服务商
+ joinClassSuccessCallBackData.isp = _GlobalConfig2.default.isp; //服务商
+
+ loger.log('加入会议成功');
+ console.log(joinClassSuccessCallBackData);
+
+ //加入会议成功,广播消息
+ this._emit(_MessageTypes2.default.CLASS_JOIN_SUCCESS, joinClassSuccessCallBackData);
+ }
+
+ //Sass删除文档数据
+
+ }, {
+ key: '_sassDeleteDocument',
+ value: function _sassDeleteDocument(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+
+ //判断传入的参数是否存在
+ if (_param == null || _EngineUtils2.default.isEmptyObject(_param)) {
+ loger.error('sassDeleteDocument失败,参数错误', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_DOC_DELETE_FAILED_PARAM);
+ return;
+ }
+ //判断必要的参数字段值
+ if (_param.itemIdx == null || isNaN(_param.itemIdx) || _param.docId == null || _param.docId == "") {
+ loger.error('sassDeleteDocument失败', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_DOC_DELETE_FAILED_PARAM);
+ return;
+ }
+ loger.log('_sassDeleteDocument', _param);
+
+ if (_sass) {
+ _sass.sassDeleteDocument(_param);
+ }
+ }
+
+ //Sass删除文档成功之后,同步删除MCU数据
+
+ }, {
+ key: '_sassDeleteDocumentSuccess',
+ value: function _sassDeleteDocumentSuccess(_param) {
+ loger.log('sassDeleteDocumentSuccess', _param);
+ this._sendDocumentDelete(_param);
+ }
+
+ //ConferApe
+ //开始上课
+
+ }, {
+ key: '_sendStartClass',
+ value: function _sendStartClass(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+
+ if (_confer_ape) {
+ _confer_ape.startClass(_param);
+ }
+ }
+ //暂停上课
+
+ }, {
+ key: '_sendPauseClass',
+ value: function _sendPauseClass(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_confer_ape) {
+ _confer_ape.pauseClass(_param);
+ }
+ }
+ //停止上课
+
+ }, {
+ key: '_sendCloseClass',
+ value: function _sendCloseClass(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_confer_ape) {
+ _confer_ape.closeClass(_param);
+ }
+ }
+ // 离开会议
+
+ }, {
+ key: '_leaveClass',
+ value: function _leaveClass() {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+
+ //停止推流
+ if (_video_ape) {
+ _video_ape.stopPublishVideo();
+ }
+ if (_audio_ape) {
+ _audio_ape.stopPublishAudio();
+ }
+ //离开会议
+ if (_confer_ape) {
+ _confer_ape.stopRecord();
+ _confer_ape.leaveClass();
+ }
+ //断开MCU连接
+ if (_mcu) {
+ _mcu.leaveMCU();
+ _GlobalConfig2.default.setCurrentStatus(_GlobalConfig2.default.statusCode_3);
+ }
+ }
+
+ //ChatApe
+ // 发送聊天消息
+
+ }, {
+ key: '_sendChatMsg',
+ value: function _sendChatMsg(_messageInfo) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_messageInfo === null || _EngineUtils2.default.isEmptyObject(_messageInfo)) {
+ loger.log('sendChatMsg 传递的参数不对', _messageInfo);
+ return;
+ }
+ if (_chat_ape) {
+ _chat_ape.sendChatMsg(_messageInfo);
+ }
+ }
+
+ //VidoeApe
+
+ }, {
+ key: 'videoUpdate',
+ value: function videoUpdate(_data) {
+ //视频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
+ if (_confer_ape) {
+ _confer_ape.updaterRosterStatus(_data);
+ }
+ }
+ }, {
+ key: '_sendVideoBroadcastMsg',
+ value: function _sendVideoBroadcastMsg(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_video_ape) {
+ return _video_ape.sendVideoBroadcastMsg(_param);
+ }
+ }
+ }, {
+ key: '_getVideoPlayPath',
+ value: function _getVideoPlayPath(_param) {
+ if (_video_ape) {
+ return _video_ape.getPlayVideoPath(_param);
+ }
+ }
+ }, {
+ key: '_getVideoPublishPath',
+ value: function _getVideoPublishPath(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+
+ if (_video_ape) {
+ return _video_ape.getPublishVideoPath(_param);
+ }
+ }
+ }, {
+ key: '_getVideoAllChannelInfo',
+ value: function _getVideoAllChannelInfo(_param) {
+ if (_video_ape) {
+ return _video_ape.getAllChannelInfo(_param);
+ }
+ }
+ }, {
+ key: '_publishVideo',
+ value: function _publishVideo(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_video_ape) {
+ return _video_ape.publishVideo(_param);
+ }
+ }
+ }, {
+ key: '_stopPublishVideo',
+ value: function _stopPublishVideo(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_video_ape) {
+ return _video_ape.stopPublishVideo(_param);
+ }
+ }
+
+ //AudioApe
+
+ }, {
+ key: 'audioUpdate',
+ value: function audioUpdate(_data) {
+ //音频同步的消息发送改变,需要通知ferApe模块中的用户更新状态
+ if (_confer_ape) {
+ _confer_ape.updaterRosterStatus(_data);
+ }
+ }
+ }, {
+ key: 'sendAudioCommandMsg',
+ value: function sendAudioCommandMsg(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_audio_ape) {
+ return _audio_ape.sendAudioBroadcastMsg(_param);
+ }
+ }
+ }, {
+ key: '_getPlayAudioPath',
+ value: function _getPlayAudioPath(_param) {
+ if (_audio_ape) {
+ return _audio_ape.getAudioPlayPath(_param);
+ }
+ }
+ }, {
+ key: '_getPublishAudioPath',
+ value: function _getPublishAudioPath(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_audio_ape) {
+ return _audio_ape.getAudioPublishPath(_param);
+ }
+ }
+ }, {
+ key: '_getAudioAllChannelInfo',
+ value: function _getAudioAllChannelInfo(_param) {
+ if (_audio_ape) {
+ return _audio_ape.getAllChannelInfo(_param);
+ }
+ }
+ }, {
+ key: '_publishAudio',
+ value: function _publishAudio(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_audio_ape) {
+ return _audio_ape.publishAudio(_param);
+ }
+ }
+ }, {
+ key: '_stopPublishAudio',
+ value: function _stopPublishAudio(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_audio_ape) {
+ return _audio_ape.stopPublishAudio(_param);
+ }
+ }
+
+ //WhiteBoardApe
+ // 添加标注,发送信息
+
+ }, {
+ key: '_sendInsertAnnotaion',
+ value: function _sendInsertAnnotaion(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_whiteboard_ape) {
+ _whiteboard_ape.sendInsetAnnotaion(_param);
+ }
+ }
+
+ //删除标注,发送信息
+
+ }, {
+ key: '_sendDeleteAnnotaion',
+ value: function _sendDeleteAnnotaion(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_whiteboard_ape) {
+ _whiteboard_ape.sendDeleteAnnotaion(_param);
+ }
+ }
+ //删除当前页面上的所有标注
+
+ }, {
+ key: '_sendDeleteCurPageAnnotation',
+ value: function _sendDeleteCurPageAnnotation(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_whiteboard_ape) {
+ _whiteboard_ape.sendDeleteCurPageAnnotation(_param);
+ }
+ }
+ //删除所有标注
+
+ }, {
+ key: '_sendDeleteAllAnnotation',
+ value: function _sendDeleteAllAnnotation(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_whiteboard_ape) {
+ _whiteboard_ape.sendDeleteAllAnnotation(_param);
+ }
+ }
+ //返回上一步标注
+
+ }, {
+ key: '_sendGotoPrev',
+ value: function _sendGotoPrev(_param) {
+ if (_whiteboard_ape) {
+ _whiteboard_ape.sendGotoPrev(_param);
+ }
+ }
+
+ //DocApe
+ //获取文档完整路径
+
+ }, {
+ key: '_getDocImageFullPath',
+ value: function _getDocImageFullPath(_param) {
+ if (_doc_ape) {
+ return _doc_ape.getDocImageFullPath(_param);
+ } else {
+ loger.error("文档模块还没有创建,无法获取");
+ return [];
+ }
+ }
+ }, {
+ key: '_getDocPDFFullPath',
+ value: function _getDocPDFFullPath(_param) {
+ if (_doc_ape) {
+ return _doc_ape.getDocPDFFullPath(_param);
+ } else {
+ loger.error("文档模块还没有创建,无法获取");
+ return [];
+ }
+ }
+ //上传文档
+
+ }, {
+ key: '_sendDocumentUpload',
+ value: function _sendDocumentUpload(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_doc_ape) {
+ _doc_ape.documentUpload(_param);
+ }
+ }
+ //切换文档
+
+ }, {
+ key: '_sendDocumentSwitchDoc',
+ value: function _sendDocumentSwitchDoc(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_doc_ape) {
+ _doc_ape.documentSwitchDoc(_param);
+ }
+ }
+ //操作文档(翻页)
+
+ }, {
+ key: '_sendDocumentSwitchPage',
+ value: function _sendDocumentSwitchPage(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_doc_ape) {
+ _doc_ape.documentSwitchPage(_param);
+ }
+ }
+ //操作文档(缩放、滚动...)
+
+ }, {
+ key: '_sendDocumentCommand',
+ value: function _sendDocumentCommand(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_doc_ape) {
+ _doc_ape.documentCommand(_param);
+ }
+ }
+ //删除文档
+
+ }, {
+ key: '_sendDocumentDelete',
+ value: function _sendDocumentDelete(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_doc_ape) {
+ _doc_ape.documentDelete(_param);
+ }
+ }
+ //删除所有文档
+
+ }, {
+ key: '_documentDeleteAll',
+ value: function _documentDeleteAll(_param) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ if (_doc_ape) {
+ _doc_ape.documentDeleteAll(_param);
+ }
+ }
+
+ //// 文档变更,白板也需要做处理
+
+ }, {
+ key: 'docUpdateHandler',
+ value: function docUpdateHandler(_data) {
+ if (!_mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return;
+ }
+ loger.log('Doc UpdateId ->');
+ console.log(_data);
+ if (_whiteboard_ape) {
+ _whiteboard_ape.docUpdateHandler(_data);
+ }
+ }
+
+ //文档删除,白板也需要做处理
+
+ }, {
+ key: 'docDeleteHandler',
+ value: function docDeleteHandler(_data) {
+ if (_whiteboard_ape) {
+ _whiteboard_ape.docDeleteHandler(_data);
+ }
+ }
+
+ //文档加入频道成功,同步到MCU服务器上的数据
+
+ }, {
+ key: 'docJoinChannelSuccess',
+ value: function docJoinChannelSuccess() {
+ loger.log("docJoinChannelSuccess isHost=", _GlobalConfig2.default.isHost);
+ console.log(_GlobalConfig2.default.docListPrepare);
+ loger.log("docJoinChannelSuccess docListPrepare=");
+ //如果是主持人,那么需要判断一下文档模块同步的数据和从sass获取的文档数据是否相同,如果mcu服务器不存在的,需要上传
+ if (_GlobalConfig2.default.isHost) {
+ var _iteratorNormalCompletion = true;
+ var _didIteratorError = false;
+ var _iteratorError = undefined;
+
+ try {
+ for (var _iterator = _GlobalConfig2.default.docListPrepare[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+ var value = _step.value;
+
+ if (value) {
+ /* //提前上传的文档文档信息的结构
+ {
+ "MD5": "f3feb3fac8cd3a953bded00e07a0c66b",
+ "absoluteLocation": "http://101.200.150.192/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
+ "createUserID": "972",
+ "createUserIP": "114.241.81.175",
+ "createUserName": "base",
+ "dynamicPPT": 0,
+ "dynamicTransferStatic": "",
+ "id": "8ab3b0ed5a00f2fa015a0219a3df016c",
+ "meetingNumber": "",
+ "name": "McuClient_v.1.0.1_API.pdf",
+ "orderStr": "",
+ "pdfSize": 5,
+ "processEndTime": "2017-02-03 11:54:31",
+ "processRate": 0,
+ "processStartTime": "2017-02-03 11:54:27",
+ "relativeLocation": "/DocSharing/data/526661904/20170203-115400026/f3feb3fac8cd3a953bded00e07a0c66b.swf",
+ "siteID": "h5test",
+ "size": 360920,
+ "status": 3,
+ "type": "pdf",
+ "uploadEndTime": "2017-02-03 11:54:27",
+ "uploadStartTime": "2017-02-03 11:54:27"
+ }*/
+
+ loger.log("判断是否需要把提前上传的文档上传到mcu", value);
+ var paramInfo = {
+ "pageNum": value.pdfSize,
+ "fileName": value.name,
+ "fileType": value.type,
+ "relativeUrl": value.relativeLocation,
+ "url": value.absoluteLocation,
+ "creatUserId": value.createUserID,
+ "docId": value.id,
+ "md5": value.MD5,
+ "visible": false
+ };
+
+ this._sendDocumentUpload(paramInfo);
+ }
+ }
+ } catch (err) {
+ _didIteratorError = true;
+ _iteratorError = err;
+ } finally {
+ try {
+ if (!_iteratorNormalCompletion && _iterator.return) {
+ _iterator.return();
+ }
+ } finally {
+ if (_didIteratorError) {
+ throw _iteratorError;
+ }
+ }
+ }
+ }
+ }
+ }]);
+
+ return MessageEntrance;
+ }(_Emiter3.default);
+
+ var _default = MessageEntrance;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_sdkInfo, '_sdkInfo', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_sass, '_sass', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_serverCheck, '_serverCheck', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_mcu, '_mcu', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_confer_ape, '_confer_ape', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_chat_ape, '_chat_ape', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_video_ape, '_video_ape', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_audio_ape, '_audio_ape', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_doc_ape, '_doc_ape', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_whiteboard_ape, '_whiteboard_ape', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(MessageEntrance, 'MessageEntrance', 'D:/work/McuClient/src/EngineEntrance.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/EngineEntrance.js');
+ }();
+
+ ;
+
+/***/ },
+/* 3 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ var Emiter = function () {
+ function Emiter() {
+ _classCallCheck(this, Emiter);
+
+ this.MAPS = {};
+ }
+
+ _createClass(Emiter, [{
+ key: 'on',
+ value: function on(eid, elistener) {
+ if (eid && elistener) {
+ var stub = this.MAPS[eid];
+ if (!stub) {
+ return this.MAPS[eid] = [elistener];
+ }
+ stub.push(elistener);
+ }
+ }
+ }, {
+ key: 'off',
+ value: function off(eid, elistener) {
+ if (eid) {
+ var stub = this.MAPS[eid];
+ if (stub) {
+ if (elistener) {
+ return stub.splice(stub.indexOf(elistener), 1);
+ }
+ stub.length = 0;
+ }
+ }
+ }
+ }, {
+ key: '_emit',
+ value: function _emit(eid, data) {
+ if (eid) {
+ //eid=* broadcast
+ var asteriskStub = this.MAPS['*'];
+ if (asteriskStub && asteriskStub.length) {
+ asteriskStub.forEach(function (elistener) {
+ elistener(eid, data);
+ });
+ }
+
+ // eid= normal
+ var stub = this.MAPS[eid];
+ if (stub && stub.length) {
+ stub.forEach(function (elistener) {
+ elistener(data);
+ });
+ }
+ }
+ }
+ }]);
+
+ return Emiter;
+ }();
+
+ var _default = Emiter;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(Emiter, 'Emiter', 'D:/work/McuClient/src/Emiter.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/Emiter.js');
+ }();
+
+ ;
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Emiter2 = __webpack_require__(3);
+
+ var _Emiter3 = _interopRequireDefault(_Emiter2);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _md = __webpack_require__(15);
+
+ var _md2 = _interopRequireDefault(_md);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _iphunter = __webpack_require__(19);
+
+ var _iphunter2 = _interopRequireDefault(_iphunter);
+
+ var _fetchJsonp = __webpack_require__(20);
+
+ var _fetchJsonp2 = _interopRequireDefault(_fetchJsonp);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+ // 日志对象
+ var loger = _Loger2.default.getLoger('Sass');
+
+ var confInfo = {};
+
+ var Sass = function (_Emiter) {
+ _inherits(Sass, _Emiter);
+
+ function Sass() {
+ _classCallCheck(this, Sass);
+
+ return _possibleConstructorReturn(this, (Sass.__proto__ || Object.getPrototypeOf(Sass)).call(this));
+ //window.findIpInfoCallback=this._findIpInfoCallback.bind(this);
+ }
+
+ ///////////////////////////////////////Sass 接口///////////////////////////////////////////////////
+ //Sass init初始化获取课堂校验信息-----------------------------------------------------------------
+
+
+ _createClass(Sass, [{
+ key: 'getJoinParams',
+ value: function getJoinParams(_initInfo) {
+ var _this2 = this;
+
+ /* 获取用于加入课堂的参数
+ /3m/api/meeting/joinParams.do
+ 参数 (application/x-www-form-urlencoded):
+ 名称 类型 可选 默认值 说明
+ meetingNumber String 否 null 课堂号
+ userID String 是 0 用户id
+ 返回 (application/json):
+ code int 0 正常
+ 1 课堂号必填
+ 2 无效的课堂号
+ 3 没有对应的站点
+ 4 站点已过期
+ siteId String 站点号
+ passwordRequired Boolean 是否需要输入密码
+ md5 String 用于后续加入课堂验证
+ msType int 媒体服务器类型
+ classType 课堂类型
+ */
+ var url = 'http://' + _initInfo.portal + '/3m/api/meeting/joinParams.do?meetingNumber=' + _initInfo.classId + '&userID=' + _initInfo.userId;
+ loger.log('1.初始化init获取课堂校验信息.');
+ console.log(url);
+ console.log(_initInfo);
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.ok) {
+ return ret.json();
+ } else {
+ loger.error('\u521D\u59CB\u5316init\u83B7\u53D6\u8BFE\u5802\u6821\u9A8C\u4FE1\u606F-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_NETWORK);
+ throw '';
+ }
+ }).then(function (ret) {
+ // code int 0 正常
+ // 1 课堂号必填
+ //2 无效的课堂号
+ //3 没有对应的站点
+ //4 站点已过期
+ if (ret.code === 0) {
+ loger.log('初始化init获取课堂校验信息-完成');
+ _this2._emit(Sass.CLASS_INIT_SUCCESS, ret);
+ } else if (ret.code === 1) {
+ //loger.warn('Sass获取课堂校验信息失败.');
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_FAILED_1);
+ } else if (ret.code === 2) {
+ //loger.warn('Sass获取课堂校验信息失败.');
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_FAILED_2);
+ } else if (ret.code === 3) {
+ //loger.warn('Sass获取课堂校验信息失败.');
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_FAILED_3);
+ } else if (ret.code === 4) {
+ //loger.warn('Sass获取课堂校验信息失败.');
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_FAILED_4);
+ } else {
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_FAILED, ret);
+ }
+ }).catch(function (err) {
+ loger.error('\u521D\u59CB\u5316init\u83B7\u53D6\u8BFE\u5802\u6821\u9A8C\u4FE1\u606F-\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ _this2._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_INIT_PROTOCOL, err);
+ });
+ }
+
+ // Sass校验开始-->密码校验(如果需要密码)--->MD5校验----------------------------------------------------
+
+ }, {
+ key: 'passwordAndMd5Checking',
+ value: function passwordAndMd5Checking(_param) {
+ loger.log('2.开始Sass校验');
+ console.log(_param);
+ confInfo = _param;
+ // 密码校验
+ if (confInfo.passwordRequired === 'true' || confInfo.passwordRequired === true) {
+ this.sendPWDChecking();
+ return;
+ }
+ // MD5校验
+ this.sendMD5Checking();
+ }
+
+ // 入会密码校验---------------------------------------------------------------------------------------
+
+ }, {
+ key: 'sendPWDChecking',
+ value: function sendPWDChecking() {
+ var _this3 = this;
+
+ //let url = `http://${classInfo.portal}/3m/getCheckMeetinig.do?siteId=${classInfo.siteId}&classId=${classInfo.classId}&password=${classInfo.password}`;
+ /*
+ /3m/api/meeting/signIn.do
+ siteId 站点号
+ classId 课堂号(meetingNumber)
+ isTeacher 是否是老师:1 是 0 否
+ password 输入的密码
+ // 请求格式 http://112.126.80.182/3m/api/meeting/signIn.do?siteId=h5test&classId=526661904&password=111111&isTeacher=0
+ */
+ //判断是否是老师
+ var isTeacher = 0;
+ if (confInfo.userRole == _ApeConsts2.default.host) {
+ isTeacher = 1;
+ }
+
+ var url = 'http://' + confInfo.portal + '/3m/api/meeting/signIn.do?siteId=' + confInfo.siteId + '&classId=' + confInfo.classId + '&isTeacher=' + isTeacher + '&password=' + confInfo.password;
+ loger.log('3.会议密码校验', url);
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.status === 200) {
+ return ret.text();
+ } else {
+ loger.error('\u4F1A\u8BAE\u5BC6\u7801\u6821\u9A8C-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ _this3._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_NETWORK);
+ throw '';
+ }
+ }).then(function (ret) {
+ var rectObj = JSON.parse(ret);
+ if (rectObj.flag === 'false' || rectObj.flag === false) {
+ loger.error('\u4F1A\u8BAE\u5BC6\u7801\u6821\u9A8C-\u5931\u8D25.');
+ _this3._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_PASSWORD_WRONG);
+ return;
+ }
+ if (rectObj.flag === 'true' || rectObj.flag === true) {
+ loger.log('\u4F1A\u8BAE\u5BC6\u7801\u6821\u9A8C-\u6210\u529F.');
+ _this3.sendMD5Checking();
+ return;
+ }
+ loger.error('\u4F1A\u8BAE\u5BC6\u7801\u6821\u9A8C-\u534F\u8BAE\u5F02\u5E38.', rectObj);
+ _this3._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_PROTOCOL);
+ }).catch(function (err) {
+ loger.error('\u4F1A\u8BAE\u5BC6\u7801\u6821\u9A8C-\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ _this3._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_FAILED);
+ });
+ }
+
+ //MD5校验-----------------------------------------------------------------------------------------
+
+ }, {
+ key: 'sendMD5Checking',
+ value: function sendMD5Checking() {
+ var _this4 = this;
+
+ var url = 'http://' + confInfo.portal + '/3m/meeting/md5CheckMeeting.do?siteId=' + confInfo.siteId + '&meetingNumber=' + confInfo.classId + '&userId=' + confInfo.userId + '&userName=' + confInfo.userName + '&userType=' + confInfo.userType + '&nopassword=' + confInfo.passwordRequired + '&md5=' + confInfo.md5;
+ loger.log('4.MD5校验', url);
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.status === 200) {
+ return ret.json();
+ } else {
+ loger.error('MD5\u6821\u9A8C-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ _this4._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_NETWORK);
+ throw '';
+ }
+ }).then(function (ret) {
+ if (ret.flag == "true" || ret.flag == true) {
+ /* if (ret.h5_mcu_list) {
+ let server = ret.h5_mcu_list.split(";")[0];
+ confInfo.MCUServerIP = server.split(":")[0];
+ confInfo.MCUServerPort = server.split(":")[1];
+ GlobalConfig.MCUServerIP=confInfo.MCUServerIP;
+ GlobalConfig.MCUServerPort=confInfo.MCUServerPort;
+ }
+ confInfo.maxVideoChannels = ret.maxVideoChannels;
+ confInfo.maxAudioChannels = ret.maxAudioChannels;
+ confInfo.maxMediaChannels = confInfo.maxVideoChannels + confInfo.maxAudioChannels;
+ GlobalConfig.maxVideoChannels=confInfo.maxVideoChannels;
+ GlobalConfig.maxAudioChannels=confInfo.maxAudioChannels;
+ GlobalConfig.maxMediaChannels=confInfo.maxMediaChannels;*/
+ loger.log('MD5校验完成');
+ console.log(ret);
+ _this4._emit(Sass.SUCCESS, ret);
+ } else {
+ loger.log('MD5校验-失败.');
+ _this4._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_MD5_WRONG);
+ }
+ }).catch(function (err) {
+ loger.error('MD5\u6821\u9A8C-\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ _this4._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_FAILED);
+ });
+ }
+
+ // 获取会议基本详情------------------------------------------------------------------------------------
+
+ }, {
+ key: 'getClassDetail',
+ value: function getClassDetail() {
+ var _this5 = this;
+
+ var url = 'http://' + confInfo.portal + '/3m/meeting/getClassH5.do?classNumber=' + confInfo.classId;
+ loger.log('获取Class详情.', url);
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.ok) {
+ return ret.json();
+ } else {
+ loger.error('\u83B7\u53D6Class\u8BE6\u60C5-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ _this5._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_GET_CLASS_DETAIL);
+ throw '';
+ }
+ }).then(function (ret) {
+ if (ret.errorCode === 0) {
+ loger.log('获取Class详情完成');
+ _this5._emit(Sass.CLASS_GET_CLASS_DETAIL, ret);
+ } else {
+ loger.warn('获取Class详情失败.');
+ _this5._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_GET_CLASS_DETAIL);
+ }
+ }).catch(function (err) {
+ loger.error('\u83B7\u53D6Class\u8BE6\u60C5\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ _this5._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_GET_CLASS_DETAIL);
+ });
+ }
+
+ //获取课堂会议的完整信息--------------------------------------------------------------------------------
+
+ }, {
+ key: 'getClassParam',
+ value: function getClassParam() {
+ var _this6 = this;
+
+ /*
+ 参数 (application/x-www-form-urlencoded):
+ 名称 类型 可选 默认值 说明
+ meetingNumber String 否 null 课堂号
+ timestamp String 否 null 时间戳
+ authId String 否 null 验证信息 md5(meetingNumber + timestamp)
+ 返回 (application/json):
+ 名称 类型 说明
+ code int 0 正常
+ 1 课堂号必填
+ 2 无效的课堂号
+ 3 没有对应的站点
+ 4 站点已过期
+ siteId String 站点号
+ meetingNumber String 课堂号 对应的是classId
+ */
+ var timestamp = new Date().getTime();
+ var authId = (0, _md2.default)(confInfo.classId + "" + timestamp); //课堂号+时间戳 的字符串,转成MD5
+ var url = 'http://' + confInfo.portal + '/3m/api/meeting/detail.do?meetingNumber=' + confInfo.classId + '×tamp=' + timestamp + '&authId=' + authId;
+ loger.log('5.获取课堂会议的完整信息 ');
+ console.log(url);
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.ok) {
+ return ret.json();
+ } else {
+ loger.error('\u83B7\u53D6\u8BFE\u5802\u4F1A\u8BAE\u7684\u5B8C\u6574\u4FE1\u606F-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ _this6._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_GET_CLASS_PARAML);
+
+ throw '';
+ }
+ }).then(function (ret) {
+ if (ret.code === 0) {
+ loger.log('获取课堂会议的完整信息完成');
+ _this6._emit(Sass.CLASS_GET_CLASS_PARAM, ret);
+ } else {
+ loger.warn('获取课堂会议的完整信息 失败.');
+ _this6._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_GET_CLASS_PARAML);
+ }
+ }).catch(function (err) {
+ loger.error('\u83B7\u53D6\u8BFE\u5802\u4F1A\u8BAE\u7684\u5B8C\u6574\u4FE1\u606F\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ _this6._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_GET_CLASS_PARAML);
+ });
+ }
+
+ //删除文档-----------------------------------------------------------------------------------------------------
+ /*
+ 删除课堂中的文档,即删除课堂与文档的关联
+ /api/document/deleteRelation.do
+ 参数
+ docId 文档的唯一id
+ classId 课堂号
+ timestamp 时间戳
+ authId md5(docId+classId+timestamp)
+ 返回 (application/json):
+ 0 成功, 1 验证信息错误
+ */
+
+ }, {
+ key: 'sassDeleteDocument',
+ value: function sassDeleteDocument(_param) {
+ var _this7 = this;
+
+ var timestamp = new Date().getTime();
+ var authId = (0, _md2.default)(_param.docId + "" + _param.classId + "" + timestamp); // docId+classId+timestamp的字符串,转成MD5
+ var url = 'http://' + confInfo.portal + '/3m/api/document/deleteRelation.do?docId=' + _param.docId + '&classId=' + confInfo.classId + '×tamp=' + timestamp + '&authId=' + authId;
+ loger.log('sassDeleteDocument', url);
+
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.ok) {
+ return ret.json();
+ } else {
+ loger.error('sassDeleteDocument-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ _this7._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_DOC_DELETE_FAILED);
+
+ throw '';
+ }
+ }).then(function (ret) {
+ if (ret.code === 0) {
+ loger.log('sassDeleteDocument 完成');
+ _this7._emit(Sass.DELETE_DOCUMENT_SUCCESS, _param);
+ } else {
+ loger.warn('sassDeleteDocumnt 失败.');
+ _this7._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_DOC_DELETE_FAILED);
+ }
+ }).catch(function (err) {
+ loger.error('sassDeleteDocument\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ _this7._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_DOC_DELETE_FAILED);
+ });
+ }
+
+ //保存课堂的当前信息-------------------------------------------------------------------------------------------------
+ /*保存课堂的当前信息,首次是插入,后面是更新
+ /api/meeting/saveInfo.do
+ 参数(application/x-www-form-urlencoded):
+ info Json字符串课堂信息,由前端自己维护
+ classId 课堂号
+ timestamp 时间戳
+ authId 做基本验证,md5(classId+timestamp)
+ 返回 (application/json):
+ code 0 成功 1 课堂号为空 2 无效的课堂号 3 验证信息错误*/
+
+ }, {
+ key: 'saveClassStatusInfo',
+ value: function saveClassStatusInfo(_param) {
+ var _this8 = this;
+
+ //{"classStatusInfo":classStatusInfo}
+ var timestamp = new Date().getTime();
+ var authId = (0, _md2.default)(confInfo.classId + "" + timestamp); // (classId+timestamp)的字符串,转成MD5
+ var classStatusInfo = JSON.stringify(_param.classStatusInfo);
+ var url = 'http://' + confInfo.portal + '/3m/api/meeting/saveInfo.do';
+ loger.log('saveClassStatusInfo', url);
+ fetch(url, {
+ method: 'POST',
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded"
+ },
+ body: 'classId=' + confInfo.classId + '&info=' + classStatusInfo + '×tamp=' + timestamp + '&authId=' + authId,
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.ok) {
+ return ret.json();
+ } else {
+ loger.error('saveClassStatusInfo-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ //this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
+ throw '';
+ }
+ }).then(function (ret) {
+ if (ret.code === 0) {
+ loger.log('saveClassStatusInfo 完成');
+ _this8._emit(Sass.CLASS_SAVE_STATUS_INFO_SUCCESS, _param);
+ } else if (ret.code === 1) {
+ loger.log('saveClassStatusInfo 失败 课堂号为空');
+ } else if (ret.code === 2) {
+ loger.log('saveClassStatusInfo 失败 无效的课堂号');
+ } else if (ret.code === 3) {
+ loger.log('saveClassStatusInfo 失败 验证信息错误');
+ } else {
+ loger.warn('saveClassStatusInfo 失败.', ret);
+ //this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
+ }
+ }).catch(function (err) {
+ loger.error('saveClassStatusInfo.\u72B6\u6001\u7801:' + err);
+ //this._emit(MessageTypes.MCU_ERROR,MessageTypes.ERR_DOC_DELETE_FAILED);
+ });
+ }
+
+ //保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同
+
+ }, {
+ key: 'saveClassRecordContrlInfo',
+ value: function saveClassRecordContrlInfo(_param) {
+ var _this9 = this;
+
+ loger.log('保存开始录制信息');
+ var key = "3mang123A";
+ var siteID = _GlobalConfig2.default.siteId;
+ var meetingID = _GlobalConfig2.default.classId;
+ var userID = _GlobalConfig2.default.userId;
+ var userName = _GlobalConfig2.default.userName;
+ var meetingName = _GlobalConfig2.default.className;
+ var startTime = _GlobalConfig2.default.classBeginTime;
+ var endTime = _GlobalConfig2.default.classEndTime;
+ var playUrl = "";
+ var streamName = _GlobalConfig2.default.recordFileName;
+ var confRecordFileName = _GlobalConfig2.default.recordFileName;
+ var downloadUrl = "";
+ var recordStatus = _GlobalConfig2.default.classStatus;
+ var recordTimestamp = _GlobalConfig2.default.classTimestamp;
+
+ var timestamp = new Date().getTime();
+ var authId = (0, _md2.default)(key + siteID + meetingID + timestamp);
+ var url = 'http://' + confInfo.portal + '/3m/recordingMeeting/insertRecordingMeeting.do?siteID=' + siteID + '&meetingID=' + meetingID + '&userID=' + userID + '&userName=' + userName + '&meetingName=' + meetingName + '&startTime=' + startTime + '&endTime=' + endTime + '&playUrl=' + playUrl + '&streamName=' + streamName + '&downloadUrl=' + downloadUrl + '&configFile=' + confRecordFileName + '×tamp=' + timestamp + '&recordTimestamp=' + recordTimestamp + '&authId=' + authId;
+ loger.log('saveClassRecordContrlInfo', url);
+
+ fetch(url, {
+ timeout: 5000
+ }).then(function (ret) {
+ if (ret.ok) {
+ return ret.json();
+ } else {
+ loger.error('\u4FDD\u5B58\u5F00\u59CB\u5F55\u5236\u4FE1\u606F-\u7F51\u7EDC\u5F02\u5E38.\u72B6\u6001\u7801:' + ret.status);
+ throw '';
+ }
+ }).then(function (ret) {
+ if (ret.errorCode === 0) {
+ loger.log('保存开始录制信息 完成');
+ _this9._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param);
+ } else {
+ loger.warn('保存开始录制信息 失败.', ret);
+ }
+ }).catch(function (err) {
+ loger.error('\u4FDD\u5B58\u5F00\u59CB\u5F55\u5236\u4FE1\u606F\u5F02\u5E38.\u72B6\u6001\u7801:' + err);
+ });
+ }
+ /*
+ //根据userIp获取ip相关的信息,参数是userIp
+ getUserIpInfo(token, userIp) {
+ let userIpInfo = new Object;
+ userIpInfo.ret = -1;
+ let ip = userIp;
+ let md5Str = MD5("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3");//("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"),转成MD5
+ let timestamp=new Date().getTime();
+ //let location = "http://ipapi.ipip.net/find?addr=" + ip + "&callback=?&sid=14&uid=5237&sig=" + $.md5("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3");
+ let location = `http://ipapi.ipip.net/find?addr=${ip}&callback=findIpInfoCallback&sid=14&uid=5237&sig=${md5Str}&_=${timestamp}`;
+ loger.log('getUserIpInfo ', userIp,location);
+
+ fetchJsonp(location, {
+ timeout: 3000,
+ jsonpCallback: 'findIpInfoCallback'
+ }) .then(function(response) {
+ return response.json()
+ }).then(function(json) {
+ loger.log('getUserIpInfo parsed json', json)
+ }).catch(function(ex) {
+ loger.log('getUserIpInfo parsing failed', ex.message)
+ })
+ }*/
+
+ /* //获取ip信息返回
+ _findIpInfoCallback(_param){
+ loger.log("getUserIpInfo->findIpInfoCallback",_param);
+ let userIpInfo={};
+ userIpInfo.ret=-1;
+ if(_param){
+ userIpInfo.ret = _param.ret;
+ userIpInfo.country = _param.data[0];//国家
+ userIpInfo.province = _param.data[1];//省份
+ userIpInfo.city = _param.data[2];//城市
+ userIpInfo.isp = _param.data[4];//运营商
+ }
+ this._emit(Sass.SEVER_CHECK_GET_USER_IP_INFO, userIpInfo);
+ }
+ //获取最快的MCU服务器地址,参数是一个ip数组
+ getBestMcuServer(_param) {
+ loger.log('getBestMcuServer ', _param);
+ iphunter(_param, function (fatest_ip_response) {
+ if (!fatest_ip_response) {
+ loger.warn('getBestMcuServer -> nothing!');
+ this._emit(Sass.SEVERCHECK_GET_BEST_MCU, "");
+ } else {
+ loger.log('getBestMcuServer done -> ', fatest_ip_response);
+ this._emit(Sass.SEVERCHECK_GET_BEST_MCU, fatest_ip_response);
+ }
+ }.bind(this), 3000);
+ }
+ //获取最快的MS服务器地址,参数是一个ip数组
+ getBestMsServer(_param) {
+ loger.log('getBestMsServer ', _param);
+ iphunter(_param, function (fatest_ip_response) {
+ if (!fatest_ip_response) {
+ loger.warn('getBestMsServer -> nothing!');
+ this._emit(Sass.SEVER_CHECK_GET_BEST_MS, "");
+ } else {
+ loger.log('getBestMsServer done -> ', fatest_ip_response);
+ this._emit(Sass.SEVER_CHECK_GET_BEST_MS, fatest_ip_response);
+ }
+ }.bind(this), 3000);
+ }*/
+
+ }]);
+
+ return Sass;
+ }(_Emiter3.default);
+
+ Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success';
+ Sass.prototype.CLASS_INIT_SUCCESS = Sass.CLASS_INIT_SUCCESS = 'sass_class_init_success';
+ Sass.prototype.CLASS_GET_CLASS_PARAM = Sass.CLASS_GET_CLASS_PARAM = 'sass_class_getClassParam.message';
+ Sass.prototype.CLASS_GET_CLASS_DETAIL = Sass.CLASS_GET_CLASS_DETAIL = 'sass_class_getClassDetail_message';
+ //Sass.prototype.SEVERCHECK_GET_BEST_MCU = Sass.SEVERCHECK_GET_BEST_MCU = 'sass_class_getBestMcu_message';//获取最快的mcu地址
+ //Sass.prototype.SEVER_CHECK_GET_BEST_MS = Sass.SEVER_CHECK_GET_BEST_MS = 'sass_class_getBestMs_message';//获取最快的MS地址
+ //Sass.prototype.SEVER_CHECK_GET_USER_IP_INFO = Sass.SEVER_CHECK_GET_USER_IP_INFO = 'sass_class_getUserIpInfo_message';//获取最快的MS地址
+
+ Sass.prototype.DELETE_DOCUMENT_SUCCESS = Sass.DELETE_DOCUMENT_SUCCESS = 'sass_class_deleteDocumentSuccess_message'; //删除文档成功
+
+ Sass.prototype.CLASS_SAVE_STATUS_INFO_SUCCESS = Sass.CLASS_SAVE_STATUS_INFO_SUCCESS = 'sass_class_saveClassStatusInfoSuccess_message'; //保存会议状态信息
+ Sass.prototype.CLASS_SAVE_RECORD_INFO_SUCCESS = Sass.CLASS_SAVE_RECORD_INFO_SUCCESS = 'sass_class_saveClassRecordInfoSuccess_message'; //保存录制会议信息
+
+
+ var _default = new Sass();
+
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/Sass.js');
+
+ __REACT_HOT_LOADER__.register(confInfo, 'confInfo', 'D:/work/McuClient/src/Sass.js');
+
+ __REACT_HOT_LOADER__.register(Sass, 'Sass', 'D:/work/McuClient/src/Sass.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/Sass.js');
+ }();
+
+ ;
+
+/***/ },
+/* 5 */
+/***/ function(module, exports) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ // //////////////////////////////////////////////////////////////////////////////
+ //
+ // Copyright (C) 2016-present All Rights Reserved.
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Github Home: https://github.com/AlexWang1987
+ // Author: AlexWang
+ // Date: 2016-08-27 22:58:47
+ // QQ Email: 1669499355@qq.com
+ // Last Modified time: 2016-08-27 23:05:53
+ // Description: LiveClass-Loger
+ //
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var Loger = function () {
+ function Loger(info) {
+ _classCallCheck(this, Loger);
+
+ this.sdkInfo = info || '';
+ this.id = this.initId();
+ }
+
+ _createClass(Loger, [{
+ key: 'initId',
+ value: function initId() {
+ var infoType = this.sdkInfo.constructor.name.toLowerCase();
+ if (infoType === 'string') {
+ return this.sdkInfo;
+ }
+ if (infoType === 'object') {
+ return this.sdkInfo.mid || '';
+ }
+ return '';
+ }
+ }, {
+ key: 'log',
+ value: function log() {
+ for (var _len = arguments.length, msg = Array(_len), _key = 0; _key < _len; _key++) {
+ msg[_key] = arguments[_key];
+ }
+
+ this._log(Loger.LOG, msg);
+ }
+ }, {
+ key: 'warn',
+ value: function warn() {
+ for (var _len2 = arguments.length, msg = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
+ msg[_key2] = arguments[_key2];
+ }
+
+ this._log(Loger.WARN, msg);
+ }
+ }, {
+ key: 'error',
+ value: function error() {
+ for (var _len3 = arguments.length, msg = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
+ msg[_key3] = arguments[_key3];
+ }
+
+ this._log(Loger.ERROR, msg);
+ }
+ }, {
+ key: 'data',
+ value: function data() {
+ for (var _len4 = arguments.length, msg = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
+ msg[_key4] = arguments[_key4];
+ }
+
+ this._log(Loger.DATA, msg);
+ }
+ }, {
+ key: '_log',
+ value: function _log(type, msg) {
+ msg = JSON.stringify(msg);
+
+ var logMsg = this.id + ' -> ' + msg;
+ if (type >= Loger.logLevel) {
+ switch (type) {
+ case Loger.LOG:
+ console.log(logMsg);
+ break;
+ case Loger.WARN:
+ console.warn(logMsg);
+ break;
+ case Loger.ERROR:
+ console.error(logMsg);
+ break;
+ case Loger.DATA:
+ console.log(logMsg);
+ break;
+ }
+ }
+ }
+ }]);
+
+ return Loger;
+ }();
+
+ Loger.LOG = 0;
+ Loger.WARN = 1;
+ Loger.ERROR = 2;
+ Loger.NO = Infinity;
+ Loger.logLevel = Loger.LOG;
+ Loger.DATA = 5;
+ var _default = {
+ getLoger: function getLoger(info) {
+ return new Loger(info);
+ },
+ setLogLevel: function setLogLevel(logLevel) {
+ Loger.logLevel = logLevel;
+ },
+ LOG: Loger.LOG,
+ WARN: Loger.WARN,
+ ERROR: Loger.ERROR,
+ NO: Loger.NO,
+ DATA: Loger.DATA
+ };
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(Loger, 'Loger', 'D:/work/McuClient/src/Loger.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/Loger.js');
+ }();
+
+ ;
+
+/***/ },
+/* 6 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ /**
+ *事件消息ID和错误码 定义
+ */
+
+ function MessageTypes() {}
+
+ //--------------------事件相关的定义--------------------------------------
+ //初始化相关事件定义
+ MessageTypes.CLASS_INIT_SUCCESS = "class_init_success"; //'class.init.success';//初始化成功
+ //MessageTypes.CLASS_INIT_FAILED='class.init.failed';//初始化失败
+
+ //加入会议相关事件定义
+ MessageTypes.CLASS_JOIN_MCU_SUCCESS = "class_join_mcu_success"; // 'join.mcu.success';
+ //MessageTypes.CLASS_JOIN_FAILED = 'join.class.failed';
+
+ //会议信息和操作事件定义
+ //MessageTypes.CLASS_SHOW_DETAIL = 'class_detail.message';
+ MessageTypes.CLASS_JOIN_SUCCESS = "class_join_success"; // 'join.class.success';
+ MessageTypes.CLASS_UPDATE_ROSTER_NUM = "class_update_roster_num"; // 'roster_num.message';
+ MessageTypes.CLASS_INSERT_ROSTER = "class_insert_roster"; // 'roster.insert.message';
+ MessageTypes.CLASS_DELETE_ROSTER = "class_delete_roster"; // 'roster.delete.message';
+ MessageTypes.CLASS_NONENTITY_ROSTER = "class_nonenetity_roster"; // 'roster.nonentity.message';
+
+ MessageTypes.CLASS_EXIT = "class_exit"; // 'class.exit';//退出 关闭会议
+ MessageTypes.CLASS_UPTATE_STATUS = "class_update_status"; // 'class.update.status';//更新会议状态信息
+ MessageTypes.CLASS_STATUS_INFO_CHANGE = "class_status_info_change"; // 'class.status.info.change';//会议状态信息发生改变,需要保存数据到sass和同步MCU
+
+ MessageTypes.CLASS_UPDATE_TIMER = "class_update_timer"; //'class.update.timer';//更新当前上课的时间
+
+ MessageTypes.CLASS_RECORD_START = "class_record_start"; //'class.record.start';//开始录制
+
+
+ //聊天模块事件定义
+ MessageTypes.CHAT_RECEIVE = "chat_receive_message"; // 'chat.receive';
+
+ //视频模块事件定义
+ MessageTypes.VIDEO_PLAY = "video_play"; // 'video.play';//播放视频
+ MessageTypes.VIDEO_STOP = "video_stop"; //'video.stop';//停止视频
+ MessageTypes.VIDEO_UPDATE = "video_update"; // //这个监听事件不能删除,需要通知会议模块,检查channel占用(内部使用)
+ MessageTypes.VIDEO_BROADCAST = "video_broadcast"; //'video.broadcast';
+
+ //音频模块事件定义
+ MessageTypes.AUDIO_PLAY = "audio_play"; // 'audio.play';//播放
+ MessageTypes.AUDIO_STOP = "audio_stop"; //'audio.stop';//停止
+ MessageTypes.AUDIO_UPDATE = "audio_update"; //这个监听事件不能删除,需要通知会议模块,检查channel占用(内部使用)
+ MessageTypes.AUDIO_BROADCAST = "audio_broadcast"; //'audio.broadcast';
+
+
+ //文档模块事件定义
+ MessageTypes.DOC_DELETE = "document_delete"; //'document.delete';//删除文档
+ MessageTypes.DOC_UPDATE = "document_update"; // 'document.update';//更新文档(添加、变更)
+ //MessageTypes.DOC_SHOW = 'document.show';
+ //MessageTypes.DOC_UPLOAD='document.upload';//上传文档
+ //MessageTypes.DOC_COMMAND='document.command';//操作文档
+ //MessageTypes.DOC_SWITCH = 'document.switch';//切换文档
+ //MessageTypes.DOC_DELETE='document.delete';//删除文档
+ //MessageTypes.DOC_ANNOTATION = 'document.annotation';//笔记
+
+
+ //白板笔记事件定义
+ MessageTypes.WHITEBOARD_ANNOTATION_UPDATE = "whiteboard_annotation_update"; // 'whiteboard.annotation.update';
+ //MessageTypes.WHITEBOARD_ANNOTAION_INSERT = 'whiteboard.annotation.insert';
+ //MessageTypes.WHITEBOARD_ANNOTAION_DELETE = 'whiteboard.annotation.delete';
+ //MessageTypes.WHITEBOARD_ANNOTATION_CLEAR = 'whiteboard.annotation.clear';
+
+
+ //错误事件定义
+ MessageTypes.MCU_ERROR = "mcu_error"; //"mcuError";//MCU错误(内部使用)
+ MessageTypes.ERROR_EVENT = "error_event"; //外部监听错误的消息ID(外部使用)
+
+
+ //---------------错误消息 ErrorCode 定义-------------------------------------------------
+
+ //会议初始化失败的几种情况
+ MessageTypes.ERR_CLASS_INIT_PARAM = 100; //初始化参数错误
+ MessageTypes.ERR_CLASS_INIT_NETWORK = 101; //初始化网络错误
+ MessageTypes.ERR_CLASS_INIT_PROTOCOL = 102; //初始化协议错误
+ MessageTypes.ERR_CLASS_INIT_FAILED = 103; //初始化验证失败
+ MessageTypes.ERR_CLASS_INIT_FAILED_1 = 104; //初始化验证失败,课堂号必填
+ MessageTypes.ERR_CLASS_INIT_FAILED_2 = 105; //初始化验证失败,无效的课堂号
+ MessageTypes.ERR_CLASS_INIT_FAILED_3 = 106; //初始化验证失败,没有对应的站点
+ MessageTypes.ERR_CLASS_INIT_FAILED_4 = 107; //初始化验证失败,站点已过期
+
+ //加入会议失败的几种情况
+ MessageTypes.ERR_CLASS_JOIN_NETWORK = 200; //加入会议网络错误
+ MessageTypes.ERR_CLASS_JOIN_PROTOCOL = 201; //加入会议化协议错误
+ MessageTypes.ERR_CLASS_JOIN_FAILED = 202; //加入会议化异常错误
+ MessageTypes.ERR_CLASS_JOIN_PARAM = 203; //加入会议参数错误
+ MessageTypes.ERR_CLASS_JOIN_FULL = 204; //人数已满
+ MessageTypes.ERR_CLASS_MD5_WRONG = 205; //MD5验证失败
+ MessageTypes.ERR_CLASS_PASSWORD_WRONG = 206; //密码错误
+ MessageTypes.ERR_CLASS_JOIN_CONFILICT = 207; //已经在其它地方登陆
+ MessageTypes.ERR_CLASS_KICK_OUT = 208; //有相同身份的人员加入课堂,自己被踢出;
+
+ MessageTypes.ERR_GET_CLASS_DETAIL = 300; //获取classDetail失败
+ MessageTypes.ERR_GET_CLASS_PARAML = 301; //获取ClassParam失败
+
+ //APE
+ MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN = 500; //APE在sdk为初始化或未加入会议之前调用发送数据接口
+ MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG = 501; //APE在接口调用时参数错误
+
+ //DOC
+ MessageTypes.ERR_DOC_DELETE_FAILED = 600; //删除文档失败
+ MessageTypes.ERR_DOC_DELETE_FAILED_PARAM = 601; //删除文档失败,参数错误
+
+
+ MessageTypes.ERR_SDK_FAILED = 700; // sdk还没初始化
+ MessageTypes.ERR_INTERFACE_NONE = 701; //调用的接口不存在
+ MessageTypes.ERR_INTERFACE_PARAMS_ERROR = 702; //调用的接口,传递的参数不正确
+
+ MessageTypes.ERR_NETWORK = 10000; //网络错误
+ MessageTypes.ERR_UNKNOWN = 10001; //未知错误
+
+ MessageTypes.ERR_SOCKET_DISCONNECT = 20000; //MCU断开连接,已经离开会议
+
+ //---------------错误消息 Error Reson 定义-------------------------------------------------
+ MessageTypes.ErrorReson = {};
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_PARAM] = "初始化参数错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_NETWORK] = "初始化网络错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_PROTOCOL] = "初始化协议错误";
+
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED] = "初始化验证失败";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_1] = "初始化验证失败,课堂号必填";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_2] = "初始化验证失败,无效的课堂号";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_3] = "初始化验证失败,没有对应的站点";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_INIT_FAILED_4] = "初始化验证失败,站点已过期";
+
+ //加入会议失败的几种情况
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_NETWORK] = "加入会议网络错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PROTOCOL] = "加入会议化协议错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FAILED] = "加入会议化异常错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_PARAM] = "加入会议参数错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_FULL] = "人数已满";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_MD5_WRONG] = "MD5验证失败";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_PASSWORD_WRONG] = "密码错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_JOIN_CONFILICT] = "已经在其它地方登陆";
+ MessageTypes.ErrorReson[MessageTypes.ERR_CLASS_KICK_OUT] = "有相同身份的人员加入课堂,自己被踢出课堂";
+
+ MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_DETAIL] = "获取classDetail失败";
+ MessageTypes.ErrorReson[MessageTypes.ERR_GET_CLASS_PARAML] = "获取ClassParam失败";
+
+ //APE
+ MessageTypes.ErrorReson[MessageTypes.ERR_APE_SEND_FAILED_NO_JOIN] = "APE在sdk为初始化或未加入会议之前调用发送数据接口";
+ MessageTypes.ErrorReson[MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG] = "APE在接口调用时参数错误";
+
+ //DOC
+ MessageTypes.ErrorReson[MessageTypes.ERR_DOC_DELETE_FAILED] = "删除文档失败";
+ MessageTypes.ErrorReson[MessageTypes.ERR_DOC_DELETE_FAILED_PARAM] = "删除文档失败,参数错误";
+
+ MessageTypes.ErrorReson[MessageTypes.ERR_SDK_FAILED] = "sdk还没初始化";
+ MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_NONE] = "调用的接口不存在";
+ MessageTypes.ErrorReson[MessageTypes.ERR_INTERFACE_PARAMS_ERROR] = "调用的接口,传递的参数不正确";
+
+ MessageTypes.ErrorReson[MessageTypes.ERR_NETWORK] = "网络错误";
+ MessageTypes.ErrorReson[MessageTypes.ERR_UNKNOWN] = "未知错误";
+
+ MessageTypes.ErrorReson[MessageTypes.ERR_SOCKET_DISCONNECT] = "MCU断开连接,已经离开会议";
+
+ var _default = MessageTypes;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(MessageTypes, "MessageTypes", "D:/work/McuClient/src/MessageTypes.js");
+
+ __REACT_HOT_LOADER__.register(_default, "default", "D:/work/McuClient/src/MessageTypes.js");
+ }();
+
+ ;
+
+/***/ },
+/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
+ * 全局数据管理
+ * */
+
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ var loger = _Loger2.default.getLoger('GlobalConfig');
+
+ var GlobalConfig = function () {
+ function GlobalConfig() {
+ _classCallCheck(this, GlobalConfig);
+
+ this._currentStatus = null;
+ }
+
+ _createClass(GlobalConfig, null, [{
+ key: 'getCurrentStatus',
+ value: function getCurrentStatus() {
+ if (this._currentStatus == null) {
+ this._currentStatus = this.statusCode_0;
+ }
+ return this._currentStatus;
+ }
+ }, {
+ key: 'setCurrentStatus',
+ value: function setCurrentStatus(_data) {
+ this._currentStatus = _data;
+ }
+ }, {
+ key: 'getClassDetail',
+ value: function getClassDetail() {
+ return this.classDetail;
+ }
+ }, {
+ key: 'setClassDetail',
+ value: function setClassDetail(_data) {
+ this.classDetail = _data;
+ }
+ }, {
+ key: 'getClassInfo',
+ value: function getClassInfo() {
+ var classInfo = {};
+ classInfo.siteId = this.siteId;
+ classInfo.classId = this.classId;
+ classInfo.className = this.className;
+ classInfo.h5Module = this.h5Module;
+ classInfo.nodeId = this.nodeId;
+ classInfo.topNodeID = this.topNodeID;
+ classInfo.userRole = this.userRole;
+ classInfo.role = this.role;
+ classInfo.isHost = this.isHost;
+ classInfo.userId = this.userId;
+ classInfo.userName = this.userName;
+ classInfo.password = this.password;
+ classInfo.userType = this.userType;
+ classInfo.passwordRequired = this.passwordRequired;
+ classInfo.md5 = this.md5;
+ classInfo.msType = this.msType;
+ classInfo.portal = this.portal;
+ classInfo.mcuDelay = this.mcuDelay;
+ classInfo.MCUServerIP = this.MCUServerIP;
+ classInfo.MCUServerPort = this.MCUServerPort;
+ classInfo.maxVideoChannels = this.maxVideoChannels;
+ classInfo.maxAudioChannels = this.maxAudioChannels;
+
+ return classInfo;
+ }
+
+ //获取当前的课堂状态的信息
+
+ }, {
+ key: 'setClassStatusInfo',
+
+ //设置当前的课堂状态的信息
+ value: function setClassStatusInfo(_data) {
+ loger.log("setClassStatusInfo");
+ if (_data == null) {
+ loger.warn("classStatusInfo error,_data:", _data);
+ return;
+ }
+ var data = _data;
+
+ this.siteId = data.siteId || this.siteId; //站点号
+
+ this.classId = data.classId || this.classId;
+ this.className = data.className || this.className;
+ this.classType = data.classType || this.classType; //课堂类型
+ this.classStatus = data.classStatus || this.classStatus; //课堂的状态
+ this.classStartTime = data.classStartTime || this.classStartTime; //课堂点击开始时间
+
+ this.classStopTime = data.classStopTime || this.classStopTime; //最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
+ this.classTimestamp = data.classTimestamp || this.classTimestamp; //相对于点开始课堂的时间戳
+
+ this.classBeginTime = data.classBeginTime || this.classBeginTime; //课堂创建的时间,这个是Sass返回的
+ this.classEndTime = data.classEndTime || this.classEndTime; //课堂结束的时间,这个是Sass返回的
+
+ this.recordStatus = data.recordStatus || this.recordStatus; //当前录制状态
+ this.recordTimestamp = data.recordTimestamp || this.recordTimestamp; //相对于首次开始录制的时间戳
+ this.recordFileName = data.recordFileName || this.recordFileName; //录制的文件名
+ this.recordDownloadUrl = data.recordDownloadUrl || this.recordDownloadUrl; //下载地址
+
+ this.activeDocId = data.activeDocId || this.activeDocId; //当前激活的文档ID
+ this.activeDocCurPage = data.activeDocCurPage || this.activeDocCurPage; //当前激活的文档的当前页
+ }
+
+ // 判断自己是否主持人角色
+
+ }, {
+ key: 'setDocListPrepare',
+
+ //储存已经提前上传的文档列表
+ value: function setDocListPrepare(_data) {
+ if (_data == null) return;
+ this.docListPrepare = _data;
+ }
+ }, {
+ key: 'getDocListPrepare',
+ value: function getDocListPrepare() {
+ return this.docListPrepare;
+ }
+ //储存录制列表
+
+ }, {
+ key: 'setRecordList',
+ value: function setRecordList(_data) {
+ if (_data == null) return;
+ this.recordList = _data;
+ }
+ }, {
+ key: 'getRecordList',
+ value: function getRecordList() {
+ return this.recordList;
+ }
+
+ //文档服务器列表
+
+ }, {
+ key: 'setDocList',
+ value: function setDocList(_data) {
+ if (_data == null) return;
+ this.docList = _data;
+ }
+ }, {
+ key: 'getDocList',
+ value: function getDocList() {
+ return this.docList;
+ }
+ //ms列表
+
+ }, {
+ key: 'setMsList',
+ value: function setMsList(_data) {
+ if (_data == null) return;
+ this.msList = _data;
+ }
+ }, {
+ key: 'getMsList',
+ value: function getMsList() {
+ return this.msList;
+ }
+
+ //mcu列表
+
+ }, {
+ key: 'setMcuList',
+ value: function setMcuList(_data) {
+ if (_data == null) return;
+ this.mcuList = _data;
+ }
+ }, {
+ key: 'getMcuList',
+ value: function getMcuList() {
+ return this.mcuList;
+ }
+
+ //声音列表
+
+ }, {
+ key: 'setMusicList',
+ value: function setMusicList(_data) {
+ if (_data == null) return;
+ this.musicList = _data;
+ }
+ }, {
+ key: 'getMusicList',
+ value: function getMusicList() {
+ return this.musicList;
+ }
+ //已经上传的声音列表
+
+ }, {
+ key: 'setMusicListPrepare',
+ value: function setMusicListPrepare(_data) {
+ if (_data == null) return;
+ this.musicListPrepare = _data;
+ }
+ }, {
+ key: 'getMusicListPrepare',
+ value: function getMusicListPrepare() {
+ return this.musicListPrepare;
+ }
+
+ //rs列表
+
+ }, {
+ key: 'setRsList',
+ value: function setRsList(_data) {
+ if (_data == null) return;
+ this.rsList = _data;
+ }
+ }, {
+ key: 'getRsList',
+ value: function getRsList() {
+ return this.rsList;
+ }
+ }, {
+ key: 'classStatusInfo',
+ get: function get() {
+ var classStatusInfo = {};
+
+ classStatusInfo.siteId = this.siteId; //站点号
+
+ classStatusInfo.classId = this.classId;
+ classStatusInfo.className = this.className;
+ classStatusInfo.classType = this.classType; //课堂类型
+ classStatusInfo.classStatus = this.classStatus; //课堂的状态
+ classStatusInfo.classStartTime = this.classStartTime; //课堂点击开始时间
+ classStatusInfo.classStopTime = this.classStopTime; //最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
+ classStatusInfo.classTimestamp = this.classTimestamp; //相对于点开始课堂的时间戳
+
+ classStatusInfo.classBeginTime = this.classBeginTime; //课堂创建的时间,这个是Sass返回的
+ classStatusInfo.classEndTime = this.classEndTime; //课堂结束的时间,这个是Sass返回的
+
+ classStatusInfo.recordStatus = this.recordStatus; //当前录制状态
+ classStatusInfo.recordTimestamp = this.recordTimestamp; //相对于首次开始录制的时间戳
+ classStatusInfo.recordFileName = this.recordFileName; //录制的文件名
+ classStatusInfo.recordDownloadUrl = this.recordDownloadUrl; //下载地址
+
+ classStatusInfo.serverTimestamp = this.serverTimestamp; //当前的系统时间戳
+ classStatusInfo.activeDocId = this.activeDocId; //当前激活的文档ID
+ classStatusInfo.activeDocCurPage = this.activeDocCurPage; //当前激活的文档的当前页
+ return classStatusInfo;
+ }
+ }, {
+ key: 'isHost',
+ get: function get() {
+ if (this.userRole == _ApeConsts2.default.host) {
+ return true;
+ }
+ return false;
+ }
+
+ // 判断自己是否助教角色
+
+ }, {
+ key: 'isAssistant',
+ get: function get() {
+ if (this.userRole == _ApeConsts2.default.assistant) {
+ return true;
+ }
+ return false;
+ }
+
+ // 判断自己是否主讲人角色
+
+ }, {
+ key: 'isPresenter',
+ get: function get() {
+ if (this.userRole == _ApeConsts2.default.presenter) {
+ return true;
+ }
+ return false;
+ }
+
+ // 判断自己是否普通角色
+
+ }, {
+ key: 'isNormal',
+ get: function get() {
+ if (this.userRole == _ApeConsts2.default.normal) {
+ return true;
+ }
+ return false;
+ }
+
+ // 判断自己是否是隐身用户
+
+ }, {
+ key: 'isInvisible',
+ get: function get() {
+ if (this.userRole == _ApeConsts2.default.invisible) {
+ return true;
+ }
+ return false;
+ }
+ }, {
+ key: 'serverTimestamp',
+ get: function get() {
+ return _EngineUtils2.default.creatTimestamp();
+ }
+ }]);
+
+ return GlobalConfig;
+ }();
+
+ GlobalConfig.statusCode_0 = { "code": 0, message: "SDK 未初始化" };
+ GlobalConfig.statusCode_1 = { "code": 1, message: "未加入会议" };
+ GlobalConfig.statusCode_2 = { "code": 2, message: "已经加入会议" };
+ GlobalConfig.statusCode_3 = { "code": 3, message: "已经离开会议" };
+ GlobalConfig.statusCode_4 = { "code": 4, message: "未知状态" };
+
+ GlobalConfig.md5 = "";
+ GlobalConfig.msType = 1; //目前固定用这个
+ GlobalConfig.mcuDelay = 60; //默认的延迟时间 flash中使用的是3000毫秒
+ GlobalConfig.docDelay = 1600; //文档模块加入成功之后延迟发送送成功的消息给主模块
+ GlobalConfig.portal = "112.126.80.182:80"; //Sass IP
+
+ //GlobalConfig.ip="112.126.80.182";
+ //GlobalConfig.port="80";
+
+ GlobalConfig.MCUServerIP = "114.215.195.70";
+ GlobalConfig.MCUServerPort = 9003;
+
+ GlobalConfig.MSServerIP = ""; //推流 播流的地址
+ GlobalConfig.MSServerPort = "";
+
+ //m3u8播流地址
+ GlobalConfig.RSServerIP = "";
+ GlobalConfig.RSServerPort = "";
+
+ //DOC
+ GlobalConfig.DOCServerIP = "";
+ GlobalConfig.DOCServerPort = "";
+
+ GlobalConfig.RecordServerIP = "";
+ GlobalConfig.RecordServerPort = "";
+
+ GlobalConfig.maxVideoChannels = 0;
+ GlobalConfig.maxAudioChannels = 0;
+
+ GlobalConfig.hasCamera = false; //摄像头是否可用
+ GlobalConfig.hasMicrophone = false; //麦克风是否可用
+
+ GlobalConfig.deviceType = 0; //设备类型 0:电脑 1:安卓 2:ios
+ GlobalConfig.userIp = ""; //用户当前IP
+ GlobalConfig.userId = 0;
+ GlobalConfig.userName = "";
+
+ GlobalConfig.nodeId = 0; //随机生成 mcu中的唯一ID
+ GlobalConfig.passwordRequired = false;
+ GlobalConfig.password = "";
+ GlobalConfig.userType = 8;
+ GlobalConfig.userRole = _ApeConsts2.default.normal; //用户的身份,5种类型:
+ GlobalConfig.role = _ApeConsts2.default.NR_NORMAL; //课堂角色身份
+
+ GlobalConfig.h5Module = 1; //是否支持H5
+ GlobalConfig.topNodeID = 101; //现在固定值,还不知道是做什么用
+
+ GlobalConfig.siteId = "gust"; //站点号
+ GlobalConfig.className = ""; // 课程名称
+ GlobalConfig.classId = 0; //课堂号=classId=meetingNumber 之后统一修改为classId
+ GlobalConfig.classType = _ApeConsts2.default.CLASS_TYPE_INTERACT; //课堂类型 1:互动课堂,2:直播课堂
+ GlobalConfig.classStatus = _ApeConsts2.default.CLASS_STATUS_WAIT; // 0;//课堂还未开始 1;//直播中 2 //课间休息 3已经停止
+ GlobalConfig.classStartTime = ""; //课堂点击开始时间
+ GlobalConfig.classStopTime = ""; //最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
+ GlobalConfig.classBeginTime = ""; //课堂创建的时间,这个是Sass返回的
+ GlobalConfig.classEndTime = ""; //课堂结束的时间,这个是Sass返回的
+ GlobalConfig.classTimestamp = 0; //从课堂开始到现在的时
+
+ GlobalConfig.recordStatus = false; //当前录制状态
+ GlobalConfig.recordTimestamp = 0; //相对于首次开始录制的进行时间
+ GlobalConfig.recordFileName = ""; //录制的文件名,如 果为空就创建一个
+ GlobalConfig.recordDownloadUrl = ""; //下载地址
+ GlobalConfig.recordReplaytickValues = {}; // 滚动条关键点,用于快进快退
+
+ GlobalConfig.updateClassInfoDelay = 30; //(秒),每隔30秒同步一次会议状态的并保存到Sass
+ //GlobalConfig.serverTimestamp=0;//当前的系统时间戳 用get set 获取
+
+
+ GlobalConfig.activeDocId = 0; //当前激活的文档ID
+ GlobalConfig.activeDocCurPage = 1; //当前激活的文档的当前页
+
+
+ GlobalConfig.classAllParam = {}; //Sass直接返回的所有会议信息(最全)
+ GlobalConfig.classDetail = {}; //Sass直接返回的当前课堂基本信息
+
+ GlobalConfig.docListPrepare = []; // 已经提前上传的文档,进入课堂后需要自动加载
+ GlobalConfig.recordList = []; //录制服务器地址集合
+ GlobalConfig.docList = []; //文档服务器地址集合
+ GlobalConfig.mcuList = []; //录制服务器地址集合
+ GlobalConfig.msList = []; //ms服务器地址集合
+ GlobalConfig.musicList = []; //music服务器地址集合
+ GlobalConfig.musicListPrepare = []; //提提前上传的music集合
+ GlobalConfig.rsList = [];
+
+ GlobalConfig.country = ""; //国家
+ GlobalConfig.city = ""; //城市
+ GlobalConfig.province = ""; //服务商
+ GlobalConfig.isp = ""; //服务商
+
+ var _default = GlobalConfig;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/GlobalConfig.js');
+
+ __REACT_HOT_LOADER__.register(GlobalConfig, 'GlobalConfig', 'D:/work/McuClient/src/GlobalConfig.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/GlobalConfig.js');
+ }();
+
+ ;
+
+/***/ },
+/* 8 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ exports.default = ApeConsts;
+ function ApeConsts(id) {
+ for (var type_const in ApeConsts) {
+ if (ApeConsts[type_const] === id) {
+ return type_const;
+ }
+ }
+ }
+
+ //课堂状态
+ ApeConsts.CLASS_STATUS_WAIT = 0; //课堂还未开始
+ ApeConsts.CLASS_STATUS_STARTED = 1; //直播中
+ ApeConsts.CLASS_STATUS_PAUSE = 2; //暂停
+ ApeConsts.CLASS_STATUS_CLOSE = 3; //结束//这个是点击结束会议,把所有人踢出课堂,然后把状态值还原为0*************
+ ApeConsts.CLASS_STATUS_UPTATE = 4; //更新课堂状态信息
+
+ ApeConsts.CLASS_WAIT_START = "class.wait.start"; //课堂还未开始
+ ApeConsts.CLASS_STARTING = "class.started"; //直播中
+ ApeConsts.CLASS_PAUSING = "class.pause"; //暂停
+ ApeConsts.CLASS_PAUSING = "class.closed"; //关闭
+ ApeConsts.CLASS_PAUSING = "class.update"; //更新当前的状态信息
+
+
+ //课堂控制
+ ApeConsts.CLASS_ACTION_CLOSE_ALL = 1; //所有人关闭会议
+
+ //课堂类型
+ ApeConsts.CLASS_TYPE_INTERACT = 1; // 互动课堂,通过MS转发音视频,不能进行H5观看
+ ApeConsts.CLASS_TYPE_LIVE = 2; // 直播课堂,通过CDN转发音视频,不能进行音视频互动
+
+
+ /*
+ flash
+ public static const NR_GUEST:uint = 0; // 客人
+ public static const NR_NORMAL:uint = 1; // 普通与会者
+ public static const NR_ADMIN:uint = 2; // 管理员
+ public static const NR_MASTER:uint = 4; // 主持人
+ public static const NR_PRESENTER:uint = 8; // 主讲人
+ public static const NR_ASSISTANT:uint = 16; // 助教
+ public static const NR_INVISIBLE:uint = 32; // 隐身用户
+ */
+
+ //角色身份
+ //ApeConsts.NR_GUEST = 0; // 客人
+ ApeConsts.NR_NORMAL = 1; // 普通与会者
+ ApeConsts.NR_ADMIN = 2; // 管理员
+ ApeConsts.NR_HOST = 4; // 主持人
+ ApeConsts.NR_PRESENTER = 8; // 主讲人
+ ApeConsts.NR_ASSISTANT = 16; // 助教
+ ApeConsts.NR_INVISIBLE = 32; // 隐身用户
+
+ //用户的身份,5种类型:
+ ApeConsts.host = "host"; //(主持人/老师)
+ ApeConsts.presenter = "presenter"; //(主讲人)
+ ApeConsts.assistant = "assistant"; //(助教)
+ ApeConsts.normal = "normal"; //(普通角色/学生)
+ ApeConsts.record = "record"; //(暂时没用.
+ ApeConsts.invisible = "invisible"; //隐身用户
+
+ //下面做身份的数字和字符串对应关系
+ ApeConsts.userTypes = {};
+ ApeConsts.userTypes[ApeConsts.NR_NORMAL] = ApeConsts.normal;
+ ApeConsts.userTypes[ApeConsts.NR_ADMIN] = ApeConsts.record;
+ ApeConsts.userTypes[ApeConsts.NR_HOST] = ApeConsts.host;
+ ApeConsts.userTypes[ApeConsts.NR_PRESENTER] = ApeConsts.presenter;
+ ApeConsts.userTypes[ApeConsts.NR_ASSISTANT] = ApeConsts.assistant;
+ ApeConsts.userTypes[ApeConsts.NR_INVISIBLE] = ApeConsts.invisible;
+
+ ApeConsts.userTypesToId = {};
+ ApeConsts.userTypesToId[ApeConsts.normal] = ApeConsts.NR_NORMAL;
+ ApeConsts.userTypesToId[ApeConsts.record] = ApeConsts.NR_ADMIN;
+ ApeConsts.userTypesToId[ApeConsts.host] = ApeConsts.NR_HOST;
+ ApeConsts.userTypesToId[ApeConsts.presenter] = ApeConsts.NR_PRESENTER;
+ ApeConsts.userTypesToId[ApeConsts.assistant] = ApeConsts.NR_ASSISTANT;
+ ApeConsts.userTypesToId[ApeConsts.invisible] = ApeConsts.NR_INVISIBLE;
+
+ ////最新定义的角色身份 20170220
+ //ApeConsts.USER_TYPE_HOST=1;//(主持人/老师)
+ //ApeConsts.USER_TYPE_ASSISTANT=2;//(助教)
+ //ApeConsts.USER_TYPE_NORMAL=8;//(普通角色/学生)
+ //ApeConsts.USER_TYPE_MONITOR_INVISIBLE=32;//(监课/隐身)
+ //
+ ////
+ //ApeConsts.USER_TYPE_HOST_STRING="host";//(主持人/老师)
+ //ApeConsts.USER_TYPE_ASSISTANT_STRING="assistant";//(助教)
+ //ApeConsts.USER_TYPE_NORMAL_STRING="normal";//(普通角色/学生)
+ //ApeConsts.USER_TYPE_MONITOR_INVISIBLE_STRING="invisible";//(监课/隐身)
+
+
+ /*msType type*/
+ ApeConsts.MS_TYPE_DEFAULT = 0; //默认MS,(废弃)
+ ApeConsts.MS_TYPE_FMS = 1; //第三方FMS,目前一直用这个
+
+
+ //用户状态
+ ApeConsts.USER_HAND_UP = 0x0020; // 举手
+ ApeConsts.USER_MIC_OPEN = 0x0040; // 麦克风开启
+ ApeConsts.USER_CAMERA_OPEN = 0x0080; // 视频开启
+
+
+ //VIDEO MIC 流媒体消息操作控制类型
+ ApeConsts.MEDIA_ACTION_DEFAULT = 0;
+
+ ApeConsts.MEDIA_ACTION_OPEN_CAMERA = 1; // "open.camera";
+ ApeConsts.MEDIA_ACTION_CLOSE_CAMERA = 2; // "close.camera";
+
+ ApeConsts.MEDIA_ACTION_OPEN_MIC = 3; //"open.mic";
+ ApeConsts.MEDIA_ACTION_CLOSE_MIC = 4; //"close.mic";
+
+
+ // VIDEO AUDIO CHANNEL使用状态
+ ApeConsts.CHANNEL_STATUS_RELEASED = 0; ///< 无人占用状态
+ ApeConsts.CHANNEL_STATUS_OPENING = 1; ///< 已经占用成功
+
+ //媒体类型
+ ApeConsts.MEDIA_TYPE_DEFAULT = 0; //没有类型
+ ApeConsts.MEDIA_TYPE_VIDEO = 1; //视频流(包含音频)
+ ApeConsts.MEDIA_TYPE_AUDIO = 2; //音频流
+
+ //return返回值状态
+ ApeConsts.RETURN_SUCCESS = 0; //成功
+ ApeConsts.RETURN_FAILED = 1; //失败
+
+ ////FLASH中使用下面4个
+ //ApeConsts.CGS_RELEASED = 0;///< 无人占用状态
+ //ApeConsts.CGS_PENDING = 1;///< 占用成功,等待打开
+ //ApeConsts.CGS_OPENNED = 2;///< 打开成功
+ //ApeConsts.CGS_GRABBING = 3; ///< 准备占用中, 属于本地状态机需要用的状态,在多点数据库中不存在。
+ //
+
+
+ ApeConsts.INVALIDATE_CHANNEL_ID = -1;
+ ApeConsts.INVALIDATE_NODE_ID = -1;
+
+ // doc update status
+ ApeConsts.DOC_ACTION_NORMAL = 0; //无操作
+ ApeConsts.DOC_ACTION_SWITCH_DOC = 1; //切换文档
+ ApeConsts.DOC_ACTION_SWITCH_PAGE = 2; //文档翻页
+ ApeConsts.DOC_ACTION_COMMAND = 3; //文档操作:滚动、缩放
+
+
+ // defs for common session id
+ ApeConsts.CONFERENCE_SESSION_ID = 11;
+ ApeConsts.CHAT_SESSION_ID = 12;
+ ApeConsts.GIFT_SESSION_ID = 13;
+ ApeConsts.AUDIO_SESSION_ID = 14;
+ ApeConsts.VIDEO_SESSION_ID = 15;
+ ApeConsts.WEBSHARING_SESSION_ID = 16;
+ ApeConsts.DOCSHARING_SESSION_ID = 17;
+ ApeConsts.WHITEBOARD_SESSION_ID = 18;
+ ApeConsts.MEDIA_SESSION_ID = 19;
+ ApeConsts.SCREENSHARING_SESSION_ID = 20;
+ ApeConsts.POLL_SESSION_ID = 21;
+
+ // defs for common channel id
+ ApeConsts.BROADCAST_CHANNEL_ID = 0;
+ ApeConsts.CONFERENCE_CHANNEL_ID = ApeConsts.CONFERENCE_SESSION_ID;
+ ApeConsts.CHAT_CHANNEL_ID = ApeConsts.CHAT_SESSION_ID;
+ ApeConsts.GIFT_CHANNEL_ID = ApeConsts.GIFT_SESSION_ID;
+ ApeConsts.WEBSHARING_CHANNEL_ID = ApeConsts.WEBSHARING_SESSION_ID;
+ ApeConsts.DOCSHARING_CHANNEL_ID = ApeConsts.DOCSHARING_SESSION_ID;
+ ApeConsts.WHITEBOARD_CHANNEL_ID = ApeConsts.WHITEBOARD_SESSION_ID;
+ ApeConsts.MEDIA_CHANNEL_ID = ApeConsts.MEDIA_SESSION_ID;
+ ApeConsts.SCREENSHARING_CHANNEL_ID = ApeConsts.SCREENSHARING_SESSION_ID;
+
+ // defs for common session name
+ ApeConsts.CONFERENCE_SESSION_NAME = "conference app";
+ ApeConsts.CHAT_SESSION_NAME = "chat app";
+ ApeConsts.GIFT_SESSION_NAME = "gift app";
+ ApeConsts.AUDIO_SESSION_NAME = "audio app";
+ ApeConsts.VIDEO_SESSION_NAME = "video app";
+ ApeConsts.WEBSHARING_SESSION_NAME = "web sharing app";
+ ApeConsts.DOCSHARING_SESSION_NAME = "doc sharing app";
+ ApeConsts.WHITEBOARD_SESSION_NAME = "whiteboard app";
+ ApeConsts.MEDIA_SESSION_NAME = "media sharing app";
+ ApeConsts.SCREENSHARING_SESSION_NAME = "screen sharing app";
+
+ // def for common session tag
+ ApeConsts.CONFERENCE_SESSION_TAG = "con-tag";
+ ApeConsts.CHAT_SESSION_TAG = "cha-tag";
+ ApeConsts.GIFT_SESSION_TAG = "gif-tag";
+ ApeConsts.AUDIO_SESSION_TAG = "aud-tag";
+ ApeConsts.VIDEO_SESSION_TAG = "vid-tag";
+ ApeConsts.WEBSHARING_SESSION_TAG = "web-tag";
+ ApeConsts.DOCSHARING_SESSION_TAG = "doc-tag";
+ ApeConsts.WHITEBOARD_SESSION_TAG = "wbd-tag";
+ ApeConsts.MEDIA_SESSION_TAG = "med-tag";
+ ApeConsts.SCREENSHARING_SESSION_TAG = "scr-tag";
+
+ ApeConsts.CONFERENCE_OBJ_ROSTER_ID = (ApeConsts.CONFERENCE_SESSION_ID << 16) + 1;
+ ApeConsts.CONFERENCE_OBJ_ROSTER_NAME = "node list";
+ ApeConsts.CONFERENCE_OBJ_ROSTER_TAG = "node list tag";
+
+ ApeConsts.CONFERENCE_OBJ_QUEUE_ID = (ApeConsts.CONFERENCE_SESSION_ID << 16) + 2;
+ ApeConsts.CONFERENCE_OBJ_QUEUE_NAME = "mic list";
+ ApeConsts.CONFERENCE_OBJ_QUEUE_TAG = "mic list tag";
+
+ // conference tab pages
+ ApeConsts.CONFERENCE_OBJ_TABLE_ID = (ApeConsts.CONFERENCE_SESSION_ID << 16) + 3;
+ ApeConsts.CONFERENCE_OBJ_TABLE_NAME = "tabbar list";
+ ApeConsts.CONFERENCE_OBJ_TABLE_TAG = "tabbar list tag";
+
+ // owned id list is unique in conference
+ ApeConsts.CONFERENCE_OBJ_COUNTER_ID = (ApeConsts.CONFERENCE_SESSION_ID << 16) + 4;
+ ApeConsts.CONFERENCE_OBJ_COUNTER_NAME = "id list";
+ ApeConsts.CONFERENCE_OBJ_COUNTER_TAG = "id list tag";
+
+ // web sharing objects
+ ApeConsts.WEBSHARING_OBJ_TABLE_ID = (ApeConsts.WEBSHARING_SESSION_ID << 16) + 1;
+ ApeConsts.WEBSHARING_OBJ_TABLE_NAME = "web list";
+ ApeConsts.WEBSHARING_OBJ_TABLE_TAG = "web list tag";
+
+ // doc sharing objects
+ ApeConsts.DOCSHARING_OBJ_TABLE_ID = (ApeConsts.DOCSHARING_SESSION_ID << 16) + 1;
+ ApeConsts.DOCSHARING_OBJ_TABLE_NAME = "doc list";
+ ApeConsts.DOCSHARING_OBJ_TABLE_TAG = "doc list tag";
+
+ // doc sharing objects h5
+ ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5 = (ApeConsts.DOCSHARING_SESSION_ID << 16) + 2;
+ ApeConsts.DOCSHARING_OBJ_TABLE_NAME_H5 = "doc list h5";
+ ApeConsts.DOCSHARING_OBJ_TABLE_TAG_H5 = "doc list tag h5";
+
+ // whiteboard objects
+ ApeConsts.WHITEBOARD_OBJ_TABLE_ID = (ApeConsts.WHITEBOARD_SESSION_ID << 16) + 1;
+ ApeConsts.WHITEBOARD_OBJ_TABLE_NAME = "wbd list";
+ ApeConsts.WHITEBOARD_OBJ_TABLE_TAG = "wbd list tag";
+
+ // media sharing objects
+ ApeConsts.MEDIA_OBJ_TABLE_ID = (ApeConsts.MEDIA_SESSION_ID << 16) + 1;
+ ApeConsts.MEDIA_OBJ_TABLE_NAME = "med list";
+ ApeConsts.MEDIA_OBJ_TABLE_TAG = "med list tag";
+
+ // chat sharing objects
+ ApeConsts.CHAT_OBJ_TABLE_ID = (ApeConsts.CHAT_SESSION_ID << 16) + 1;
+ ApeConsts.CHAT_OBJ_TABLE_NAME = "chat list";
+ ApeConsts.CHAT_OBJ_TABLE_TAG = "chat list tag";
+
+ ApeConsts.AUDIO_OBJ_TABLE_ID = (ApeConsts.AUDIO_SESSION_ID << 16) + 1;
+ ApeConsts.AUDIO_OBJ_TABLE_NAME = "audio channel list";
+ ApeConsts.AUDIO_OBJ_TABLE_TAG = "audio channel list tag";
+
+ ApeConsts.VIDEO_OBJ_TABLE_ID = (ApeConsts.VIDEO_SESSION_ID << 16) + 1;
+ ApeConsts.VIDEO_OBJ_TABLE_NAME = "video channel list";
+ ApeConsts.VIDEO_OBJ_TABLE_TAG = "video channel list tag";
+
+ // screen sharing objects
+ ApeConsts.SCREENSHARING_OBJ_TABLE_ID = (ApeConsts.SCREENSHARING_SESSION_ID << 16) + 1;
+ ApeConsts.SCREEN_OBJ_TABLE_NAME = "scr list";
+ ApeConsts.SCREEN_OBJ_TABLE_TAG = "scr list tag";
+
+ // poll sharing objects
+ ApeConsts.POLL_OBJ_TABLE_ID = (ApeConsts.POLL_SESSION_ID << 16) + 1;
+ ApeConsts.VOTE_OBJ_TABLE_ID = (ApeConsts.POLL_SESSION_ID << 16) + 2;
+ ApeConsts.RECORD_OBJ_TABLE_ID = (ApeConsts.POLL_SESSION_ID << 16) + 3;
+ ApeConsts.SHAMLIVE_OBJ_TABLE_ID = (ApeConsts.POLL_SESSION_ID << 16) + 4;
+
+ ApeConsts.POLL_OBJ_TABLE_NAME = "poll list";
+ ApeConsts.POLL_OBJ_TABLE_TAG = "poll list tag";
+
+ // registry operation const
+ ApeConsts.REG_TABLE_INSERT_TAIL = 0xFFFFFF;
+ ApeConsts.REG_TABLE_DELETE_ALL = 0xFFFFFF;
+
+ ApeConsts.CJS_RELEASED = 0;
+ ApeConsts.CJS_JOINNING = 1;
+ ApeConsts.CJS_JOINNED = 2;
+
+ // 白板动作
+ ApeConsts.WBA_CLOSE = 1;
+ ApeConsts.WBA_CHANGE = 2;
+ ApeConsts.WBA_OPEN = 3;
+ ApeConsts.WBA_DOC_ANNOTATION = 4;
+ ApeConsts.WBA_LASER_PEN = 5;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(ApeConsts, "ApeConsts", "D:/work/McuClient/src/apes/ApeConsts.js");
+ }();
+
+ ;
+
+/***/ },
+/* 9 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
+ * Created by hoopoe8 on 2017/1/8.
+ */
+
+
+ var _base64Js = __webpack_require__(10);
+
+ var _base64Js2 = _interopRequireDefault(_base64Js);
+
+ var _utf = __webpack_require__(11);
+
+ var _utf2 = _interopRequireDefault(_utf);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ var EngineUtils = function () {
+ function EngineUtils() {
+ _classCallCheck(this, EngineUtils);
+ }
+
+ _createClass(EngineUtils, null, [{
+ key: 'isEmptyObject',
+ value: function isEmptyObject(O) {
+ for (var x in O) {
+ return false;
+ }
+ return true;
+ }
+ }, {
+ key: 'arrayToJsonString',
+ value: function arrayToJsonString(_param) {
+ try {
+ return JSON.stringify(_param);
+ } catch (err) {
+ console.log("arrayToJsonString error:" + err.message);
+ }
+ return null;
+ }
+ }, {
+ key: 'arrayFromJsonString',
+ value: function arrayFromJsonString(_param) {
+ try {
+ return JSON.parse(_param);
+ } catch (err) {
+ console.log("arrayFromJsonString error:" + err.message);
+ }
+ return null;
+ }
+
+ //生成时间戳后9位 保证唯一
+
+ }, {
+ key: 'creatSoleNumberFromTimestamp',
+ value: function creatSoleNumberFromTimestamp() {
+ var time = new Date().getTime();
+ var timestamp = time % 1000000000; //time后9位
+ return timestamp;
+ }
+
+ //生成时间戳毫秒
+
+ }, {
+ key: 'creatTimestamp',
+ value: function creatTimestamp() {
+ var time = parseInt(new Date().getTime() / 1000); //精确到毫秒
+ return time;
+ }
+ //生成时间戳 string
+
+ }, {
+ key: 'creatTimestampStr',
+ value: function creatTimestampStr() {
+ var curTime = new Date();
+ var timeStr = "" + curTime.getFullYear() + "-";
+ timeStr += curTime.getMonth() + 1 + "-";
+ timeStr += curTime.getDate() + "-";
+ timeStr += curTime.getHours() + "-";
+ timeStr += curTime.getMinutes() + "-";
+ timeStr += curTime.getSeconds();
+ return timeStr;
+ }
+
+ //生成时间戳 格式:"20170209"
+
+ }, {
+ key: 'creatTimestampYMD',
+ value: function creatTimestampYMD() {
+ var curTime = new Date();
+ var year = "" + curTime.getFullYear();
+ var month = "" + (curTime.getMonth() + 1);
+ var day = "" + curTime.getDate();
+
+ if (month.length < 2) {
+ month = "0" + month;
+ }
+ if (day.length < 2) {
+ day = "0" + day;
+ }
+ return year + month + day;
+ }
+ }, {
+ key: 'objectToBase64',
+ value: function objectToBase64(_object) {
+ try {
+ var _objectStr = JSON.stringify(_object);
+ //console.log("objectToBase64------1----------")
+ var byte = _utf2.default.setBytesFromString(_objectStr);
+ //console.log("objectToBase64------2----------")
+ var _objectBase64 = _base64Js2.default.fromByteArray(byte);
+ return _objectBase64;
+ } catch (err) {
+ console.log("objectToBase64 err:" + err.message);
+ return "";
+ }
+ return "";
+ }
+ }, {
+ key: 'objectFromBase64',
+ value: function objectFromBase64(_objectBase64) {
+ try {
+ var byte = _base64Js2.default.toByteArray(_objectBase64);
+ var _objectStr = _utf2.default.getStringFromBytes(byte);
+ var _object = JSON.parse(_objectStr);
+ return _object;
+ } catch (err) {
+ console.log("objectFromBase64 err:" + err.message);
+ return null;
+ }
+ return null;
+ }
+ }]);
+
+ return EngineUtils;
+ }();
+
+ var _default = EngineUtils;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(EngineUtils, 'EngineUtils', 'D:/work/McuClient/src/EngineUtils.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/EngineUtils.js');
+ }();
+
+ ;
+
+/***/ },
+/* 10 */
+/***/ function(module, exports) {
+
+ 'use strict'
+
+ exports.byteLength = byteLength
+ exports.toByteArray = toByteArray
+ exports.fromByteArray = fromByteArray
+
+ var lookup = []
+ var revLookup = []
+ var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array
+
+ var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
+ for (var i = 0, len = code.length; i < len; ++i) {
+ lookup[i] = code[i]
+ revLookup[code.charCodeAt(i)] = i
+ }
+
+ revLookup['-'.charCodeAt(0)] = 62
+ revLookup['_'.charCodeAt(0)] = 63
+
+ function placeHoldersCount (b64) {
+ var len = b64.length
+ if (len % 4 > 0) {
+ throw new Error('Invalid string. Length must be a multiple of 4')
+ }
+
+ // the number of equal signs (place holders)
+ // if there are two placeholders, than the two characters before it
+ // represent one byte
+ // if there is only one, then the three characters before it represent 2 bytes
+ // this is just a cheap hack to not do indexOf twice
+ return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0
+ }
+
+ function byteLength (b64) {
+ // base64 is 4/3 + up to two characters of the original data
+ return b64.length * 3 / 4 - placeHoldersCount(b64)
+ }
+
+ function toByteArray (b64) {
+ var i, j, l, tmp, placeHolders, arr
+ var len = b64.length
+ placeHolders = placeHoldersCount(b64)
+
+ arr = new Arr(len * 3 / 4 - placeHolders)
+
+ // if there are placeholders, only get up to the last complete 4 chars
+ l = placeHolders > 0 ? len - 4 : len
+
+ var L = 0
+
+ for (i = 0, j = 0; i < l; i += 4, j += 3) {
+ tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]
+ arr[L++] = (tmp >> 16) & 0xFF
+ arr[L++] = (tmp >> 8) & 0xFF
+ arr[L++] = tmp & 0xFF
+ }
+
+ if (placeHolders === 2) {
+ tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4)
+ arr[L++] = tmp & 0xFF
+ } else if (placeHolders === 1) {
+ tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2)
+ arr[L++] = (tmp >> 8) & 0xFF
+ arr[L++] = tmp & 0xFF
+ }
+
+ return arr
+ }
+
+ function tripletToBase64 (num) {
+ return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]
+ }
+
+ function encodeChunk (uint8, start, end) {
+ var tmp
+ var output = []
+ for (var i = start; i < end; i += 3) {
+ tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
+ output.push(tripletToBase64(tmp))
+ }
+ return output.join('')
+ }
+
+ function fromByteArray (uint8) {
+ var tmp
+ var len = uint8.length
+ var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes
+ var output = ''
+ var parts = []
+ var maxChunkLength = 16383 // must be multiple of 3
+
+ // go through the array every three bytes, we'll deal with trailing stuff later
+ for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
+ parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)))
+ }
+
+ // pad the end with zeros, but make sure to not forget the extra bytes
+ if (extraBytes === 1) {
+ tmp = uint8[len - 1]
+ output += lookup[tmp >> 2]
+ output += lookup[(tmp << 4) & 0x3F]
+ output += '=='
+ } else if (extraBytes === 2) {
+ tmp = (uint8[len - 2] << 8) + (uint8[len - 1])
+ output += lookup[tmp >> 10]
+ output += lookup[(tmp >> 4) & 0x3F]
+ output += lookup[(tmp << 2) & 0x3F]
+ output += '='
+ }
+
+ parts.push(output)
+
+ return parts.join('')
+ }
+
+
+/***/ },
+/* 11 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /* WEBPACK VAR INJECTION */(function(module) {// UTF8 : Manage UTF-8 strings in ArrayBuffers
+ if(module.require) {
+ __webpack_require__(13);
+ __webpack_require__(14);
+ }
+
+ var UTF8={
+ // non UTF8 encoding detection (cf README file for details)
+ 'isNotUTF8': function(bytes, byteOffset, byteLength) {
+ try {
+ UTF8.getStringFromBytes(bytes, byteOffset, byteLength, true);
+ } catch(e) {
+ return true;
+ }
+ return false;
+ },
+ // UTF8 decoding functions
+ 'getCharLength': function(theByte) {
+ // 4 bytes encoded char (mask 11110000)
+ if(0xF0 == (theByte&0xF0)) {
+ return 4;
+ // 3 bytes encoded char (mask 11100000)
+ } else if(0xE0 == (theByte&0xE0)) {
+ return 3;
+ // 2 bytes encoded char (mask 11000000)
+ } else if(0xC0 == (theByte&0xC0)) {
+ return 2;
+ // 1 bytes encoded char
+ } else if(theByte == (theByte&0x7F)) {
+ return 1;
+ }
+ return 0;
+ },
+ 'getCharCode': function(bytes, byteOffset, charLength) {
+ var charCode = 0, mask = '';
+ byteOffset = byteOffset || 0;
+ // Retrieve charLength if not given
+ charLength = charLength || UTF8.getCharLength(bytes[byteOffset]);
+ if(charLength == 0) {
+ throw new Error(bytes[byteOffset].toString(2)+' is not a significative' +
+ ' byte (offset:'+byteOffset+').');
+ }
+ // Return byte value if charlength is 1
+ if(1 === charLength) {
+ return bytes[byteOffset];
+ }
+ // Test UTF8 integrity
+ mask = '00000000'.slice(0, charLength) + 1 + '00000000'.slice(charLength + 1);
+ if(bytes[byteOffset]&(parseInt(mask, 2))) {
+ throw Error('Index ' + byteOffset + ': A ' + charLength + ' bytes' +
+ ' encoded char' +' cannot encode the '+(charLength+1)+'th rank bit to 1.');
+ }
+ // Reading the first byte
+ mask='0000'.slice(0,charLength+1)+'11111111'.slice(charLength+1);
+ charCode+=(bytes[byteOffset]&parseInt(mask,2))<<((--charLength)*6);
+ // Reading the next bytes
+ while(charLength) {
+ if(0x80!==(bytes[byteOffset+1]&0x80)
+ ||0x40===(bytes[byteOffset+1]&0x40)) {
+ throw Error('Index '+(byteOffset+1)+': Next bytes of encoded char'
+ +' must begin with a "10" bit sequence.');
+ }
+ charCode += ((bytes[++byteOffset]&0x3F) << ((--charLength) * 6));
+ }
+ return charCode;
+ },
+ 'getStringFromBytes': function(bytes, byteOffset, byteLength, strict) {
+ var charLength, chars = [];
+ byteOffset = byteOffset|0;
+ byteLength=('number' === typeof byteLength ?
+ byteLength :
+ bytes.byteLength || bytes.length
+ );
+ for(; byteOffset < byteLength; byteOffset++) {
+ charLength = UTF8.getCharLength(bytes[byteOffset]);
+ if(byteOffset + charLength > byteLength) {
+ if(strict) {
+ throw Error('Index ' + byteOffset + ': Found a ' + charLength +
+ ' bytes encoded char declaration but only ' +
+ (byteLength - byteOffset) +' bytes are available.');
+ }
+ } else {
+ chars.push(String.fromCodePoint(
+ UTF8.getCharCode(bytes, byteOffset, charLength, strict)
+ ));
+ }
+ byteOffset += charLength - 1;
+ }
+ return chars.join('');
+ },
+ // UTF8 encoding functions
+ 'getBytesForCharCode': function(charCode) {
+ if(charCode < 128) {
+ return 1;
+ } else if(charCode < 2048) {
+ return 2;
+ } else if(charCode < 65536) {
+ return 3;
+ } else if(charCode < 2097152) {
+ return 4;
+ }
+ throw new Error('CharCode '+charCode+' cannot be encoded with UTF8.');
+ },
+ 'setBytesFromCharCode': function(charCode, bytes, byteOffset, neededBytes) {
+ charCode = charCode|0;
+ bytes = bytes || [];
+ byteOffset = byteOffset|0;
+ neededBytes = neededBytes || UTF8.getBytesForCharCode(charCode);
+ // Setting the charCode as it to bytes if the byte length is 1
+ if(1 == neededBytes) {
+ bytes[byteOffset] = charCode;
+ } else {
+ // Computing the first byte
+ bytes[byteOffset++] =
+ (parseInt('1111'.slice(0, neededBytes), 2) << 8 - neededBytes) +
+ (charCode >>> ((--neededBytes) * 6));
+ // Computing next bytes
+ for(;neededBytes>0;) {
+ bytes[byteOffset++] = ((charCode>>>((--neededBytes) * 6))&0x3F)|0x80;
+ }
+ }
+ return bytes;
+ },
+ 'setBytesFromString': function(string, bytes, byteOffset, byteLength, strict) {
+ string = string || '';
+ bytes = bytes || [];
+ byteOffset = byteOffset|0;
+ byteLength = ('number' === typeof byteLength ?
+ byteLength :
+ bytes.byteLength||Infinity
+ );
+ for(var i = 0, j = string.length; i < j; i++) {
+ var neededBytes = UTF8.getBytesForCharCode(string[i].codePointAt(0));
+ if(strict && byteOffset + neededBytes > byteLength) {
+ throw new Error('Not enought bytes to encode the char "' + string[i] +
+ '" at the offset "' + byteOffset + '".');
+ }
+ UTF8.setBytesFromCharCode(string[i].codePointAt(0),
+ bytes, byteOffset, neededBytes, strict);
+ byteOffset += neededBytes;
+ }
+ return bytes;
+ }
+ };
+
+ if(true) {
+ module.exports = UTF8;
+ }
+
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module)))
+
+/***/ },
+/* 12 */
+/***/ function(module, exports) {
+
+ module.exports = function(module) {
+ if(!module.webpackPolyfill) {
+ module.deprecate = function() {};
+ module.paths = [];
+ // module.parent = undefined by default
+ module.children = [];
+ module.webpackPolyfill = 1;
+ }
+ return module;
+ }
+
+
+/***/ },
+/* 13 */
+/***/ function(module, exports) {
+
+ /*! http://mths.be/fromcodepoint v0.2.1 by @mathias */
+ if (!String.fromCodePoint) {
+ (function() {
+ var defineProperty = (function() {
+ // IE 8 only supports `Object.defineProperty` on DOM elements
+ try {
+ var object = {};
+ var $defineProperty = Object.defineProperty;
+ var result = $defineProperty(object, object, object) && $defineProperty;
+ } catch(error) {}
+ return result;
+ }());
+ var stringFromCharCode = String.fromCharCode;
+ var floor = Math.floor;
+ var fromCodePoint = function(_) {
+ var MAX_SIZE = 0x4000;
+ var codeUnits = [];
+ var highSurrogate;
+ var lowSurrogate;
+ var index = -1;
+ var length = arguments.length;
+ if (!length) {
+ return '';
+ }
+ var result = '';
+ while (++index < length) {
+ var codePoint = Number(arguments[index]);
+ if (
+ !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
+ codePoint < 0 || // not a valid Unicode code point
+ codePoint > 0x10FFFF || // not a valid Unicode code point
+ floor(codePoint) != codePoint // not an integer
+ ) {
+ throw RangeError('Invalid code point: ' + codePoint);
+ }
+ if (codePoint <= 0xFFFF) { // BMP code point
+ codeUnits.push(codePoint);
+ } else { // Astral code point; split in surrogate halves
+ // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+ codePoint -= 0x10000;
+ highSurrogate = (codePoint >> 10) + 0xD800;
+ lowSurrogate = (codePoint % 0x400) + 0xDC00;
+ codeUnits.push(highSurrogate, lowSurrogate);
+ }
+ if (index + 1 == length || codeUnits.length > MAX_SIZE) {
+ result += stringFromCharCode.apply(null, codeUnits);
+ codeUnits.length = 0;
+ }
+ }
+ return result;
+ };
+ if (defineProperty) {
+ defineProperty(String, 'fromCodePoint', {
+ 'value': fromCodePoint,
+ 'configurable': true,
+ 'writable': true
+ });
+ } else {
+ String.fromCodePoint = fromCodePoint;
+ }
+ }());
+ }
+
+
+/***/ },
+/* 14 */
+/***/ function(module, exports) {
+
+ /*! http://mths.be/codepointat v0.2.0 by @mathias */
+ if (!String.prototype.codePointAt) {
+ (function() {
+ 'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
+ var defineProperty = (function() {
+ // IE 8 only supports `Object.defineProperty` on DOM elements
+ try {
+ var object = {};
+ var $defineProperty = Object.defineProperty;
+ var result = $defineProperty(object, object, object) && $defineProperty;
+ } catch(error) {}
+ return result;
+ }());
+ var codePointAt = function(position) {
+ if (this == null) {
+ throw TypeError();
+ }
+ var string = String(this);
+ var size = string.length;
+ // `ToInteger`
+ var index = position ? Number(position) : 0;
+ if (index != index) { // better `isNaN`
+ index = 0;
+ }
+ // Account for out-of-bounds indices:
+ if (index < 0 || index >= size) {
+ return undefined;
+ }
+ // Get the first code unit
+ var first = string.charCodeAt(index);
+ var second;
+ if ( // check if it’s the start of a surrogate pair
+ first >= 0xD800 && first <= 0xDBFF && // high surrogate
+ size > index + 1 // there is a next code unit
+ ) {
+ second = string.charCodeAt(index + 1);
+ if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
+ // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
+ return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+ }
+ }
+ return first;
+ };
+ if (defineProperty) {
+ defineProperty(String.prototype, 'codePointAt', {
+ 'value': codePointAt,
+ 'configurable': true,
+ 'writable': true
+ });
+ } else {
+ String.prototype.codePointAt = codePointAt;
+ }
+ }());
+ }
+
+
+/***/ },
+/* 15 */
+/***/ function(module, exports, __webpack_require__) {
+
+ (function(){
+ var crypt = __webpack_require__(16),
+ utf8 = __webpack_require__(17).utf8,
+ isBuffer = __webpack_require__(18),
+ bin = __webpack_require__(17).bin,
+
+ // The core
+ md5 = function (message, options) {
+ // Convert to byte array
+ if (message.constructor == String)
+ if (options && options.encoding === 'binary')
+ message = bin.stringToBytes(message);
+ else
+ message = utf8.stringToBytes(message);
+ else if (isBuffer(message))
+ message = Array.prototype.slice.call(message, 0);
+ else if (!Array.isArray(message))
+ message = message.toString();
+ // else, assume byte array already
+
+ var m = crypt.bytesToWords(message),
+ l = message.length * 8,
+ a = 1732584193,
+ b = -271733879,
+ c = -1732584194,
+ d = 271733878;
+
+ // Swap endian
+ for (var i = 0; i < m.length; i++) {
+ m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
+ ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
+ }
+
+ // Padding
+ m[l >>> 5] |= 0x80 << (l % 32);
+ m[(((l + 64) >>> 9) << 4) + 14] = l;
+
+ // Method shortcuts
+ var FF = md5._ff,
+ GG = md5._gg,
+ HH = md5._hh,
+ II = md5._ii;
+
+ for (var i = 0; i < m.length; i += 16) {
+
+ var aa = a,
+ bb = b,
+ cc = c,
+ dd = d;
+
+ a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
+ d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
+ c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
+ b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
+ a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
+ d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
+ c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
+ b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
+ a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
+ d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
+ c = FF(c, d, a, b, m[i+10], 17, -42063);
+ b = FF(b, c, d, a, m[i+11], 22, -1990404162);
+ a = FF(a, b, c, d, m[i+12], 7, 1804603682);
+ d = FF(d, a, b, c, m[i+13], 12, -40341101);
+ c = FF(c, d, a, b, m[i+14], 17, -1502002290);
+ b = FF(b, c, d, a, m[i+15], 22, 1236535329);
+
+ a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
+ d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
+ c = GG(c, d, a, b, m[i+11], 14, 643717713);
+ b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
+ a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
+ d = GG(d, a, b, c, m[i+10], 9, 38016083);
+ c = GG(c, d, a, b, m[i+15], 14, -660478335);
+ b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
+ a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
+ d = GG(d, a, b, c, m[i+14], 9, -1019803690);
+ c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
+ b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
+ a = GG(a, b, c, d, m[i+13], 5, -1444681467);
+ d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
+ c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
+ b = GG(b, c, d, a, m[i+12], 20, -1926607734);
+
+ a = HH(a, b, c, d, m[i+ 5], 4, -378558);
+ d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
+ c = HH(c, d, a, b, m[i+11], 16, 1839030562);
+ b = HH(b, c, d, a, m[i+14], 23, -35309556);
+ a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
+ d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
+ c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
+ b = HH(b, c, d, a, m[i+10], 23, -1094730640);
+ a = HH(a, b, c, d, m[i+13], 4, 681279174);
+ d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
+ c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
+ b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
+ a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
+ d = HH(d, a, b, c, m[i+12], 11, -421815835);
+ c = HH(c, d, a, b, m[i+15], 16, 530742520);
+ b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
+
+ a = II(a, b, c, d, m[i+ 0], 6, -198630844);
+ d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
+ c = II(c, d, a, b, m[i+14], 15, -1416354905);
+ b = II(b, c, d, a, m[i+ 5], 21, -57434055);
+ a = II(a, b, c, d, m[i+12], 6, 1700485571);
+ d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
+ c = II(c, d, a, b, m[i+10], 15, -1051523);
+ b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
+ a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
+ d = II(d, a, b, c, m[i+15], 10, -30611744);
+ c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
+ b = II(b, c, d, a, m[i+13], 21, 1309151649);
+ a = II(a, b, c, d, m[i+ 4], 6, -145523070);
+ d = II(d, a, b, c, m[i+11], 10, -1120210379);
+ c = II(c, d, a, b, m[i+ 2], 15, 718787259);
+ b = II(b, c, d, a, m[i+ 9], 21, -343485551);
+
+ a = (a + aa) >>> 0;
+ b = (b + bb) >>> 0;
+ c = (c + cc) >>> 0;
+ d = (d + dd) >>> 0;
+ }
+
+ return crypt.endian([a, b, c, d]);
+ };
+
+ // Auxiliary functions
+ md5._ff = function (a, b, c, d, x, s, t) {
+ var n = a + (b & c | ~b & d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._gg = function (a, b, c, d, x, s, t) {
+ var n = a + (b & d | c & ~d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._hh = function (a, b, c, d, x, s, t) {
+ var n = a + (b ^ c ^ d) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+ md5._ii = function (a, b, c, d, x, s, t) {
+ var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
+ return ((n << s) | (n >>> (32 - s))) + b;
+ };
+
+ // Package private blocksize
+ md5._blocksize = 16;
+ md5._digestsize = 16;
+
+ module.exports = function (message, options) {
+ if (message === undefined || message === null)
+ throw new Error('Illegal argument ' + message);
+
+ var digestbytes = crypt.wordsToBytes(md5(message, options));
+ return options && options.asBytes ? digestbytes :
+ options && options.asString ? bin.bytesToString(digestbytes) :
+ crypt.bytesToHex(digestbytes);
+ };
+
+ })();
+
+
+/***/ },
+/* 16 */
+/***/ function(module, exports) {
+
+ (function() {
+ var base64map
+ = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+
+ crypt = {
+ // Bit-wise rotation left
+ rotl: function(n, b) {
+ return (n << b) | (n >>> (32 - b));
+ },
+
+ // Bit-wise rotation right
+ rotr: function(n, b) {
+ return (n << (32 - b)) | (n >>> b);
+ },
+
+ // Swap big-endian to little-endian and vice versa
+ endian: function(n) {
+ // If number given, swap endian
+ if (n.constructor == Number) {
+ return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
+ }
+
+ // Else, assume array and swap all items
+ for (var i = 0; i < n.length; i++)
+ n[i] = crypt.endian(n[i]);
+ return n;
+ },
+
+ // Generate an array of any length of random bytes
+ randomBytes: function(n) {
+ for (var bytes = []; n > 0; n--)
+ bytes.push(Math.floor(Math.random() * 256));
+ return bytes;
+ },
+
+ // Convert a byte array to big-endian 32-bit words
+ bytesToWords: function(bytes) {
+ for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
+ words[b >>> 5] |= bytes[i] << (24 - b % 32);
+ return words;
+ },
+
+ // Convert big-endian 32-bit words to a byte array
+ wordsToBytes: function(words) {
+ for (var bytes = [], b = 0; b < words.length * 32; b += 8)
+ bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+ return bytes;
+ },
+
+ // Convert a byte array to a hex string
+ bytesToHex: function(bytes) {
+ for (var hex = [], i = 0; i < bytes.length; i++) {
+ hex.push((bytes[i] >>> 4).toString(16));
+ hex.push((bytes[i] & 0xF).toString(16));
+ }
+ return hex.join('');
+ },
+
+ // Convert a hex string to a byte array
+ hexToBytes: function(hex) {
+ for (var bytes = [], c = 0; c < hex.length; c += 2)
+ bytes.push(parseInt(hex.substr(c, 2), 16));
+ return bytes;
+ },
+
+ // Convert a byte array to a base-64 string
+ bytesToBase64: function(bytes) {
+ for (var base64 = [], i = 0; i < bytes.length; i += 3) {
+ var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
+ for (var j = 0; j < 4; j++)
+ if (i * 8 + j * 6 <= bytes.length * 8)
+ base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
+ else
+ base64.push('=');
+ }
+ return base64.join('');
+ },
+
+ // Convert a base-64 string to a byte array
+ base64ToBytes: function(base64) {
+ // Remove non-base-64 characters
+ base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
+
+ for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
+ imod4 = ++i % 4) {
+ if (imod4 == 0) continue;
+ bytes.push(((base64map.indexOf(base64.charAt(i - 1))
+ & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
+ | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
+ }
+ return bytes;
+ }
+ };
+
+ module.exports = crypt;
+ })();
+
+
+/***/ },
+/* 17 */
+/***/ function(module, exports) {
+
+ var charenc = {
+ // UTF-8 encoding
+ utf8: {
+ // Convert a string to a byte array
+ stringToBytes: function(str) {
+ return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
+ },
+
+ // Convert a byte array to a string
+ bytesToString: function(bytes) {
+ return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
+ }
+ },
+
+ // Binary encoding
+ bin: {
+ // Convert a string to a byte array
+ stringToBytes: function(str) {
+ for (var bytes = [], i = 0; i < str.length; i++)
+ bytes.push(str.charCodeAt(i) & 0xFF);
+ return bytes;
+ },
+
+ // Convert a byte array to a string
+ bytesToString: function(bytes) {
+ for (var str = [], i = 0; i < bytes.length; i++)
+ str.push(String.fromCharCode(bytes[i]));
+ return str.join('');
+ }
+ }
+ };
+
+ module.exports = charenc;
+
+
+/***/ },
+/* 18 */
+/***/ function(module, exports) {
+
+ /*!
+ * Determine if an object is a Buffer
+ *
+ * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ * @license MIT
+ */
+
+ // The _isBuffer check is for Safari 5-7 support, because it's missing
+ // Object.prototype.constructor. Remove this eventually
+ module.exports = function (obj) {
+ return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
+ }
+
+ function isBuffer (obj) {
+ return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
+ }
+
+ // For Node v0.10 support. Remove this eventually.
+ function isSlowBuffer (obj) {
+ return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
+ }
+
+
+/***/ },
+/* 19 */
+/***/ function(module, exports, __webpack_require__) {
+
+ !function(e,t){ true?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new o(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();t.default=i;var o=function(){function e(t,i,r){n(this,e),this.ip="",this.ipcallback=i,this.timeoutId=null,this.reqsCache=[];for(var o=0;o<t.length;o++)this.reqsCache.push(this.send(t[o],r-10));this.timeoutId=setTimeout(this.notify.bind(this),r)}return r(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,i=new XMLHttpRequest;return i.open("HEAD","//"+e+"/?_="+Date.now()),i.timeout=t,i.onload=function(){n.ip=e,n.clearReq(i),i.onload=null,n.notify()},i.ontimeout=function(){n.clearReq(i),i.ontimeout=null},i.onerror=function(){n.clearReq(i),i.onerror=null},i.onabort=function(){n.clearReq(i),i.onabort=null},i.send(),i}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(o,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(i,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()}])});
+
+/***/ },
+/* 20 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
+ if (true) {
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [exports, module], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
+ factory(exports, module);
+ } else {
+ var mod = {
+ exports: {}
+ };
+ factory(mod.exports, mod);
+ global.fetchJsonp = mod.exports;
+ }
+ })(this, function (exports, module) {
+ 'use strict';
+
+ var defaultOptions = {
+ timeout: 5000,
+ jsonpCallback: 'callback',
+ jsonpCallbackFunction: null
+ };
+
+ function generateCallbackFunction() {
+ return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
+ }
+
+ // Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined'
+ // error if request timeout
+ function clearFunction(functionName) {
+ // IE8 throws an exception when you try to delete a property on window
+ // http://stackoverflow.com/a/1824228/751089
+ try {
+ delete window[functionName];
+ } catch (e) {
+ window[functionName] = undefined;
+ }
+ }
+
+ function removeScript(scriptId) {
+ var script = document.getElementById(scriptId);
+ document.getElementsByTagName('head')[0].removeChild(script);
+ }
+
+ function fetchJsonp(_url) {
+ var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+
+ // to avoid param reassign
+ var url = _url;
+ var timeout = options.timeout || defaultOptions.timeout;
+ var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
+
+ var timeoutId = undefined;
+
+ return new Promise(function (resolve, reject) {
+ var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
+ var scriptId = jsonpCallback + '_' + callbackFunction;
+
+ window[callbackFunction] = function (response) {
+ resolve({
+ ok: true,
+ // keep consistent with fetch API
+ json: function json() {
+ return Promise.resolve(response);
+ }
+ });
+
+ if (timeoutId) clearTimeout(timeoutId);
+
+ removeScript(scriptId);
+
+ clearFunction(callbackFunction);
+ };
+
+ // Check if the user set their own params, and if not add a ? to start a list of params
+ url += url.indexOf('?') === -1 ? '?' : '&';
+
+ var jsonpScript = document.createElement('script');
+ jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
+ jsonpScript.id = scriptId;
+ document.getElementsByTagName('head')[0].appendChild(jsonpScript);
+
+ timeoutId = setTimeout(function () {
+ reject(new Error('JSONP request to ' + _url + ' timed out'));
+
+ clearFunction(callbackFunction);
+ removeScript(scriptId);
+ }, timeout);
+ });
+ }
+
+ // export as global function
+ /*
+ let local;
+ if (typeof global !== 'undefined') {
+ local = global;
+ } else if (typeof self !== 'undefined') {
+ local = self;
+ } else {
+ try {
+ local = Function('return this')();
+ } catch (e) {
+ throw new Error('polyfill failed because global object is unavailable in this environment');
+ }
+ }
+ local.fetchJsonp = fetchJsonp;
+ */
+
+ module.exports = fetchJsonp;
+ });
+
+/***/ },
+/* 21 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Emiter2 = __webpack_require__(3);
+
+ var _Emiter3 = _interopRequireDefault(_Emiter2);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _md = __webpack_require__(15);
+
+ var _md2 = _interopRequireDefault(_md);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _iphunter = __webpack_require__(19);
+
+ var _iphunter2 = _interopRequireDefault(_iphunter);
+
+ var _Server = __webpack_require__(22);
+
+ var _Server2 = _interopRequireDefault(_Server);
+
+ var _fetchJsonp = __webpack_require__(20);
+
+ var _fetchJsonp2 = _interopRequireDefault(_fetchJsonp);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+ // 日志对象
+ var loger = _Loger2.default.getLoger('ServerCheck');
+
+ //ip选点流程的状态
+ var isRequestMcuCallback = false; //是否获取最佳mcu返回
+ var isRequestMsCallback = false; //是否获取ms最佳返回
+ var isTestFromSass = false;
+ var isTestFromServer = false;
+
+ var tempMcuIp = "";
+ var tempMcuPort = "";
+ var tempMsIp = "";
+ var tempMsPort = "";
+
+ var ServerCheck = function (_Emiter) {
+ _inherits(ServerCheck, _Emiter);
+
+ function ServerCheck() {
+ _classCallCheck(this, ServerCheck);
+
+ return _possibleConstructorReturn(this, (ServerCheck.__proto__ || Object.getPrototypeOf(ServerCheck)).call(this));
+ }
+
+ //根据userIp获取ip相关的信息,参数是userIp
+
+
+ _createClass(ServerCheck, [{
+ key: 'getUserIpInfo',
+ value: function getUserIpInfo(token, userIp) {
+ //重置ip选点流程状态
+ isRequestMcuCallback = false;
+ isRequestMsCallback = false;
+ isTestFromSass = false;
+ isTestFromServer = false;
+
+ var userIpInfo = new Object();
+ userIpInfo.ret = -1;
+
+ var ip = userIp;
+ var md5Str = (0, _md2.default)("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"); //("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"),转成MD5
+ var timestamp = new Date().getTime();
+ var location = 'http://ipapi.ipip.net/find?addr=' + ip + '&sid=14&uid=5237&sig=' + md5Str + '&_=' + timestamp;
+ loger.log('获取IP信息 ', userIp, location);
+
+ (0, _fetchJsonp2.default)(location, {
+ timeout: 3000
+ }).then(function (response) {
+ return response.json();
+ }).then(function (json) {
+ loger.log('获取IP信息返回', json);
+ if (json) {
+ userIpInfo.ret = json.ret;
+ userIpInfo.country = json.data[0]; //国家
+ userIpInfo.province = json.data[1]; //省份
+ userIpInfo.city = json.data[2]; //城市
+ userIpInfo.isp = json.data[4]; //运营商
+ }
+ this.serverGetUserIpInfoCallback(userIpInfo);
+ }.bind(this)).catch(function (ex) {
+ loger.log('获取IP信息失败', ex.message);
+ this.serverGetUserIpInfoCallback(userIpInfo);
+ }.bind(this));
+ }
+
+ //获取ip信息返回
+
+ }, {
+ key: 'serverGetUserIpInfoCallback',
+ value: function serverGetUserIpInfoCallback(userIpInfo) {
+ loger.log("获取IP详情,开始处理", userIpInfo);
+ if (userIpInfo.ret == "ok") {
+ _GlobalConfig2.default.country = userIpInfo.country; //国家
+ _GlobalConfig2.default.city = userIpInfo.city; //城市
+ _GlobalConfig2.default.province = userIpInfo.province; //服务商
+ _GlobalConfig2.default.isp = userIpInfo.isp; //服务商
+ loger.log("获取ip详情成功,country:" + _GlobalConfig2.default.country + ",city:" + _GlobalConfig2.default.city + ",isp:" + _GlobalConfig2.default.isp);
+ this._chooseBestIpFromServer();
+ } else {
+ loger.log("获取ip详情失败");
+ this._chooseBestIpFromSassParam();
+ }
+ }
+
+ //从IPIP服务列表中选择最快的IP
+
+ }, {
+ key: '_chooseBestIpFromServer',
+ value: function _chooseBestIpFromServer() {
+ loger.log("从IPIP服务列表中选择最快的IP");
+ isRequestMcuCallback = false;
+ isRequestMsCallback = false;
+ isTestFromServer = true;
+ isTestFromSass = false;
+
+ var mcuIpGroup = this._returnServerMS();
+ var msIpGroup = this._returnServerMCU();
+ this.getBestMcuServer(mcuIpGroup);
+ this.getBestMsServer(msIpGroup);
+ }
+ //从Sass返回的msList mcuList中选点
+
+ }, {
+ key: '_chooseBestIpFromSassParam',
+ value: function _chooseBestIpFromSassParam() {
+ loger.log("从Sass服务列表中选择最快的IP");
+ isRequestMcuCallback = false;
+ isRequestMsCallback = false;
+ isTestFromServer = true;
+ isTestFromSass = true;
+ //MCU
+ var mcuIpGroup = [];
+ var speedTestPort = ':8080'; //测速端口统一
+ for (var i = 0; i < _GlobalConfig2.default.mcuList.length; i++) {
+ var ipPort = _GlobalConfig2.default.mcuList[i].ip + speedTestPort;
+ mcuIpGroup.push(ipPort);
+ }
+ this.getBestMcuServer(mcuIpGroup);
+
+ //MS
+ var msIpGroup = [];
+ for (var _i = 0; _i < _GlobalConfig2.default.msList.length; _i++) {
+ var _ipPort = _GlobalConfig2.default.msList[_i].ip + speedTestPort;
+ msIpGroup.push(_ipPort);
+ }
+ this.getBestMsServer(msIpGroup);
+ }
+
+ //获取最快的MCU服务器地址,参数是一个ip数组
+
+ }, {
+ key: 'getBestMcuServer',
+ value: function getBestMcuServer(_param) {
+ loger.log('getBestMcuServer ', _param);
+ if (_param == null || _param.length < 1) {
+ this._getBestMcuServerCallbackHandler("");
+ return;
+ }
+ (0, _iphunter2.default)(_param, function (fatest_ip_response) {
+ if (!fatest_ip_response) {
+ loger.warn('getBestMcuServer -> nothing!');
+ this._getBestMcuServerCallbackHandler("");
+ } else {
+ loger.log('getBestMcuServer done -> ', fatest_ip_response);
+ this._getBestMcuServerCallbackHandler(fatest_ip_response);
+ }
+ }.bind(this), 3000);
+ }
+
+ //获取最快的MS服务器地址,参数是一个ip数组
+
+ }, {
+ key: 'getBestMsServer',
+ value: function getBestMsServer(_param) {
+ loger.log('getBestMsServer ', _param);
+ if (_param == null || _param.length < 1) {
+ this._getBestMsServerCallbackHandler("");
+ return;
+ }
+ (0, _iphunter2.default)(_param, function (fatest_ip_response) {
+ if (!fatest_ip_response) {
+ loger.warn('getBestMsServer -> nothing!');
+ this._getBestMsServerCallbackHandler("");
+ } else {
+ loger.log('getBestMsServer done -> ', fatest_ip_response);
+ this._getBestMsServerCallbackHandler(fatest_ip_response);
+ }
+ }.bind(this), 3000);
+ }
+ }, {
+ key: '_getBestMcuServerCallbackHandler',
+ value: function _getBestMcuServerCallbackHandler(_data) {
+ loger.log("_getBestMcuServerCallbackHandler", _data);
+ if (isRequestMcuCallback) {
+ loger.log("_getBestMcuServerCallbackHandler,已经有返回");
+ return;
+ }
+ isRequestMcuCallback = true;
+ if (_data) {
+ var server = _data.split(":");
+ if (server[0]) {
+ tempMcuIp = server[0];
+ }
+ if (server[1]) {
+ tempMcuPort = server[1];
+ }
+ }
+ //loger.log("_getBestMcuServerCallbackHandler",tempMcuIp,tempMcuPort);
+ this._startConnectMcu();
+ }
+ }, {
+ key: '_getBestMsServerCallbackHandler',
+ value: function _getBestMsServerCallbackHandler(_data) {
+ loger.log("_getBestMsServerCallbackHandler", _data);
+ if (isRequestMsCallback) {
+ loger.log("_getBestMsServerCallbackHandler,已经有返回");
+ return;
+ }
+ isRequestMsCallback = true;
+ if (_data) {
+ var server = _data.split(":");
+ if (server[0]) {
+ tempMsIp = server[0];
+ }
+ if (server[1]) {
+ tempMsPort = server[1];
+ }
+ }
+ //loger.log("_getBestMsServerCallbackHandler", tempMsIp,tempMsPort);
+ this._startConnectMcu();
+ }
+
+ //ip选点结束,开始连接MCU
+
+ }, {
+ key: '_startConnectMcu',
+ value: function _startConnectMcu() {
+ if (isRequestMcuCallback && isRequestMsCallback) {
+ if (isTestFromServer && !isTestFromSass) {
+ //从Server服务列表中选点结束,如果没有选到合适的,从Sass的列表中获取
+ if (!tempMcuIp || !tempMsIp) {
+ this._chooseBestIpFromSassParam();
+ } else {
+ this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
+ }
+ } else {
+ //从Sass返回的服务列表中选点结束
+ this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
+ }
+ } else {
+ loger.warn("_startConnectMcu 正在选点", isRequestMcuCallback, isRequestMsCallback);
+ }
+ }
+
+ //检测MCU连接地址
+
+ }, {
+ key: '_returnServerMCU',
+ value: function _returnServerMCU(country, province, ctiy, isp, jsona) {
+ var arr = [];
+ return arr;
+ }
+ //检测MS连接地址
+ //Config.ipInfo
+
+ }, {
+ key: '_returnServerMS',
+ value: function _returnServerMS(country, province, ctiy, isp, jsona) {
+ var arr = [];
+ /* let acquire = false;
+ if (isp != "") {
+ for (let obja in jsona.MS.isp) {
+ if (isp.indexOf(obja.idc) != -1) {
+ arr = obja.mslist;
+ acquire = true;
+ break;
+ }
+ }
+ }
+ if (country == "中国" && !acquire) {
+ for (let obja in jsona.MS.china) {
+ if (obja.province.indexOf(province) != -1 && province != "") {
+ arr = obja.mslist;
+ acquire = true;
+ break;
+ }
+ }
+ if (!acquire) {
+ arr = jsona.MS.china[jsona.MS.china.length - 1].mslist;
+ acquire = true;
+ }
+ }
+ if (country != "中国" && country != "") {
+ for (let obja:Object in jsona.MS.international) {
+ if (obja.country.indexOf(country) != -1) {
+ arr = obja.mslist;
+ acquire = true;
+ break;
+ }
+ }
+ if (!acquire) {
+ arr = jsona.MS.international[jsona.MS.international.length - 1].mslist;
+ acquire = true;
+ }
+ }
+ else if (!acquire) {
+ arr = jsona.MS.Default;
+ }
+ loger.info("ms匹配结束;" + arr.length);*/
+ return arr;
+ }
+ }]);
+
+ return ServerCheck;
+ }(_Emiter3.default);
+
+ ServerCheck.prototype.SEVER_CHECK_BEST_IP_SUCCESS = ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS = 'severCheck_checkBestIpSuccess_message'; //获取最快的MS地址
+
+ var _default = new ServerCheck();
+
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(isRequestMcuCallback, 'isRequestMcuCallback', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(isRequestMsCallback, 'isRequestMsCallback', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(isTestFromSass, 'isTestFromSass', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(isTestFromServer, 'isTestFromServer', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(tempMcuIp, 'tempMcuIp', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(tempMcuPort, 'tempMcuPort', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(tempMsIp, 'tempMsIp', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(tempMsPort, 'tempMsPort', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(ServerCheck, 'ServerCheck', 'D:/work/McuClient/src/ServerCheck.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/ServerCheck.js');
+ }();
+
+ ;
+
+/***/ },
+/* 22 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /*
+ * 全局数据管理
+ * */
+
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ var loger = _Loger2.default.getLoger('Server');
+
+ var Server = function () {
+ function Server() {
+ _classCallCheck(this, Server);
+ }
+
+ _createClass(Server, null, [{
+ key: 'serverList',
+ get: function get() {
+ return {
+ "共享地址": [{
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "221.228.109.123",
+ "name": "无锡"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }, {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ }, {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ }, {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ }, {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }],
+ "局域网": [{
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "221.228.109.123",
+ "name": "无锡"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }, {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ }, {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ }, {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ }, {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }],
+ "中国": {
+ "province": {
+ "香港": [{
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }],
+ "台湾": [{
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }]
+ },
+ "isp": {
+ "鹏博士": [{
+ "ip": "124.192.148.139",
+ "name": "鹏博士"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }],
+ "长城": [{
+ "ip": "124.192.148.139",
+ "name": "鹏博士"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }],
+ "移动": [{
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ }, {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }],
+ "电信": [{
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ }, {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }, {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }],
+ "联通": [{
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }, {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ }, {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }]
+ },
+ "default": [{
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ }, {
+ "ip": "221.228.109.123",
+ "name": "无锡"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }, {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ }, {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ }, {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ }, {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ }, {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ }, {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ }, {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }]
+ },
+ "美国": [{
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ }, {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ }, {
+ "ip": "185.114.76.243",
+ "name": "全球通阿什本"
+ }, {
+ "ip": "159.100.196.217",
+ "name": "全球通迈阿密"
+ }, {
+ "ip": "185.114.77.84",
+ "name": "全球通圣何塞"
+ }, {
+ "ip": "159.100.195.230",
+ "name": "全球通洛杉矶"
+ }, {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }],
+ "加拿大": [{
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ }, {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ }, {
+ "ip": "185.114.76.243",
+ "name": "全球通阿什本"
+ }, {
+ "ip": "159.100.196.217",
+ "name": "全球通迈阿密"
+ }, {
+ "ip": "185.114.77.84",
+ "name": "全球通圣何塞"
+ }, {
+ "ip": "159.100.195.230",
+ "name": "全球通洛杉矶"
+ }, {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }],
+ "墨西哥": [{
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ }, {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ }, {
+ "ip": "185.114.76.243",
+ "name": "全球通阿什本"
+ }, {
+ "ip": "159.100.196.217",
+ "name": "全球通迈阿密"
+ }, {
+ "ip": "185.114.77.84",
+ "name": "全球通圣何塞"
+ }, {
+ "ip": "159.100.195.230",
+ "name": "全球通洛杉矶"
+ }, {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }],
+ "菲律宾": [{
+ "ip": "223.255.248.122",
+ "name": "香港"
+ }, {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ }, {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ }, {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ }, {
+ "ip": "185.114.78.179",
+ "name": "全球通新加坡"
+ }, {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ }, {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ }, {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ }, {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }],
+ "越南": [{
+ "ip": "223.255.248.122",
+ "name": "香港"
+ }, {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ }, {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ }, {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ }, {
+ "ip": "185.114.78.179",
+ "name": "全球通新加坡"
+ }, {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ }, {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ }, {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ }, {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }],
+ "泰国": [{
+ "ip": "223.255.248.122",
+ "name": "香港"
+ }, {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ }, {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ }, {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ }, {
+ "ip": "185.114.78.179",
+ "name": "全球通新加坡"
+ }, {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ }, {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ }, {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ }, {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }],
+ "default": [{
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ }, {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }, {
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ }, {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ }, {
+ "ip": "38.123.107.18",
+ "name": "德国"
+ }, {
+ "ip": "223.255.248.122",
+ "name": "香港"
+ }, {
+ "ip": "148.153.8.22",
+ "port": "1935",
+ "name": "纽约"
+ }, {
+ "ip": "38.121.61.242",
+ "port": "1935",
+ "name": "洛杉矶"
+ }, {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ }, {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ }, {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }, {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ }, {
+ "ip": "45.126.246.148",
+ "name": "全球通德国"
+ }, {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ }, {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ }, {
+ "ip": "202.127.74.126",
+ "name": "全球通新加坡"
+ }, {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }, {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ }]
+ };
+ }
+ }]);
+
+ return Server;
+ }();
+
+ var _default = Server;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/config/Server.js');
+
+ __REACT_HOT_LOADER__.register(Server, 'Server', 'D:/work/McuClient/src/config/Server.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/config/Server.js');
+ }();
+
+ ;
+
+/***/ },
+/* 23 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Emiter2 = __webpack_require__(3);
+
+ var _Emiter3 = _interopRequireDefault(_Emiter2);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _everSocket = __webpack_require__(24);
+
+ var _everSocket2 = _interopRequireDefault(_everSocket);
+
+ var _index = __webpack_require__(25);
+
+ var _index2 = _interopRequireDefault(_index);
+
+ var _PduType = __webpack_require__(34);
+
+ var _PduType2 = _interopRequireDefault(_PduType);
+
+ var _PduConsts = __webpack_require__(35);
+
+ var _PduConsts2 = _interopRequireDefault(_PduConsts);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _ConferApe = __webpack_require__(36);
+
+ var _ConferApe2 = _interopRequireDefault(_ConferApe);
+
+ var _ArrayBufferUtil = __webpack_require__(38);
+
+ var _ArrayBufferUtil2 = _interopRequireDefault(_ArrayBufferUtil);
+
+ var _base64Js = __webpack_require__(10);
+
+ var _base64Js2 = _interopRequireDefault(_base64Js);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*eslint-disable*/
+
+ var loger = _Loger2.default.getLoger('MCU');
+
+ var MCU = function (_Emiter) {
+ _inherits(MCU, _Emiter);
+
+ function MCU() {
+ _classCallCheck(this, MCU);
+
+ var _this = _possibleConstructorReturn(this, (MCU.__proto__ || Object.getPrototypeOf(MCU)).call(this));
+
+ _this._apes = {};
+ _this._everSocket = _everSocket2.default;
+ _this._everSocket.on(_everSocket2.default.OPEN, _this._everSocketOpenHandler.bind(_this));
+ _this._everSocket.on(_everSocket2.default.MESSAGE, _this._everSocketMsgReceivedHandler.bind(_this));
+ _this._everSocket.on(_everSocket2.default.CLOSED, _this._everSocketCloseHandler.bind(_this));
+ return _this;
+ }
+
+ // 注册Ape
+
+
+ _createClass(MCU, [{
+ key: 'registerApe',
+ value: function registerApe(ape) {
+ this._apes[ape._session_id] = ape;
+ }
+
+ // EverSocket建立通道完毕
+
+ }, {
+ key: '_everSocketOpenHandler',
+ value: function _everSocketOpenHandler() {
+ this._sendJoinClassRequest();
+ }
+ // EverSocket连接断开
+
+ }, {
+ key: '_everSocketCloseHandler',
+ value: function _everSocketCloseHandler() {
+ _GlobalConfig2.default.setCurrentStatus(_GlobalConfig2.default.statusCode_3);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_SOCKET_DISCONNECT);
+ }
+
+ //MCU-发送加入会议请求
+
+ }, {
+ key: '_sendJoinClassRequest',
+ value: function _sendJoinClassRequest() {
+ //const classInfo = this.classInfo;
+ loger.log('MCU-发送加入会议请求.');
+ console.log(this.classInfo);
+ var descriptorPdu = new _index2.default['RCConferenceDescriptorPdu']();
+ descriptorPdu.id = this.classInfo.classId;
+ descriptorPdu.name = this.classInfo.className || "";
+ descriptorPdu.mode = 0;
+ descriptorPdu.capacity = 1;
+
+ var joinRequestPdu = new _index2.default['RCConferenceJoinRequestPdu']();
+ joinRequestPdu.type = 2;
+ joinRequestPdu.initiator = this.classInfo.nodeId;
+ joinRequestPdu.nodeType = _PduConsts2.default.NT_TERMINAL; //normal
+ joinRequestPdu.classDescription = descriptorPdu; // classDescription
+
+ var pduMsg = _index2.default.create_join_class_request_pdu(joinRequestPdu.type, this.classInfo.nodeId, this.classInfo.classId, 0, _ApeConsts2.default.BROADCAST_CHANNEL_ID, true, _PduConsts2.default.DP_TOP, this.classInfo.topNodeID, _PduConsts2.default.SEG_ONCE);
+
+ pduMsg.set("site", this.classInfo.siteId); //课堂号对应的名称
+ pduMsg.set("userId", this.classInfo.userId);
+ pduMsg.set("userName", _base64Js2.default.fromByteArray(_ArrayBufferUtil2.default.strToUint8Array(this.classInfo.userName)));
+ pduMsg.set("userRole", this.classInfo.userRole);
+ pduMsg.set("deviceType", "" + _GlobalConfig2.default.deviceType);
+ pduMsg.set("data", joinRequestPdu.toArrayBuffer());
+
+ this._everSocket.send(pduMsg.toArrayBuffer());
+ }
+
+ // EverSocket底层消息处理
+
+ }, {
+ key: '_everSocketMsgReceivedHandler',
+ value: function _everSocketMsgReceivedHandler(data) {
+ var pduMsg = _index2.default.decode_pdu(data);
+ var pduType = pduMsg.get("type");
+ var pduData = pduMsg.get("data");
+ //loger.data('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
+ //loger.log('MCU-FirstLayer封装消息', 'type', pdu.id2type(pduMsg.type), pduMsg.type, 'sessionId', ApeConsts(pduMsg.sessionId), pduMsg.sessionId);
+ switch (pduType) {
+ case _PduType2.default.RCPDU_CONNECT_PROVIDER_RESPONSE:
+ //加入会议请求返回数据处理
+ var joinConfPdu = _index2.default['RCConferenceJoinResponsePdu'].decode(pduData);
+ var pduResultCode = joinConfPdu.result;
+ loger.warn('RCPDU_CONNECT_PROVIDER_RESPONSE ->pduResultCode:' + pduResultCode);
+ switch (pduResultCode) {
+ case _PduConsts2.default.RET_SUCCESS:
+ //加入成功
+ this._updateMCUConfInfoDescription(joinConfPdu.classDescription);
+ this._emit(_MessageTypes2.default.CLASS_JOIN_MCU_SUCCESS, this.classInfo);
+ break;
+ case _PduConsts2.default.RET_FULL_CAPACITY:
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_JOIN_FULL);
+ //this._emit(MessageTypes.CLASS_JOIN_FAILED,MessageTypes.ERR_CLASS_JOIN_FULL);
+ //this._emit(MessageTypes.CLASS_JOIN_FULL);
+ break;
+ default:
+ loger.arn('JoinConfPdu-未知类型-等待处理.', pduResultCode);
+ break;
+ }
+ break;
+ case _PduType2.default.RCPDU_SEND_DATA_REQUEST:
+ //先判断当前消息属于哪个APE 根据 sessionId来判断
+ var ape = this._apes[pduMsg.sessionId];
+ var sessionLabel = (0, _ApeConsts2.default)(pduMsg.sessionId);
+ if (ape) {
+ var subTypeLabel = _index2.default.id2type(pduMsg.subType);
+ //loger.log('MCU-SecondLayer封装消息', 'sessionId', sessionLabel, pduMsg.sessionId, 'subtype', subTypeLabel, pduMsg.subType);
+ //ape广播事件,只要ape中监听就能收到
+ ape._emit(pduMsg.subType, pduMsg.data);
+ } else {
+ loger.warn(sessionLabel + '尚未注册');
+ }
+ break;
+ default:
+ loger.warn('PDU-未知类型-等待处理.', pduType);
+ }
+ }
+ }, {
+ key: '_updateMCUConfInfoDescription',
+ value: function _updateMCUConfInfoDescription(_data) {
+ // let _mcuConfDesc=new pdu['RCConferenceDescriptorPdu'].decode(mcuConfDesc);
+ loger.log('_updateMCUConfInfoDescription.');
+ //let classDescription=new pdu['RCConferenceDescriptorPdu'].decode(_data);
+ console.log(_data);
+ //let info = this.mcuClassInfo.info;
+ //info._conference_name = ArrayBufferUtil.uint8ArrayToStr(mcuConfDesc.name, 0);
+ //info._capacity = mcuConfDesc.capacity;
+ //info._mode = mcuConfDesc.mode;
+ }
+
+ // MU服务是否连接
+
+ }, {
+ key: 'send',
+
+
+ // 会议发送消息 -- 消息同意序列号
+ value: function send(msg) {
+ if (this.connected) {
+ loger.log('MCU-发送会议数据....');
+ this._everSocket.send(msg.toArrayBuffer());
+ } else {
+ loger.log('MCU-发送会议数据失败,MCU底层通道不可用');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_SOCKET_DISCONNECT);
+ }
+ }
+
+ // 主动断开MCU连接
+
+ }, {
+ key: 'leaveMCU',
+ value: function leaveMCU() {
+ // for (let ape in this._apes) {
+ // this._apes[ape].stop();
+ // }
+ loger.log('leaveMCU');
+ _GlobalConfig2.default.setCurrentStatus(_GlobalConfig2.default.statusCode_3);
+ this._everSocket.end();
+ }
+
+ // 主动建立MCU连接
+
+ }, {
+ key: 'joinMCU',
+ value: function joinMCU(_classInfo) {
+ loger.log('开始建立EverSocket通道.');
+ console.log(_classInfo);
+ _classInfo.classId = parseInt(_classInfo.classId); // classId 必须整形
+ this.classInfo = _classInfo;
+ // 创建刷新nodeId
+ this.classInfo.nodeId = _EngineUtils2.default.creatSoleNumberFromTimestamp();
+ _GlobalConfig2.default.nodeId = this.classInfo.nodeId; //这是标识自己身份的id
+
+ var nodeInfoRecordPdu = new _index2.default['RCNodeInfoRecordPdu']();
+ nodeInfoRecordPdu.name = this.classInfo.userName;
+ nodeInfoRecordPdu.nodeId = this.classInfo.nodeId;
+ nodeInfoRecordPdu.userId = this.classInfo.userId;
+ nodeInfoRecordPdu.role = _ApeConsts2.default.userTypesToId[this.classInfo.userRole] || 1; //NR_NORMAL用户的身份,根据用户登录时的身份设置
+ nodeInfoRecordPdu.level = 0;
+
+ var conferenceRecord = {}; //RCConferenceRecord_T
+ conferenceRecord._conference_id = this.classInfo.classId;
+ conferenceRecord._top_node_id = this.classInfo.topNodeID;
+
+ this.mcuClassInfo = {}; //RCMeetingInfo_T
+ this.mcuClassInfo.self = nodeInfoRecordPdu;
+ this.mcuClassInfo.info = conferenceRecord;
+
+ // 内部mcuConfInfo
+ this.classInfo.mcuClassInfo = this.mcuClassInfo;
+
+ //开启EverSocket
+ this._everSocket.begin(this.classInfo.MCUServerIP, this.classInfo.MCUServerPort);
+ }
+ }, {
+ key: 'connected',
+ get: function get() {
+ if (this._everSocket && this._everSocket.connected) return true;
+ return false;
+ }
+ }]);
+
+ return MCU;
+ }(_Emiter3.default);
+
+ var _default = new MCU();
+
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/mcu.js');
+
+ __REACT_HOT_LOADER__.register(MCU, 'MCU', 'D:/work/McuClient/src/mcu.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/mcu.js');
+ }();
+
+ ;
+
+/***/ },
+/* 24 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Emiter2 = __webpack_require__(3);
+
+ var _Emiter3 = _interopRequireDefault(_Emiter2);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //
+ // Copyright (C) 2016-present
+ // All Rights Reserved.
+ //
+ // Author: AlexWang
+ // Date: 2016-08-27 21:40:49
+ // Last Modified by: AlexWang
+ // Last Modified time: 2016-12-05 12:02:48
+ // QQ Email: 1669499355@qq.com
+ // Description: 底层Socket管理器,保持一直在线及异常重连.
+ //
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('EverSocket');
+
+ var EverSocket = function (_Emiter) {
+ _inherits(EverSocket, _Emiter);
+
+ function EverSocket() {
+ _classCallCheck(this, EverSocket);
+
+ var _this = _possibleConstructorReturn(this, (EverSocket.__proto__ || Object.getPrototypeOf(EverSocket)).call(this));
+
+ _this._connected = false;
+ _this._lastActiveTime = 0; //最后一次收到消息的时间
+ _this._enableEverSocket = false;
+ return _this;
+ }
+
+ _createClass(EverSocket, [{
+ key: 'begin',
+ value: function begin(ip, port) {
+ loger.log('开始WebSocket应用.');
+ this._enableEverSocket = true;
+ this.wsURL = 'ws://' + ip + ':' + port;
+ this._newConnection();
+ }
+ }, {
+ key: 'end',
+ value: function end() {
+ loger.log('停止WebSocket应用.');
+ this._clear();
+ }
+ }, {
+ key: 'send',
+ value: function send(data) {
+ if (this._connected) {
+ if (data) {
+ loger.log('SEND MESSAGE,byteLength---->', data.byteLength);
+ } else {
+ loger.log('SEND MESSAGE---->');
+ }
+ this.websocket.send(data);
+ } else {
+ loger.warn('WebSocket未建立连接.消息忽略');
+ }
+ }
+ }, {
+ key: '_setConnected',
+ value: function _setConnected() {
+ var isConn = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
+
+ this._connected = isConn;
+ if (this._connected) {
+ this._emit(EverSocket.OPEN);
+ } else {
+ this._emit(EverSocket.CLOSED);
+ }
+ }
+ }, {
+ key: '_newConnection',
+ value: function _newConnection() {
+ this.websocket = new WebSocket(this.wsURL);
+ this.websocket.binaryType = 'arraybuffer';
+ this.websocket.onopen = this._onOpen.bind(this);
+ this.websocket.onclose = this._onClose.bind(this);
+ this.websocket.onerror = this._onError.bind(this);
+ this.websocket.onmessage = this._onMessage.bind(this);
+ }
+ }, {
+ key: '_reConnection',
+ value: function _reConnection() {
+ var _this2 = this;
+
+ this._clear();
+ this.reConnectionTimeout = window.setTimeout(function () {
+ loger.log('WebSocket重新建立.');
+ window.clearTimeout(_this2.reConnectionTimeout);
+ _this2._newConnection();
+ }, EverSocket.RECONN_INTERVAL);
+ }
+ }, {
+ key: '_clear',
+ value: function _clear() {
+ //this._emit(EverSocket.CLOSED);
+ loger.log('WebSocket,Timers销毁');
+ window.clearInterval(this.pingTimer);
+ window.clearInterval(this.pongTimer);
+ if (this.websocket == null) {
+ loger.log('WebSocket,Timers已经销毁');
+ return;
+ }
+ this._setConnected(false); //先设置状态
+ this._enableEverSocket = false;
+ this.websocket.onopen = undefined;
+ this.websocket.onclose = undefined;
+ this.websocket.onerror = undefined;
+ this.websocket.onmessage = undefined;
+ try {
+ this.websocket.close();
+ } catch (e) {
+ loger.log('ignore errors');
+ }
+ this.websocket = undefined;
+ }
+ }, {
+ key: '_onOpen',
+ value: function _onOpen() {
+ loger.log('WebSocket建立成功', this.wsURL);
+
+ //启动心跳,检查socket链接状态
+ this.pingTimer = window.setInterval(this._sendPingHandler.bind(this), EverSocket.PING_INTERVAL);
+ this.pongTimer = window.setInterval(this._checkPongHandler.bind(this), EverSocket.PONG_INTERVAL);
+
+ this._setConnected();
+ }
+ }, {
+ key: '_onClose',
+ value: function _onClose(closeEvent) {
+ loger.log('WebSocket\u8FDE\u63A5\u65AD\u5F00 CODE:' + closeEvent.code + ' REASON:' + closeEvent.reason + ' CLEAN: ' + closeEvent.wasClean, this.wsURL);
+ this._reConnection();
+ }
+ }, {
+ key: '_onError',
+ value: function _onError() {
+ loger.log('WebSocket错误出现');
+ this._connected = false;
+ this._reConnection();
+ }
+ }, {
+ key: '_onMessage',
+ value: function _onMessage(messageEvent) {
+ loger.log('<----RECEIVE MESSAGE');
+ this._lastActiveTime = Date.now();
+ var bufferData = messageEvent.data;
+ if (bufferData.byteLength > 0) {
+ this._emit(EverSocket.MESSAGE, bufferData);
+ }
+ }
+ }, {
+ key: '_sendPingHandler',
+ value: function _sendPingHandler() {
+ if (this._connected) {
+ this.websocket.send(new ArrayBuffer());
+ } else {
+ this._reConnection();
+ }
+ }
+ }, {
+ key: '_checkPongHandler',
+ value: function _checkPongHandler() {
+ var pongTime = Date.now();
+ if (this._lastActiveTime && this._lastActiveTime >= pongTime - EverSocket.PONG_INTERVAL && this._lastActiveTime <= pongTime) {} else {
+ loger.warn('---服务器PINGPONG超时-----');
+ this._reConnection();
+ }
+ }
+ }, {
+ key: 'connected',
+ get: function get() {
+ return this._connected;
+ }
+ }]);
+
+ return EverSocket;
+ }(_Emiter3.default);
+
+ /*//修改之前的
+ EverSocket.prototype.PONG_INTERVAL = EverSocket.PONG_INTERVAL = 5000;
+ EverSocket.prototype.PING_INTERVAL = EverSocket.PING_INTERVAL = 3000;
+ EverSocket.prototype.RECONN_INTERVAL = EverSocket.RECONN_INTERVAL = 2000;*/
+
+ //20170223-mcu服务端修改了心跳的逻辑,如果客户端30秒没有请求,就会按离开的处理
+ //目前客户端发送心跳请求的空数据,服务端不会每次都回,暂定为10秒心跳一次
+
+
+ EverSocket.prototype.PONG_INTERVAL = EverSocket.PONG_INTERVAL = 21000; //
+ EverSocket.prototype.PING_INTERVAL = EverSocket.PING_INTERVAL = 10000; //心跳间隔
+ EverSocket.prototype.RECONN_INTERVAL = EverSocket.RECONN_INTERVAL = 3000; //重连的间隔
+
+ EverSocket.prototype.CONNECTING = EverSocket.CONNECTING = 0;
+ EverSocket.prototype.OPEN = EverSocket.OPEN = 1;
+ EverSocket.prototype.CLOSING = EverSocket.CLOSING = 2;
+ EverSocket.prototype.CLOSED = EverSocket.CLOSED = 3;
+ EverSocket.prototype.MESSAGE = EverSocket.MESSAGE = 4;
+
+ var _default = new EverSocket();
+
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/everSocket.js');
+
+ __REACT_HOT_LOADER__.register(EverSocket, 'EverSocket', 'D:/work/McuClient/src/everSocket.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/everSocket.js');
+ }();
+
+ ;
+
+/***/ },
+/* 25 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
+
+ var _protobufjs = __webpack_require__(26);
+
+ var _protobufjs2 = _interopRequireDefault(_protobufjs);
+
+ var _pro = __webpack_require__(33);
+
+ var _pro2 = _interopRequireDefault(_pro);
+
+ var _PduType = __webpack_require__(34);
+
+ var _PduType2 = _interopRequireDefault(_PduType);
+
+ var _PduConsts = __webpack_require__(35);
+
+ var _PduConsts2 = _interopRequireDefault(_PduConsts);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ var builder = _protobufjs2.default.newBuilder({ convertFieldsToCamelCase: true });
+ _protobufjs2.default.loadProto(_pro2.default, builder);
+
+ var pdu = builder.build();
+
+ // 底层通信层[Firstlayer] - RCSendDataPdu封包
+ function create_pdu(type, sub_type, initiator, conference_id, session_id, channel_id, upward, reliability, priority, peer, seg) {
+ var pduMsg = new pdu['RCSendDataPdu']();
+ pduMsg.set("type", type);
+ pduMsg.set("subType", sub_type);
+ pduMsg.set("initiator", initiator);
+ pduMsg.set("confId", conference_id); //***confId mcu服务用的是这个字段,客户端在其他地方统一为classId
+ pduMsg.set("sessionId", session_id);
+ pduMsg.set("channelId", channel_id);
+ pduMsg.set("upward", upward);
+ pduMsg.set("reliability", reliability);
+ pduMsg.set("priority", priority);
+ pduMsg.set("peer", peer);
+ pduMsg.set("seg", seg);
+ return pduMsg;
+ }
+ // 底层通信层[Firstlayer] - RCSendDataPdu解包
+ pdu.decode_pdu = function (buffer) {
+ return pdu['RCSendDataPdu'].decode(buffer);
+ };
+
+ pdu.create_join_class_request_pdu = function (sub_type, initiator, conference_id, session_id, channel_id, reliability, priority, peer, seg) {
+ return create_pdu(_PduType2.default.RCPDU_CONNECT_PROVIDER_REQUEST, sub_type, initiator, conference_id, session_id, channel_id, true, reliability, priority, peer, seg);
+ };
+
+ //upward 是否向顶层抛 create_uniform_pdu默认为true
+ pdu.create_uniform_pdu = function (sub_type, initiator, conference_id, session_id, channel_id, reliability, priority, peer, seg) {
+ return create_pdu(_PduType2.default.RCPDU_UNIFORM_SEND_DATA_REQUEST, sub_type, initiator, conference_id, session_id, channel_id, true, reliability, priority, peer, seg);
+ };
+
+ //upward 是否向顶层抛 create_normal_pdu 中由外部定义
+ pdu.create_normal_pdu = function (sub_type, initiator, conference_id, session_id, channel_id, upward, reliability, priority, peer, seg) {
+ return create_pdu(_PduType2.default.RCPDU_SEND_DATA_REQUEST, sub_type, initiator, conference_id, session_id, channel_id, upward, reliability, priority, peer, seg);
+ };
+
+ pdu.id2type = function (id) {
+ for (var type_const in _PduType2.default) {
+ if (_PduType2.default[type_const] === id) {
+ return type_const;
+ }
+ }
+ };
+
+ // 合并统一对外
+ pdu = _extends({}, pdu, _PduType2.default, _PduConsts2.default);
+
+ var _default = pdu;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(builder, 'builder', 'D:/work/McuClient/src/pdus/index.js');
+
+ __REACT_HOT_LOADER__.register(pdu, 'pdu', 'D:/work/McuClient/src/pdus/index.js');
+
+ __REACT_HOT_LOADER__.register(create_pdu, 'create_pdu', 'D:/work/McuClient/src/pdus/index.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/pdus/index.js');
+ }();
+
+ ;
+
+/***/ },
+/* 26 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(process, module) {/*
+ Copyright 2013 Daniel Wirtz <dcode@dcode.io>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+ /**
+ * @license protobuf.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/protobuf.js for details
+ */
+ (function (global, factory) {
+
+ /* AMD */
+ if ("function" === 'function' && __webpack_require__(28)["amd"])
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(29)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ /* CommonJS */
+ else if ("function" === "function" && typeof module === "object" && module && module["exports"])
+ module["exports"] = factory(__webpack_require__(29), true);
+ /* Global */
+ else
+ (global["dcodeIO"] = global["dcodeIO"] || {})["ProtoBuf"] = factory(global["dcodeIO"]["ByteBuffer"]);
+
+ })(this, function (ByteBuffer, isCommonJS) {
+ "use strict";
+
+ /**
+ * The ProtoBuf namespace.
+ * @exports ProtoBuf
+ * @namespace
+ * @expose
+ */
+ var ProtoBuf = {};
+
+ /**
+ * @type {!function(new: ByteBuffer, ...[*])}
+ * @expose
+ */
+ ProtoBuf.ByteBuffer = ByteBuffer;
+
+ /**
+ * @type {?function(new: Long, ...[*])}
+ * @expose
+ */
+ ProtoBuf.Long = ByteBuffer.Long || null;
+
+ /**
+ * ProtoBuf.js version.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ProtoBuf.VERSION = "5.0.1";
+
+ /**
+ * Wire types.
+ * @type {Object.<string,number>}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES = {};
+
+ /**
+ * Varint wire type.
+ * @type {number}
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.VARINT = 0;
+
+ /**
+ * Fixed 64 bits wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.BITS64 = 1;
+
+ /**
+ * Length delimited wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.LDELIM = 2;
+
+ /**
+ * Start group wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.STARTGROUP = 3;
+
+ /**
+ * End group wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.ENDGROUP = 4;
+
+ /**
+ * Fixed 32 bits wire type.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.WIRE_TYPES.BITS32 = 5;
+
+ /**
+ * Packable wire types.
+ * @type {!Array.<number>}
+ * @const
+ * @expose
+ */
+ ProtoBuf.PACKABLE_WIRE_TYPES = [
+ ProtoBuf.WIRE_TYPES.VARINT,
+ ProtoBuf.WIRE_TYPES.BITS64,
+ ProtoBuf.WIRE_TYPES.BITS32
+ ];
+
+ /**
+ * Types.
+ * @dict
+ * @type {!Object.<string,{name: string, wireType: number, defaultValue: *}>}
+ * @const
+ * @expose
+ */
+ ProtoBuf.TYPES = {
+ // According to the protobuf spec.
+ "int32": {
+ name: "int32",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: 0
+ },
+ "uint32": {
+ name: "uint32",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: 0
+ },
+ "sint32": {
+ name: "sint32",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: 0
+ },
+ "int64": {
+ name: "int64",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
+ },
+ "uint64": {
+ name: "uint64",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: ProtoBuf.Long ? ProtoBuf.Long.UZERO : undefined
+ },
+ "sint64": {
+ name: "sint64",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
+ },
+ "bool": {
+ name: "bool",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: false
+ },
+ "double": {
+ name: "double",
+ wireType: ProtoBuf.WIRE_TYPES.BITS64,
+ defaultValue: 0
+ },
+ "string": {
+ name: "string",
+ wireType: ProtoBuf.WIRE_TYPES.LDELIM,
+ defaultValue: ""
+ },
+ "bytes": {
+ name: "bytes",
+ wireType: ProtoBuf.WIRE_TYPES.LDELIM,
+ defaultValue: null // overridden in the code, must be a unique instance
+ },
+ "fixed32": {
+ name: "fixed32",
+ wireType: ProtoBuf.WIRE_TYPES.BITS32,
+ defaultValue: 0
+ },
+ "sfixed32": {
+ name: "sfixed32",
+ wireType: ProtoBuf.WIRE_TYPES.BITS32,
+ defaultValue: 0
+ },
+ "fixed64": {
+ name: "fixed64",
+ wireType: ProtoBuf.WIRE_TYPES.BITS64,
+ defaultValue: ProtoBuf.Long ? ProtoBuf.Long.UZERO : undefined
+ },
+ "sfixed64": {
+ name: "sfixed64",
+ wireType: ProtoBuf.WIRE_TYPES.BITS64,
+ defaultValue: ProtoBuf.Long ? ProtoBuf.Long.ZERO : undefined
+ },
+ "float": {
+ name: "float",
+ wireType: ProtoBuf.WIRE_TYPES.BITS32,
+ defaultValue: 0
+ },
+ "enum": {
+ name: "enum",
+ wireType: ProtoBuf.WIRE_TYPES.VARINT,
+ defaultValue: 0
+ },
+ "message": {
+ name: "message",
+ wireType: ProtoBuf.WIRE_TYPES.LDELIM,
+ defaultValue: null
+ },
+ "group": {
+ name: "group",
+ wireType: ProtoBuf.WIRE_TYPES.STARTGROUP,
+ defaultValue: null
+ }
+ };
+
+ /**
+ * Valid map key types.
+ * @type {!Array.<!Object.<string,{name: string, wireType: number, defaultValue: *}>>}
+ * @const
+ * @expose
+ */
+ ProtoBuf.MAP_KEY_TYPES = [
+ ProtoBuf.TYPES["int32"],
+ ProtoBuf.TYPES["sint32"],
+ ProtoBuf.TYPES["sfixed32"],
+ ProtoBuf.TYPES["uint32"],
+ ProtoBuf.TYPES["fixed32"],
+ ProtoBuf.TYPES["int64"],
+ ProtoBuf.TYPES["sint64"],
+ ProtoBuf.TYPES["sfixed64"],
+ ProtoBuf.TYPES["uint64"],
+ ProtoBuf.TYPES["fixed64"],
+ ProtoBuf.TYPES["bool"],
+ ProtoBuf.TYPES["string"],
+ ProtoBuf.TYPES["bytes"]
+ ];
+
+ /**
+ * Minimum field id.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.ID_MIN = 1;
+
+ /**
+ * Maximum field id.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ProtoBuf.ID_MAX = 0x1FFFFFFF;
+
+ /**
+ * If set to `true`, field names will be converted from underscore notation to camel case. Defaults to `false`.
+ * Must be set prior to parsing.
+ * @type {boolean}
+ * @expose
+ */
+ ProtoBuf.convertFieldsToCamelCase = false;
+
+ /**
+ * By default, messages are populated with (setX, set_x) accessors for each field. This can be disabled by
+ * setting this to `false` prior to building messages.
+ * @type {boolean}
+ * @expose
+ */
+ ProtoBuf.populateAccessors = true;
+
+ /**
+ * By default, messages are populated with default values if a field is not present on the wire. To disable
+ * this behavior, set this setting to `false`.
+ * @type {boolean}
+ * @expose
+ */
+ ProtoBuf.populateDefaults = true;
+
+ /**
+ * @alias ProtoBuf.Util
+ * @expose
+ */
+ ProtoBuf.Util = (function () {
+ "use strict";
+
+ /**
+ * ProtoBuf utilities.
+ * @exports ProtoBuf.Util
+ * @namespace
+ */
+ var Util = {};
+
+ /**
+ * Flag if running in node or not.
+ * @type {boolean}
+ * @const
+ * @expose
+ */
+ Util.IS_NODE = !!(
+ typeof process === 'object' && process + '' === '[object process]' && !process['browser']
+ );
+
+ /**
+ * Constructs a XMLHttpRequest object.
+ * @return {XMLHttpRequest}
+ * @throws {Error} If XMLHttpRequest is not supported
+ * @expose
+ */
+ Util.XHR = function () {
+ // No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
+ var XMLHttpFactories = [
+ function () {
+ return new XMLHttpRequest()
+ },
+ function () {
+ return new ActiveXObject("Msxml2.XMLHTTP")
+ },
+ function () {
+ return new ActiveXObject("Msxml3.XMLHTTP")
+ },
+ function () {
+ return new ActiveXObject("Microsoft.XMLHTTP")
+ }
+ ];
+ /** @type {?XMLHttpRequest} */
+ var xhr = null;
+ for (var i = 0; i < XMLHttpFactories.length; i++) {
+ try { xhr = XMLHttpFactories[i](); } catch (e) {
+ continue;
+ }
+ break;
+ }
+ if (!xhr)
+ throw Error("XMLHttpRequest is not supported");
+ return xhr;
+ };
+
+ /**
+ * Fetches a resource.
+ * @param {string} path Resource path
+ * @param {function(?string)=} callback Callback receiving the resource's contents. If omitted the resource will
+ * be fetched synchronously. If the request failed, contents will be null.
+ * @return {?string|undefined} Resource contents if callback is omitted (null if the request failed), else undefined.
+ * @expose
+ */
+ Util.fetch = function (path, callback) {
+ if (callback && typeof callback != 'function')
+ callback = null;
+ if (Util.IS_NODE) {
+ var fs = __webpack_require__(31);
+ if (callback) {
+ fs.readFile(path, function (err, data) {
+ if (err)
+ callback(null);
+ else
+ callback("" + data);
+ });
+ } else
+ try {
+ return fs.readFileSync(path);
+ } catch (e) {
+ return null;
+ }
+ } else {
+ var xhr = Util.XHR();
+ xhr.open('GET', path, callback ? true : false);
+ // xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
+ xhr.setRequestHeader('Accept', 'text/plain');
+ if (typeof xhr.overrideMimeType === 'function') xhr.overrideMimeType('text/plain');
+ if (callback) {
+ xhr.onreadystatechange = function () {
+ if (xhr.readyState != 4) return;
+ if ( /* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
+ callback(xhr.responseText);
+ else
+ callback(null);
+ };
+ if (xhr.readyState == 4)
+ return;
+ xhr.send(null);
+ } else {
+ xhr.send(null);
+ if ( /* remote */ xhr.status == 200 || /* local */ (xhr.status == 0 && typeof xhr.responseText === 'string'))
+ return xhr.responseText;
+ return null;
+ }
+ }
+ };
+
+ /**
+ * Converts a string to camel case.
+ * @param {string} str
+ * @returns {string}
+ * @expose
+ */
+ Util.toCamelCase = function (str) {
+ return str.replace(/_([a-zA-Z])/g, function ($0, $1) {
+ return $1.toUpperCase();
+ });
+ };
+
+ return Util;
+ })();
+
+ /**
+ * Language expressions.
+ * @type {!Object.<string,!RegExp>}
+ * @expose
+ */
+ ProtoBuf.Lang = {
+
+ // Characters always ending a statement
+ DELIM: /[\s\{\}=;:\[\],'"\(\)<>]/g,
+
+ // Field rules
+ RULE: /^(?:required|optional|repeated|map)$/,
+
+ // Field types
+ TYPE: /^(?:double|float|int32|uint32|sint32|int64|uint64|sint64|fixed32|sfixed32|fixed64|sfixed64|bool|string|bytes)$/,
+
+ // Names
+ NAME: /^[a-zA-Z_][a-zA-Z_0-9]*$/,
+
+ // Type definitions
+ TYPEDEF: /^[a-zA-Z][a-zA-Z_0-9]*$/,
+
+ // Type references
+ TYPEREF: /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/,
+
+ // Fully qualified type references
+ FQTYPEREF: /^(?:\.[a-zA-Z][a-zA-Z_0-9]*)+$/,
+
+ // All numbers
+ NUMBER: /^-?(?:[1-9][0-9]*|0|0[xX][0-9a-fA-F]+|0[0-7]+|([0-9]*(\.[0-9]*)?([Ee][+-]?[0-9]+)?)|inf|nan)$/,
+
+ // Decimal numbers
+ NUMBER_DEC: /^(?:[1-9][0-9]*|0)$/,
+
+ // Hexadecimal numbers
+ NUMBER_HEX: /^0[xX][0-9a-fA-F]+$/,
+
+ // Octal numbers
+ NUMBER_OCT: /^0[0-7]+$/,
+
+ // Floating point numbers
+ NUMBER_FLT: /^([0-9]*(\.[0-9]*)?([Ee][+-]?[0-9]+)?|inf|nan)$/,
+
+ // Booleans
+ BOOL: /^(?:true|false)$/i,
+
+ // Id numbers
+ ID: /^(?:[1-9][0-9]*|0|0[xX][0-9a-fA-F]+|0[0-7]+)$/,
+
+ // Negative id numbers (enum values)
+ NEGID: /^\-?(?:[1-9][0-9]*|0|0[xX][0-9a-fA-F]+|0[0-7]+)$/,
+
+ // Whitespaces
+ WHITESPACE: /\s/,
+
+ // All strings
+ STRING: /(?:"([^"\\]*(?:\\.[^"\\]*)*)")|(?:'([^'\\]*(?:\\.[^'\\]*)*)')/g,
+
+ // Double quoted strings
+ STRING_DQ: /(?:"([^"\\]*(?:\\.[^"\\]*)*)")/g,
+
+ // Single quoted strings
+ STRING_SQ: /(?:'([^'\\]*(?:\\.[^'\\]*)*)')/g
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto
+ * @expose
+ */
+ ProtoBuf.DotProto = (function (ProtoBuf, Lang) {
+ "use strict";
+
+ /**
+ * Utilities to parse .proto files.
+ * @exports ProtoBuf.DotProto
+ * @namespace
+ */
+ var DotProto = {};
+
+ /**
+ * Constructs a new Tokenizer.
+ * @exports ProtoBuf.DotProto.Tokenizer
+ * @class prototype tokenizer
+ * @param {string} proto Proto to tokenize
+ * @constructor
+ */
+ var Tokenizer = function (proto) {
+
+ /**
+ * Source to parse.
+ * @type {string}
+ * @expose
+ */
+ this.source = proto + "";
+
+ /**
+ * Current index.
+ * @type {number}
+ * @expose
+ */
+ this.index = 0;
+
+ /**
+ * Current line.
+ * @type {number}
+ * @expose
+ */
+ this.line = 1;
+
+ /**
+ * Token stack.
+ * @type {!Array.<string>}
+ * @expose
+ */
+ this.stack = [];
+
+ /**
+ * Opening character of the current string read, if any.
+ * @type {?string}
+ * @private
+ */
+ this._stringOpen = null;
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Tokenizer.prototype
+ * @inner
+ */
+ var TokenizerPrototype = Tokenizer.prototype;
+
+ /**
+ * Reads a string beginning at the current index.
+ * @return {string}
+ * @private
+ */
+ TokenizerPrototype._readString = function () {
+ var re = this._stringOpen === '"' ? Lang.STRING_DQ : Lang.STRING_SQ;
+ re.lastIndex = this.index - 1; // Include the open quote
+ var match = re.exec(this.source);
+ if (!match)
+ throw Error("unterminated string");
+ this.index = re.lastIndex;
+ this.stack.push(this._stringOpen);
+ this._stringOpen = null;
+ return match[1];
+ };
+
+ /**
+ * Gets the next token and advances by one.
+ * @return {?string} Token or `null` on EOF
+ * @expose
+ */
+ TokenizerPrototype.next = function () {
+ if (this.stack.length > 0)
+ return this.stack.shift();
+ if (this.index >= this.source.length)
+ return null;
+ if (this._stringOpen !== null)
+ return this._readString();
+
+ var repeat,
+ prev,
+ next;
+ do {
+ repeat = false;
+
+ // Strip white spaces
+ while (Lang.WHITESPACE.test(next = this.source.charAt(this.index))) {
+ if (next === '\n')
+ ++this.line;
+ if (++this.index === this.source.length)
+ return null;
+ }
+
+ // Strip comments
+ if (this.source.charAt(this.index) === '/') {
+ ++this.index;
+ if (this.source.charAt(this.index) === '/') { // Line
+ while (this.source.charAt(++this.index) !== '\n')
+ if (this.index == this.source.length)
+ return null;
+ ++this.index;
+ ++this.line;
+ repeat = true;
+ } else if ((next = this.source.charAt(this.index)) === '*') { /* Block */
+ do {
+ if (next === '\n')
+ ++this.line;
+ if (++this.index === this.source.length)
+ return null;
+ prev = next;
+ next = this.source.charAt(this.index);
+ } while (prev !== '*' || next !== '/');
+ ++this.index;
+ repeat = true;
+ } else
+ return '/';
+ }
+ } while (repeat);
+
+ if (this.index === this.source.length)
+ return null;
+
+ // Read the next token
+ var end = this.index;
+ Lang.DELIM.lastIndex = 0;
+ var delim = Lang.DELIM.test(this.source.charAt(end++));
+ if (!delim)
+ while (end < this.source.length && !Lang.DELIM.test(this.source.charAt(end)))
+ ++end;
+ var token = this.source.substring(this.index, this.index = end);
+ if (token === '"' || token === "'")
+ this._stringOpen = token;
+ return token;
+ };
+
+ /**
+ * Peeks for the next token.
+ * @return {?string} Token or `null` on EOF
+ * @expose
+ */
+ TokenizerPrototype.peek = function () {
+ if (this.stack.length === 0) {
+ var token = this.next();
+ if (token === null)
+ return null;
+ this.stack.push(token);
+ }
+ return this.stack[0];
+ };
+
+ /**
+ * Skips a specific token and throws if it differs.
+ * @param {string} expected Expected token
+ * @throws {Error} If the actual token differs
+ */
+ TokenizerPrototype.skip = function (expected) {
+ var actual = this.next();
+ if (actual !== expected)
+ throw Error("illegal '" + actual + "', '" + expected + "' expected");
+ };
+
+ /**
+ * Omits an optional token.
+ * @param {string} expected Expected optional token
+ * @returns {boolean} `true` if the token exists
+ */
+ TokenizerPrototype.omit = function (expected) {
+ if (this.peek() === expected) {
+ this.next();
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * Returns a string representation of this object.
+ * @return {string} String representation as of "Tokenizer(index/length)"
+ * @expose
+ */
+ TokenizerPrototype.toString = function () {
+ return "Tokenizer (" + this.index + "/" + this.source.length + " at line " + this.line + ")";
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Tokenizer
+ * @expose
+ */
+ DotProto.Tokenizer = Tokenizer;
+
+ /**
+ * Constructs a new Parser.
+ * @exports ProtoBuf.DotProto.Parser
+ * @class prototype parser
+ * @param {string} source Source
+ * @constructor
+ */
+ var Parser = function (source) {
+
+ /**
+ * Tokenizer.
+ * @type {!ProtoBuf.DotProto.Tokenizer}
+ * @expose
+ */
+ this.tn = new Tokenizer(source);
+
+ /**
+ * Whether parsing proto3 or not.
+ * @type {boolean}
+ */
+ this.proto3 = false;
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Parser.prototype
+ * @inner
+ */
+ var ParserPrototype = Parser.prototype;
+
+ /**
+ * Parses the source.
+ * @returns {!Object}
+ * @throws {Error} If the source cannot be parsed
+ * @expose
+ */
+ ParserPrototype.parse = function () {
+ var topLevel = {
+ "name": "[ROOT]", // temporary
+ "package": null,
+ "messages": [],
+ "enums": [],
+ "imports": [],
+ "options": {},
+ "services": []
+ // "syntax": undefined
+ };
+ var token,
+ head = true,
+ weak;
+ try {
+ while (token = this.tn.next()) {
+ switch (token) {
+ case 'package':
+ if (!head || topLevel["package"] !== null)
+ throw Error("unexpected 'package'");
+ token = this.tn.next();
+ if (!Lang.TYPEREF.test(token))
+ throw Error("illegal package name: " + token);
+ this.tn.skip(";");
+ topLevel["package"] = token;
+ break;
+ case 'import':
+ if (!head)
+ throw Error("unexpected 'import'");
+ token = this.tn.peek();
+ if (token === "public" || (weak = token === "weak")) // token ignored
+ this.tn.next();
+ token = this._readString();
+ this.tn.skip(";");
+ if (!weak) // import ignored
+ topLevel["imports"].push(token);
+ break;
+ case 'syntax':
+ if (!head)
+ throw Error("unexpected 'syntax'");
+ this.tn.skip("=");
+ if ((topLevel["syntax"] = this._readString()) === "proto3")
+ this.proto3 = true;
+ this.tn.skip(";");
+ break;
+ case 'message':
+ this._parseMessage(topLevel, null);
+ head = false;
+ break;
+ case 'enum':
+ this._parseEnum(topLevel);
+ head = false;
+ break;
+ case 'option':
+ this._parseOption(topLevel);
+ break;
+ case 'service':
+ this._parseService(topLevel);
+ break;
+ case 'extend':
+ this._parseExtend(topLevel);
+ break;
+ default:
+ throw Error("unexpected '" + token + "'");
+ }
+ }
+ } catch (e) {
+ e.message = "Parse error at line " + this.tn.line + ": " + e.message;
+ throw e;
+ }
+ delete topLevel["name"];
+ return topLevel;
+ };
+
+ /**
+ * Parses the specified source.
+ * @returns {!Object}
+ * @throws {Error} If the source cannot be parsed
+ * @expose
+ */
+ Parser.parse = function (source) {
+ return new Parser(source).parse();
+ };
+
+ // ----- Conversion ------
+
+ /**
+ * Converts a numerical string to an id.
+ * @param {string} value
+ * @param {boolean=} mayBeNegative
+ * @returns {number}
+ * @inner
+ */
+ function mkId(value, mayBeNegative) {
+ var id = -1,
+ sign = 1;
+ if (value.charAt(0) == '-') {
+ sign = -1;
+ value = value.substring(1);
+ }
+ if (Lang.NUMBER_DEC.test(value))
+ id = parseInt(value);
+ else if (Lang.NUMBER_HEX.test(value))
+ id = parseInt(value.substring(2), 16);
+ else if (Lang.NUMBER_OCT.test(value))
+ id = parseInt(value.substring(1), 8);
+ else
+ throw Error("illegal id value: " + (sign < 0 ? '-' : '') + value);
+ id = (sign * id) | 0; // Force to 32bit
+ if (!mayBeNegative && id < 0)
+ throw Error("illegal id value: " + (sign < 0 ? '-' : '') + value);
+ return id;
+ }
+
+ /**
+ * Converts a numerical string to a number.
+ * @param {string} val
+ * @returns {number}
+ * @inner
+ */
+ function mkNumber(val) {
+ var sign = 1;
+ if (val.charAt(0) == '-') {
+ sign = -1;
+ val = val.substring(1);
+ }
+ if (Lang.NUMBER_DEC.test(val))
+ return sign * parseInt(val, 10);
+ else if (Lang.NUMBER_HEX.test(val))
+ return sign * parseInt(val.substring(2), 16);
+ else if (Lang.NUMBER_OCT.test(val))
+ return sign * parseInt(val.substring(1), 8);
+ else if (val === 'inf')
+ return sign * Infinity;
+ else if (val === 'nan')
+ return NaN;
+ else if (Lang.NUMBER_FLT.test(val))
+ return sign * parseFloat(val);
+ throw Error("illegal number value: " + (sign < 0 ? '-' : '') + val);
+ }
+
+ // ----- Reading ------
+
+ /**
+ * Reads a string.
+ * @returns {string}
+ * @private
+ */
+ ParserPrototype._readString = function () {
+ var value = "",
+ token,
+ delim;
+ do {
+ delim = this.tn.next();
+ if (delim !== "'" && delim !== '"')
+ throw Error("illegal string delimiter: " + delim);
+ value += this.tn.next();
+ this.tn.skip(delim);
+ token = this.tn.peek();
+ } while (token === '"' || token === '"'); // multi line?
+ return value;
+ };
+
+ /**
+ * Reads a value.
+ * @param {boolean=} mayBeTypeRef
+ * @returns {number|boolean|string}
+ * @private
+ */
+ ParserPrototype._readValue = function (mayBeTypeRef) {
+ var token = this.tn.peek(),
+ value;
+ if (token === '"' || token === "'")
+ return this._readString();
+ this.tn.next();
+ if (Lang.NUMBER.test(token))
+ return mkNumber(token);
+ if (Lang.BOOL.test(token))
+ return (token.toLowerCase() === 'true');
+ if (mayBeTypeRef && Lang.TYPEREF.test(token))
+ return token;
+ throw Error("illegal value: " + token);
+
+ };
+
+ // ----- Parsing constructs -----
+
+ /**
+ * Parses a namespace option.
+ * @param {!Object} parent Parent definition
+ * @param {boolean=} isList
+ * @private
+ */
+ ParserPrototype._parseOption = function (parent, isList) {
+ var token = this.tn.next(),
+ custom = false;
+ if (token === '(') {
+ custom = true;
+ token = this.tn.next();
+ }
+ if (!Lang.TYPEREF.test(token))
+ // we can allow options of the form google.protobuf.* since they will just get ignored anyways
+ // if (!/google\.protobuf\./.test(token)) // FIXME: Why should that not be a valid typeref?
+ throw Error("illegal option name: " + token);
+ var name = token;
+ if (custom) { // (my_method_option).foo, (my_method_option), some_method_option, (foo.my_option).bar
+ this.tn.skip(')');
+ name = '(' + name + ')';
+ token = this.tn.peek();
+ if (Lang.FQTYPEREF.test(token)) {
+ name += token;
+ this.tn.next();
+ }
+ }
+ this.tn.skip('=');
+ this._parseOptionValue(parent, name);
+ if (!isList)
+ this.tn.skip(";");
+ };
+
+ /**
+ * Sets an option on the specified options object.
+ * @param {!Object.<string,*>} options
+ * @param {string} name
+ * @param {string|number|boolean} value
+ * @inner
+ */
+ function setOption(options, name, value) {
+ if (typeof options[name] === 'undefined')
+ options[name] = value;
+ else {
+ if (!Array.isArray(options[name]))
+ options[name] = [options[name]];
+ options[name].push(value);
+ }
+ }
+
+ /**
+ * Parses an option value.
+ * @param {!Object} parent
+ * @param {string} name
+ * @private
+ */
+ ParserPrototype._parseOptionValue = function (parent, name) {
+ var token = this.tn.peek();
+ if (token !== '{') { // Plain value
+ setOption(parent["options"], name, this._readValue(true));
+ } else { // Aggregate options
+ this.tn.skip("{");
+ while ((token = this.tn.next()) !== '}') {
+ if (!Lang.NAME.test(token))
+ throw Error("illegal option name: " + name + "." + token);
+ if (this.tn.omit(":"))
+ setOption(parent["options"], name + "." + token, this._readValue(true));
+ else
+ this._parseOptionValue(parent, name + "." + token);
+ }
+ }
+ };
+
+ /**
+ * Parses a service definition.
+ * @param {!Object} parent Parent definition
+ * @private
+ */
+ ParserPrototype._parseService = function (parent) {
+ var token = this.tn.next();
+ if (!Lang.NAME.test(token))
+ throw Error("illegal service name at line " + this.tn.line + ": " + token);
+ var name = token;
+ var svc = {
+ "name": name,
+ "rpc": {},
+ "options": {}
+ };
+ this.tn.skip("{");
+ while ((token = this.tn.next()) !== '}') {
+ if (token === "option")
+ this._parseOption(svc);
+ else if (token === 'rpc')
+ this._parseServiceRPC(svc);
+ else
+ throw Error("illegal service token: " + token);
+ }
+ this.tn.omit(";");
+ parent["services"].push(svc);
+ };
+
+ /**
+ * Parses a RPC service definition of the form ['rpc', name, (request), 'returns', (response)].
+ * @param {!Object} svc Service definition
+ * @private
+ */
+ ParserPrototype._parseServiceRPC = function (svc) {
+ var type = "rpc",
+ token = this.tn.next();
+ if (!Lang.NAME.test(token))
+ throw Error("illegal rpc service method name: " + token);
+ var name = token;
+ var method = {
+ "request": null,
+ "response": null,
+ "request_stream": false,
+ "response_stream": false,
+ "options": {}
+ };
+ this.tn.skip("(");
+ token = this.tn.next();
+ if (token.toLowerCase() === "stream") {
+ method["request_stream"] = true;
+ token = this.tn.next();
+ }
+ if (!Lang.TYPEREF.test(token))
+ throw Error("illegal rpc service request type: " + token);
+ method["request"] = token;
+ this.tn.skip(")");
+ token = this.tn.next();
+ if (token.toLowerCase() !== "returns")
+ throw Error("illegal rpc service request type delimiter: " + token);
+ this.tn.skip("(");
+ token = this.tn.next();
+ if (token.toLowerCase() === "stream") {
+ method["response_stream"] = true;
+ token = this.tn.next();
+ }
+ method["response"] = token;
+ this.tn.skip(")");
+ token = this.tn.peek();
+ if (token === '{') {
+ this.tn.next();
+ while ((token = this.tn.next()) !== '}') {
+ if (token === 'option')
+ this._parseOption(method);
+ else
+ throw Error("illegal rpc service token: " + token);
+ }
+ this.tn.omit(";");
+ } else
+ this.tn.skip(";");
+ if (typeof svc[type] === 'undefined')
+ svc[type] = {};
+ svc[type][name] = method;
+ };
+
+ /**
+ * Parses a message definition.
+ * @param {!Object} parent Parent definition
+ * @param {!Object=} fld Field definition if this is a group
+ * @returns {!Object}
+ * @private
+ */
+ ParserPrototype._parseMessage = function (parent, fld) {
+ var isGroup = !!fld,
+ token = this.tn.next();
+ var msg = {
+ "name": "",
+ "fields": [],
+ "enums": [],
+ "messages": [],
+ "options": {},
+ "services": [],
+ "oneofs": {}
+ // "extensions": undefined
+ };
+ if (!Lang.NAME.test(token))
+ throw Error("illegal " + (isGroup ? "group" : "message") + " name: " + token);
+ msg["name"] = token;
+ if (isGroup) {
+ this.tn.skip("=");
+ fld["id"] = mkId(this.tn.next());
+ msg["isGroup"] = true;
+ }
+ token = this.tn.peek();
+ if (token === '[' && fld)
+ this._parseFieldOptions(fld);
+ this.tn.skip("{");
+ while ((token = this.tn.next()) !== '}') {
+ if (Lang.RULE.test(token))
+ this._parseMessageField(msg, token);
+ else if (token === "oneof")
+ this._parseMessageOneOf(msg);
+ else if (token === "enum")
+ this._parseEnum(msg);
+ else if (token === "message")
+ this._parseMessage(msg);
+ else if (token === "option")
+ this._parseOption(msg);
+ else if (token === "service")
+ this._parseService(msg);
+ else if (token === "extensions")
+ msg["extensions"] = this._parseExtensionRanges();
+ else if (token === "reserved")
+ this._parseIgnored(); // TODO
+ else if (token === "extend")
+ this._parseExtend(msg);
+ else if (Lang.TYPEREF.test(token)) {
+ if (!this.proto3)
+ throw Error("illegal field rule: " + token);
+ this._parseMessageField(msg, "optional", token);
+ } else
+ throw Error("illegal message token: " + token);
+ }
+ this.tn.omit(";");
+ parent["messages"].push(msg);
+ return msg;
+ };
+
+ /**
+ * Parses an ignored statement.
+ * @private
+ */
+ ParserPrototype._parseIgnored = function () {
+ while (this.tn.peek() !== ';')
+ this.tn.next();
+ this.tn.skip(";");
+ };
+
+ /**
+ * Parses a message field.
+ * @param {!Object} msg Message definition
+ * @param {string} rule Field rule
+ * @param {string=} type Field type if already known (never known for maps)
+ * @returns {!Object} Field descriptor
+ * @private
+ */
+ ParserPrototype._parseMessageField = function (msg, rule, type) {
+ if (!Lang.RULE.test(rule))
+ throw Error("illegal message field rule: " + rule);
+ var fld = {
+ "rule": rule,
+ "type": "",
+ "name": "",
+ "options": {},
+ "id": 0
+ };
+ var token;
+ if (rule === "map") {
+
+ if (type)
+ throw Error("illegal type: " + type);
+ this.tn.skip('<');
+ token = this.tn.next();
+ if (!Lang.TYPE.test(token) && !Lang.TYPEREF.test(token))
+ throw Error("illegal message field type: " + token);
+ fld["keytype"] = token;
+ this.tn.skip(',');
+ token = this.tn.next();
+ if (!Lang.TYPE.test(token) && !Lang.TYPEREF.test(token))
+ throw Error("illegal message field: " + token);
+ fld["type"] = token;
+ this.tn.skip('>');
+ token = this.tn.next();
+ if (!Lang.NAME.test(token))
+ throw Error("illegal message field name: " + token);
+ fld["name"] = token;
+ this.tn.skip("=");
+ fld["id"] = mkId(this.tn.next());
+ token = this.tn.peek();
+ if (token === '[')
+ this._parseFieldOptions(fld);
+ this.tn.skip(";");
+
+ } else {
+
+ type = typeof type !== 'undefined' ? type : this.tn.next();
+
+ if (type === "group") {
+
+ // "A [legacy] group simply combines a nested message type and a field into a single declaration. In your
+ // code, you can treat this message just as if it had a Result type field called result (the latter name is
+ // converted to lower-case so that it does not conflict with the former)."
+ var grp = this._parseMessage(msg, fld);
+ if (!/^[A-Z]/.test(grp["name"]))
+ throw Error('illegal group name: ' + grp["name"]);
+ fld["type"] = grp["name"];
+ fld["name"] = grp["name"].toLowerCase();
+ this.tn.omit(";");
+
+ } else {
+
+ if (!Lang.TYPE.test(type) && !Lang.TYPEREF.test(type))
+ throw Error("illegal message field type: " + type);
+ fld["type"] = type;
+ token = this.tn.next();
+ if (!Lang.NAME.test(token))
+ throw Error("illegal message field name: " + token);
+ fld["name"] = token;
+ this.tn.skip("=");
+ fld["id"] = mkId(this.tn.next());
+ token = this.tn.peek();
+ if (token === "[")
+ this._parseFieldOptions(fld);
+ this.tn.skip(";");
+
+ }
+ }
+ msg["fields"].push(fld);
+ return fld;
+ };
+
+ /**
+ * Parses a message oneof.
+ * @param {!Object} msg Message definition
+ * @private
+ */
+ ParserPrototype._parseMessageOneOf = function (msg) {
+ var token = this.tn.next();
+ if (!Lang.NAME.test(token))
+ throw Error("illegal oneof name: " + token);
+ var name = token,
+ fld;
+ var fields = [];
+ this.tn.skip("{");
+ while ((token = this.tn.next()) !== "}") {
+ fld = this._parseMessageField(msg, "optional", token);
+ fld["oneof"] = name;
+ fields.push(fld["id"]);
+ }
+ this.tn.omit(";");
+ msg["oneofs"][name] = fields;
+ };
+
+ /**
+ * Parses a set of field option definitions.
+ * @param {!Object} fld Field definition
+ * @private
+ */
+ ParserPrototype._parseFieldOptions = function (fld) {
+ this.tn.skip("[");
+ var token,
+ first = true;
+ while ((token = this.tn.peek()) !== ']') {
+ if (!first)
+ this.tn.skip(",");
+ this._parseOption(fld, true);
+ first = false;
+ }
+ this.tn.next();
+ };
+
+ /**
+ * Parses an enum.
+ * @param {!Object} msg Message definition
+ * @private
+ */
+ ParserPrototype._parseEnum = function (msg) {
+ var enm = {
+ "name": "",
+ "values": [],
+ "options": {}
+ };
+ var token = this.tn.next();
+ if (!Lang.NAME.test(token))
+ throw Error("illegal name: " + token);
+ enm["name"] = token;
+ this.tn.skip("{");
+ while ((token = this.tn.next()) !== '}') {
+ if (token === "option")
+ this._parseOption(enm);
+ else {
+ if (!Lang.NAME.test(token))
+ throw Error("illegal name: " + token);
+ this.tn.skip("=");
+ var val = {
+ "name": token,
+ "id": mkId(this.tn.next(), true)
+ };
+ token = this.tn.peek();
+ if (token === "[")
+ this._parseFieldOptions({ "options": {} });
+ this.tn.skip(";");
+ enm["values"].push(val);
+ }
+ }
+ this.tn.omit(";");
+ msg["enums"].push(enm);
+ };
+
+ /**
+ * Parses extension / reserved ranges.
+ * @returns {!Array.<!Array.<number>>}
+ * @private
+ */
+ ParserPrototype._parseExtensionRanges = function () {
+ var ranges = [];
+ var token,
+ range,
+ value;
+ do {
+ range = [];
+ while (true) {
+ token = this.tn.next();
+ switch (token) {
+ case "min":
+ value = ProtoBuf.ID_MIN;
+ break;
+ case "max":
+ value = ProtoBuf.ID_MAX;
+ break;
+ default:
+ value = mkNumber(token);
+ break;
+ }
+ range.push(value);
+ if (range.length === 2)
+ break;
+ if (this.tn.peek() !== "to") {
+ range.push(value);
+ break;
+ }
+ this.tn.next();
+ }
+ ranges.push(range);
+ } while (this.tn.omit(","));
+ this.tn.skip(";");
+ return ranges;
+ };
+
+ /**
+ * Parses an extend block.
+ * @param {!Object} parent Parent object
+ * @private
+ */
+ ParserPrototype._parseExtend = function (parent) {
+ var token = this.tn.next();
+ if (!Lang.TYPEREF.test(token))
+ throw Error("illegal extend reference: " + token);
+ var ext = {
+ "ref": token,
+ "fields": []
+ };
+ this.tn.skip("{");
+ while ((token = this.tn.next()) !== '}') {
+ if (Lang.RULE.test(token))
+ this._parseMessageField(ext, token);
+ else if (Lang.TYPEREF.test(token)) {
+ if (!this.proto3)
+ throw Error("illegal field rule: " + token);
+ this._parseMessageField(ext, "optional", token);
+ } else
+ throw Error("illegal extend token: " + token);
+ }
+ this.tn.omit(";");
+ parent["messages"].push(ext);
+ return ext;
+ };
+
+ // ----- General -----
+
+ /**
+ * Returns a string representation of this parser.
+ * @returns {string}
+ */
+ ParserPrototype.toString = function () {
+ return "Parser at line " + this.tn.line;
+ };
+
+ /**
+ * @alias ProtoBuf.DotProto.Parser
+ * @expose
+ */
+ DotProto.Parser = Parser;
+
+ return DotProto;
+
+ })(ProtoBuf, ProtoBuf.Lang);
+
+ /**
+ * @alias ProtoBuf.Reflect
+ * @expose
+ */
+ ProtoBuf.Reflect = (function (ProtoBuf) {
+ "use strict";
+
+ /**
+ * Reflection types.
+ * @exports ProtoBuf.Reflect
+ * @namespace
+ */
+ var Reflect = {};
+
+ /**
+ * Constructs a Reflect base class.
+ * @exports ProtoBuf.Reflect.T
+ * @constructor
+ * @abstract
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {?ProtoBuf.Reflect.T} parent Parent object
+ * @param {string} name Object name
+ */
+ var T = function (builder, parent, name) {
+
+ /**
+ * Builder reference.
+ * @type {!ProtoBuf.Builder}
+ * @expose
+ */
+ this.builder = builder;
+
+ /**
+ * Parent object.
+ * @type {?ProtoBuf.Reflect.T}
+ * @expose
+ */
+ this.parent = parent;
+
+ /**
+ * Object name in namespace.
+ * @type {string}
+ * @expose
+ */
+ this.name = name;
+
+ /**
+ * Fully qualified class name
+ * @type {string}
+ * @expose
+ */
+ this.className;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.T.prototype
+ * @inner
+ */
+ var TPrototype = T.prototype;
+
+ /**
+ * Returns the fully qualified name of this object.
+ * @returns {string} Fully qualified name as of ".PATH.TO.THIS"
+ * @expose
+ */
+ TPrototype.fqn = function () {
+ var name = this.name,
+ ptr = this;
+ do {
+ ptr = ptr.parent;
+ if (ptr == null)
+ break;
+ name = ptr.name + "." + name;
+ } while (true);
+ return name;
+ };
+
+ /**
+ * Returns a string representation of this Reflect object (its fully qualified name).
+ * @param {boolean=} includeClass Set to true to include the class name. Defaults to false.
+ * @return String representation
+ * @expose
+ */
+ TPrototype.toString = function (includeClass) {
+ return (includeClass ? this.className + " " : "") + this.fqn();
+ };
+
+ /**
+ * Builds this type.
+ * @throws {Error} If this type cannot be built directly
+ * @expose
+ */
+ TPrototype.build = function () {
+ throw Error(this.toString(true) + " cannot be built directly");
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.T
+ * @expose
+ */
+ Reflect.T = T;
+
+ /**
+ * Constructs a new Namespace.
+ * @exports ProtoBuf.Reflect.Namespace
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {?ProtoBuf.Reflect.Namespace} parent Namespace parent
+ * @param {string} name Namespace name
+ * @param {Object.<string,*>=} options Namespace options
+ * @param {string?} syntax The syntax level of this definition (e.g., proto3)
+ * @constructor
+ * @extends ProtoBuf.Reflect.T
+ */
+ var Namespace = function (builder, parent, name, options, syntax) {
+ T.call(this, builder, parent, name);
+
+ /**
+ * @override
+ */
+ this.className = "Namespace";
+
+ /**
+ * Children inside the namespace.
+ * @type {!Array.<ProtoBuf.Reflect.T>}
+ */
+ this.children = [];
+
+ /**
+ * Options.
+ * @type {!Object.<string, *>}
+ */
+ this.options = options || {};
+
+ /**
+ * Syntax level (e.g., proto2 or proto3).
+ * @type {!string}
+ */
+ this.syntax = syntax || "proto2";
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Namespace.prototype
+ * @inner
+ */
+ var NamespacePrototype = Namespace.prototype = Object.create(T.prototype);
+
+ /**
+ * Returns an array of the namespace's children.
+ * @param {ProtoBuf.Reflect.T=} type Filter type (returns instances of this type only). Defaults to null (all children).
+ * @return {Array.<ProtoBuf.Reflect.T>}
+ * @expose
+ */
+ NamespacePrototype.getChildren = function (type) {
+ type = type || null;
+ if (type == null)
+ return this.children.slice();
+ var children = [];
+ for (var i = 0, k = this.children.length; i < k; ++i)
+ if (this.children[i] instanceof type)
+ children.push(this.children[i]);
+ return children;
+ };
+
+ /**
+ * Adds a child to the namespace.
+ * @param {ProtoBuf.Reflect.T} child Child
+ * @throws {Error} If the child cannot be added (duplicate)
+ * @expose
+ */
+ NamespacePrototype.addChild = function (child) {
+ var other;
+ if (other = this.getChild(child.name)) {
+ // Try to revert camelcase transformation on collision
+ if (other instanceof Message.Field && other.name !== other.originalName && this.getChild(other.originalName) === null)
+ other.name = other.originalName; // Revert previous first (effectively keeps both originals)
+ else if (child instanceof Message.Field && child.name !== child.originalName && this.getChild(child.originalName) === null)
+ child.name = child.originalName;
+ else
+ throw Error("Duplicate name in namespace " + this.toString(true) + ": " + child.name);
+ }
+ this.children.push(child);
+ };
+
+ /**
+ * Gets a child by its name or id.
+ * @param {string|number} nameOrId Child name or id
+ * @return {?ProtoBuf.Reflect.T} The child or null if not found
+ * @expose
+ */
+ NamespacePrototype.getChild = function (nameOrId) {
+ var key = typeof nameOrId === 'number' ? 'id' : 'name';
+ for (var i = 0, k = this.children.length; i < k; ++i)
+ if (this.children[i][key] === nameOrId)
+ return this.children[i];
+ return null;
+ };
+
+ /**
+ * Resolves a reflect object inside of this namespace.
+ * @param {string|!Array.<string>} qn Qualified name to resolve
+ * @param {boolean=} excludeNonNamespace Excludes non-namespace types, defaults to `false`
+ * @return {?ProtoBuf.Reflect.Namespace} The resolved type or null if not found
+ * @expose
+ */
+ NamespacePrototype.resolve = function (qn, excludeNonNamespace) {
+ var part = typeof qn === 'string' ? qn.split(".") : qn,
+ ptr = this,
+ i = 0;
+ if (part[i] === "") { // Fully qualified name, e.g. ".My.Message'
+ while (ptr.parent !== null)
+ ptr = ptr.parent;
+ i++;
+ }
+ var child;
+ do {
+ do {
+ if (!(ptr instanceof Reflect.Namespace)) {
+ ptr = null;
+ break;
+ }
+ child = ptr.getChild(part[i]);
+ if (!child || !(child instanceof Reflect.T) || (excludeNonNamespace && !(child instanceof Reflect.Namespace))) {
+ ptr = null;
+ break;
+ }
+ ptr = child;
+ i++;
+ } while (i < part.length);
+ if (ptr != null)
+ break; // Found
+ // Else search the parent
+ if (this.parent !== null)
+ return this.parent.resolve(qn, excludeNonNamespace);
+ } while (ptr != null);
+ return ptr;
+ };
+
+ /**
+ * Determines the shortest qualified name of the specified type, if any, relative to this namespace.
+ * @param {!ProtoBuf.Reflect.T} t Reflection type
+ * @returns {string} The shortest qualified name or, if there is none, the fqn
+ * @expose
+ */
+ NamespacePrototype.qn = function (t) {
+ var part = [],
+ ptr = t;
+ do {
+ part.unshift(ptr.name);
+ ptr = ptr.parent;
+ } while (ptr !== null);
+ for (var len = 1; len <= part.length; len++) {
+ var qn = part.slice(part.length - len);
+ if (t === this.resolve(qn, t instanceof Reflect.Namespace))
+ return qn.join(".");
+ }
+ return t.fqn();
+ };
+
+ /**
+ * Builds the namespace and returns the runtime counterpart.
+ * @return {Object.<string,Function|Object>} Runtime namespace
+ * @expose
+ */
+ NamespacePrototype.build = function () {
+ /** @dict */
+ var ns = {};
+ var children = this.children;
+ for (var i = 0, k = children.length, child; i < k; ++i) {
+ child = children[i];
+ if (child instanceof Namespace)
+ ns[child.name] = child.build();
+ }
+ if (Object.defineProperty)
+ Object.defineProperty(ns, "$options", { "value": this.buildOpt() });
+ return ns;
+ };
+
+ /**
+ * Builds the namespace's '$options' property.
+ * @return {Object.<string,*>}
+ */
+ NamespacePrototype.buildOpt = function () {
+ var opt = {},
+ keys = Object.keys(this.options);
+ for (var i = 0, k = keys.length; i < k; ++i) {
+ var key = keys[i],
+ val = this.options[keys[i]];
+ // TODO: Options are not resolved, yet.
+ // if (val instanceof Namespace) {
+ // opt[key] = val.build();
+ // } else {
+ opt[key] = val;
+ // }
+ }
+ return opt;
+ };
+
+ /**
+ * Gets the value assigned to the option with the specified name.
+ * @param {string=} name Returns the option value if specified, otherwise all options are returned.
+ * @return {*|Object.<string,*>}null} Option value or NULL if there is no such option
+ */
+ NamespacePrototype.getOption = function (name) {
+ if (typeof name === 'undefined')
+ return this.options;
+ return typeof this.options[name] !== 'undefined' ? this.options[name] : null;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Namespace
+ * @expose
+ */
+ Reflect.Namespace = Namespace;
+
+ /**
+ * Constructs a new Element implementation that checks and converts values for a
+ * particular field type, as appropriate.
+ *
+ * An Element represents a single value: either the value of a singular field,
+ * or a value contained in one entry of a repeated field or map field. This
+ * class does not implement these higher-level concepts; it only encapsulates
+ * the low-level typechecking and conversion.
+ *
+ * @exports ProtoBuf.Reflect.Element
+ * @param {{name: string, wireType: number}} type Resolved data type
+ * @param {ProtoBuf.Reflect.T|null} resolvedType Resolved type, if relevant
+ * (e.g. submessage field).
+ * @param {boolean} isMapKey Is this element a Map key? The value will be
+ * converted to string form if so.
+ * @param {string} syntax Syntax level of defining message type, e.g.,
+ * proto2 or proto3.
+ * @constructor
+ */
+ var Element = function (type, resolvedType, isMapKey, syntax) {
+
+ /**
+ * Element type, as a string (e.g., int32).
+ * @type {{name: string, wireType: number}}
+ */
+ this.type = type;
+
+ /**
+ * Element type reference to submessage or enum definition, if needed.
+ * @type {ProtoBuf.Reflect.T|null}
+ */
+ this.resolvedType = resolvedType;
+
+ /**
+ * Element is a map key.
+ * @type {boolean}
+ */
+ this.isMapKey = isMapKey;
+
+ /**
+ * Syntax level of defining message type, e.g., proto2 or proto3.
+ * @type {string}
+ */
+ this.syntax = syntax;
+
+ if (isMapKey && ProtoBuf.MAP_KEY_TYPES.indexOf(type) < 0)
+ throw Error("Invalid map key type: " + type.name);
+ };
+
+ var ElementPrototype = Element.prototype;
+
+ /**
+ * Obtains a (new) default value for the specified type.
+ * @param type {string|{name: string, wireType: number}} Field type
+ * @returns {*} Default value
+ * @inner
+ */
+ function mkDefault(type) {
+ if (typeof type === 'string')
+ type = ProtoBuf.TYPES[type];
+ if (typeof type.defaultValue === 'undefined')
+ throw Error("default value for type " + type.name + " is not supported");
+ if (type == ProtoBuf.TYPES["bytes"])
+ return new ByteBuffer(0);
+ return type.defaultValue;
+ }
+
+ /**
+ * Returns the default value for this field in proto3.
+ * @function
+ * @param type {string|{name: string, wireType: number}} the field type
+ * @returns {*} Default value
+ */
+ Element.defaultFieldValue = mkDefault;
+
+ /**
+ * Makes a Long from a value.
+ * @param {{low: number, high: number, unsigned: boolean}|string|number} value Value
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to reuse it from Long-like objects or to signed for
+ * strings and numbers
+ * @returns {!Long}
+ * @throws {Error} If the value cannot be converted to a Long
+ * @inner
+ */
+ function mkLong(value, unsigned) {
+ if (value && typeof value.low === 'number' && typeof value.high === 'number' && typeof value.unsigned === 'boolean' && value.low === value.low && value.high === value.high)
+ return new ProtoBuf.Long(value.low, value.high, typeof unsigned === 'undefined' ? value.unsigned : unsigned);
+ if (typeof value === 'string')
+ return ProtoBuf.Long.fromString(value, unsigned || false, 10);
+ if (typeof value === 'number')
+ return ProtoBuf.Long.fromNumber(value, unsigned || false);
+ throw Error("not convertible to Long");
+ }
+
+ /**
+ * Checks if the given value can be set for an element of this type (singular
+ * field or one element of a repeated field or map).
+ * @param {*} value Value to check
+ * @return {*} Verified, maybe adjusted, value
+ * @throws {Error} If the value cannot be verified for this element slot
+ * @expose
+ */
+ ElementPrototype.verifyValue = function (value) {
+ var self = this;
+
+ function fail(val, msg) {
+ throw Error("Illegal value for " + self.toString(true) + " of type " + self.type.name + ": " + val + " (" + msg + ")");
+ }
+ switch (this.type) {
+ // Signed 32bit
+ case ProtoBuf.TYPES["int32"]:
+ case ProtoBuf.TYPES["sint32"]:
+ case ProtoBuf.TYPES["sfixed32"]:
+ // Account for !NaN: value === value
+ if (typeof value !== 'number' || (value === value && value % 1 !== 0))
+ fail(typeof value, "not an integer");
+ return value > 4294967295 ? value | 0 : value;
+
+ // Unsigned 32bit
+ case ProtoBuf.TYPES["uint32"]:
+ case ProtoBuf.TYPES["fixed32"]:
+ if (typeof value !== 'number' || (value === value && value % 1 !== 0))
+ fail(typeof value, "not an integer");
+ return value < 0 ? value >>> 0 : value;
+
+ // Signed 64bit
+ case ProtoBuf.TYPES["int64"]:
+ case ProtoBuf.TYPES["sint64"]:
+ case ProtoBuf.TYPES["sfixed64"]:
+ {
+ if (ProtoBuf.Long)
+ try {
+ return mkLong(value, false);
+ } catch (e) {
+ fail(typeof value, e.message);
+ }
+ else
+ fail(typeof value, "requires Long.js");
+ }
+
+ // Unsigned 64bit
+ case ProtoBuf.TYPES["uint64"]:
+ case ProtoBuf.TYPES["fixed64"]:
+ {
+ if (ProtoBuf.Long)
+ try {
+ return mkLong(value, true);
+ } catch (e) {
+ fail(typeof value, e.message);
+ }
+ else
+ fail(typeof value, "requires Long.js");
+ }
+
+ // Bool
+ case ProtoBuf.TYPES["bool"]:
+ if (typeof value !== 'boolean')
+ fail(typeof value, "not a boolean");
+ return value;
+
+ // Float
+ case ProtoBuf.TYPES["float"]:
+ case ProtoBuf.TYPES["double"]:
+ if (typeof value !== 'number')
+ fail(typeof value, "not a number");
+ return value;
+
+ // Length-delimited string
+ case ProtoBuf.TYPES["string"]:
+ if (typeof value !== 'string' && !(value && value instanceof String))
+ fail(typeof value, "not a string");
+ return "" + value; // Convert String object to string
+
+ // Length-delimited bytes
+ case ProtoBuf.TYPES["bytes"]:
+ if (ByteBuffer.isByteBuffer(value))
+ return value;
+ return ByteBuffer.wrap(value, "base64");
+
+ // Constant enum value
+ case ProtoBuf.TYPES["enum"]:
+ {
+ var values = this.resolvedType.getChildren(ProtoBuf.Reflect.Enum.Value);
+ for (i = 0; i < values.length; i++)
+ if (values[i].name == value)
+ return values[i].id;
+ else if (values[i].id == value)
+ return values[i].id;
+
+ if (this.syntax === 'proto3') {
+ // proto3: just make sure it's an integer.
+ if (typeof value !== 'number' || (value === value && value % 1 !== 0))
+ fail(typeof value, "not an integer");
+ if (value > 4294967295 || value < 0)
+ fail(typeof value, "not in range for uint32")
+ return value;
+ } else {
+ // proto2 requires enum values to be valid.
+ fail(value, "not a valid enum value");
+ }
+ }
+ // Embedded message
+ case ProtoBuf.TYPES["group"]:
+ case ProtoBuf.TYPES["message"]:
+ {
+ if (!value || typeof value !== 'object')
+ fail(typeof value, "object expected");
+ if (value instanceof this.resolvedType.clazz)
+ return value;
+ if (value instanceof ProtoBuf.Builder.Message) {
+ // Mismatched type: Convert to object (see: https://github.com/dcodeIO/ProtoBuf.js/issues/180)
+ var obj = {};
+ for (var i in value)
+ if (value.hasOwnProperty(i))
+ obj[i] = value[i];
+ value = obj;
+ }
+ // Else let's try to construct one from a key-value object
+ return new(this.resolvedType.clazz)(value); // May throw for a hundred of reasons
+ }
+ }
+
+ // We should never end here
+ throw Error("[INTERNAL] Illegal value for " + this.toString(true) + ": " + value + " (undefined type " + this.type + ")");
+ };
+
+ /**
+ * Calculates the byte length of an element on the wire.
+ * @param {number} id Field number
+ * @param {*} value Field value
+ * @returns {number} Byte length
+ * @throws {Error} If the value cannot be calculated
+ * @expose
+ */
+ ElementPrototype.calculateLength = function (id, value) {
+ if (value === null) return 0; // Nothing to encode
+ // Tag has already been written
+ var n;
+ switch (this.type) {
+ case ProtoBuf.TYPES["int32"]:
+ return value < 0 ? ByteBuffer.calculateVarint64(value) : ByteBuffer.calculateVarint32(value);
+ case ProtoBuf.TYPES["uint32"]:
+ return ByteBuffer.calculateVarint32(value);
+ case ProtoBuf.TYPES["sint32"]:
+ return ByteBuffer.calculateVarint32(ByteBuffer.zigZagEncode32(value));
+ case ProtoBuf.TYPES["fixed32"]:
+ case ProtoBuf.TYPES["sfixed32"]:
+ case ProtoBuf.TYPES["float"]:
+ return 4;
+ case ProtoBuf.TYPES["int64"]:
+ case ProtoBuf.TYPES["uint64"]:
+ return ByteBuffer.calculateVarint64(value);
+ case ProtoBuf.TYPES["sint64"]:
+ return ByteBuffer.calculateVarint64(ByteBuffer.zigZagEncode64(value));
+ case ProtoBuf.TYPES["fixed64"]:
+ case ProtoBuf.TYPES["sfixed64"]:
+ return 8;
+ case ProtoBuf.TYPES["bool"]:
+ return 1;
+ case ProtoBuf.TYPES["enum"]:
+ return ByteBuffer.calculateVarint32(value);
+ case ProtoBuf.TYPES["double"]:
+ return 8;
+ case ProtoBuf.TYPES["string"]:
+ n = ByteBuffer.calculateUTF8Bytes(value);
+ return ByteBuffer.calculateVarint32(n) + n;
+ case ProtoBuf.TYPES["bytes"]:
+ if (value.remaining() < 0)
+ throw Error("Illegal value for " + this.toString(true) + ": " + value.remaining() + " bytes remaining");
+ return ByteBuffer.calculateVarint32(value.remaining()) + value.remaining();
+ case ProtoBuf.TYPES["message"]:
+ n = this.resolvedType.calculate(value);
+ return ByteBuffer.calculateVarint32(n) + n;
+ case ProtoBuf.TYPES["group"]:
+ n = this.resolvedType.calculate(value);
+ return n + ByteBuffer.calculateVarint32((id << 3) | ProtoBuf.WIRE_TYPES.ENDGROUP);
+ }
+ // We should never end here
+ throw Error("[INTERNAL] Illegal value to encode in " + this.toString(true) + ": " + value + " (unknown type)");
+ };
+
+ /**
+ * Encodes a value to the specified buffer. Does not encode the key.
+ * @param {number} id Field number
+ * @param {*} value Field value
+ * @param {ByteBuffer} buffer ByteBuffer to encode to
+ * @return {ByteBuffer} The ByteBuffer for chaining
+ * @throws {Error} If the value cannot be encoded
+ * @expose
+ */
+ ElementPrototype.encodeValue = function (id, value, buffer) {
+ if (value === null) return buffer; // Nothing to encode
+ // Tag has already been written
+
+ switch (this.type) {
+ // 32bit signed varint
+ case ProtoBuf.TYPES["int32"]:
+ // "If you use int32 or int64 as the type for a negative number, the resulting varint is always ten bytes
+ // long – it is, effectively, treated like a very large unsigned integer." (see #122)
+ if (value < 0)
+ buffer.writeVarint64(value);
+ else
+ buffer.writeVarint32(value);
+ break;
+
+ // 32bit unsigned varint
+ case ProtoBuf.TYPES["uint32"]:
+ buffer.writeVarint32(value);
+ break;
+
+ // 32bit varint zig-zag
+ case ProtoBuf.TYPES["sint32"]:
+ buffer.writeVarint32ZigZag(value);
+ break;
+
+ // Fixed unsigned 32bit
+ case ProtoBuf.TYPES["fixed32"]:
+ buffer.writeUint32(value);
+ break;
+
+ // Fixed signed 32bit
+ case ProtoBuf.TYPES["sfixed32"]:
+ buffer.writeInt32(value);
+ break;
+
+ // 64bit varint as-is
+ case ProtoBuf.TYPES["int64"]:
+ case ProtoBuf.TYPES["uint64"]:
+ buffer.writeVarint64(value); // throws
+ break;
+
+ // 64bit varint zig-zag
+ case ProtoBuf.TYPES["sint64"]:
+ buffer.writeVarint64ZigZag(value); // throws
+ break;
+
+ // Fixed unsigned 64bit
+ case ProtoBuf.TYPES["fixed64"]:
+ buffer.writeUint64(value); // throws
+ break;
+
+ // Fixed signed 64bit
+ case ProtoBuf.TYPES["sfixed64"]:
+ buffer.writeInt64(value); // throws
+ break;
+
+ // Bool
+ case ProtoBuf.TYPES["bool"]:
+ if (typeof value === 'string')
+ buffer.writeVarint32(value.toLowerCase() === 'false' ? 0 : !!value);
+ else
+ buffer.writeVarint32(value ? 1 : 0);
+ break;
+
+ // Constant enum value
+ case ProtoBuf.TYPES["enum"]:
+ buffer.writeVarint32(value);
+ break;
+
+ // 32bit float
+ case ProtoBuf.TYPES["float"]:
+ buffer.writeFloat32(value);
+ break;
+
+ // 64bit float
+ case ProtoBuf.TYPES["double"]:
+ buffer.writeFloat64(value);
+ break;
+
+ // Length-delimited string
+ case ProtoBuf.TYPES["string"]:
+ buffer.writeVString(value);
+ break;
+
+ // Length-delimited bytes
+ case ProtoBuf.TYPES["bytes"]:
+ if (value.remaining() < 0)
+ throw Error("Illegal value for " + this.toString(true) + ": " + value.remaining() + " bytes remaining");
+ var prevOffset = value.offset;
+ buffer.writeVarint32(value.remaining());
+ buffer.append(value);
+ value.offset = prevOffset;
+ break;
+
+ // Embedded message
+ case ProtoBuf.TYPES["message"]:
+ var bb = new ByteBuffer().LE();
+ this.resolvedType.encode(value, bb);
+ buffer.writeVarint32(bb.offset);
+ buffer.append(bb.flip());
+ break;
+
+ // Legacy group
+ case ProtoBuf.TYPES["group"]:
+ this.resolvedType.encode(value, buffer);
+ buffer.writeVarint32((id << 3) | ProtoBuf.WIRE_TYPES.ENDGROUP);
+ break;
+
+ default:
+ // We should never end here
+ throw Error("[INTERNAL] Illegal value to encode in " + this.toString(true) + ": " + value + " (unknown type)");
+ }
+ return buffer;
+ };
+
+ /**
+ * Decode one element value from the specified buffer.
+ * @param {ByteBuffer} buffer ByteBuffer to decode from
+ * @param {number} wireType The field wire type
+ * @param {number} id The field number
+ * @return {*} Decoded value
+ * @throws {Error} If the field cannot be decoded
+ * @expose
+ */
+ ElementPrototype.decode = function (buffer, wireType, id) {
+ if (wireType != this.type.wireType)
+ throw Error("Unexpected wire type for element");
+
+ var value, nBytes;
+ switch (this.type) {
+ // 32bit signed varint
+ case ProtoBuf.TYPES["int32"]:
+ return buffer.readVarint32() | 0;
+
+ // 32bit unsigned varint
+ case ProtoBuf.TYPES["uint32"]:
+ return buffer.readVarint32() >>> 0;
+
+ // 32bit signed varint zig-zag
+ case ProtoBuf.TYPES["sint32"]:
+ return buffer.readVarint32ZigZag() | 0;
+
+ // Fixed 32bit unsigned
+ case ProtoBuf.TYPES["fixed32"]:
+ return buffer.readUint32() >>> 0;
+
+ case ProtoBuf.TYPES["sfixed32"]:
+ return buffer.readInt32() | 0;
+
+ // 64bit signed varint
+ case ProtoBuf.TYPES["int64"]:
+ return buffer.readVarint64();
+
+ // 64bit unsigned varint
+ case ProtoBuf.TYPES["uint64"]:
+ return buffer.readVarint64().toUnsigned();
+
+ // 64bit signed varint zig-zag
+ case ProtoBuf.TYPES["sint64"]:
+ return buffer.readVarint64ZigZag();
+
+ // Fixed 64bit unsigned
+ case ProtoBuf.TYPES["fixed64"]:
+ return buffer.readUint64();
+
+ // Fixed 64bit signed
+ case ProtoBuf.TYPES["sfixed64"]:
+ return buffer.readInt64();
+
+ // Bool varint
+ case ProtoBuf.TYPES["bool"]:
+ return !!buffer.readVarint32();
+
+ // Constant enum value (varint)
+ case ProtoBuf.TYPES["enum"]:
+ // The following Builder.Message#set will already throw
+ return buffer.readVarint32();
+
+ // 32bit float
+ case ProtoBuf.TYPES["float"]:
+ return buffer.readFloat();
+
+ // 64bit float
+ case ProtoBuf.TYPES["double"]:
+ return buffer.readDouble();
+
+ // Length-delimited string
+ case ProtoBuf.TYPES["string"]:
+ return buffer.readVString();
+
+ // Length-delimited bytes
+ case ProtoBuf.TYPES["bytes"]:
+ {
+ nBytes = buffer.readVarint32();
+ if (buffer.remaining() < nBytes)
+ throw Error("Illegal number of bytes for " + this.toString(true) + ": " + nBytes + " required but got only " + buffer.remaining());
+ value = buffer.clone(); // Offset already set
+ value.limit = value.offset + nBytes;
+ buffer.offset += nBytes;
+ return value;
+ }
+
+ // Length-delimited embedded message
+ case ProtoBuf.TYPES["message"]:
+ {
+ nBytes = buffer.readVarint32();
+ return this.resolvedType.decode(buffer, nBytes);
+ }
+
+ // Legacy group
+ case ProtoBuf.TYPES["group"]:
+ return this.resolvedType.decode(buffer, -1, id);
+ }
+
+ // We should never end here
+ throw Error("[INTERNAL] Illegal decode type");
+ };
+
+ /**
+ * Converts a value from a string to the canonical element type.
+ *
+ * Legal only when isMapKey is true.
+ *
+ * @param {string} str The string value
+ * @returns {*} The value
+ */
+ ElementPrototype.valueFromString = function (str) {
+ if (!this.isMapKey) {
+ throw Error("valueFromString() called on non-map-key element");
+ }
+
+ switch (this.type) {
+ case ProtoBuf.TYPES["int32"]:
+ case ProtoBuf.TYPES["sint32"]:
+ case ProtoBuf.TYPES["sfixed32"]:
+ case ProtoBuf.TYPES["uint32"]:
+ case ProtoBuf.TYPES["fixed32"]:
+ return this.verifyValue(parseInt(str));
+
+ case ProtoBuf.TYPES["int64"]:
+ case ProtoBuf.TYPES["sint64"]:
+ case ProtoBuf.TYPES["sfixed64"]:
+ case ProtoBuf.TYPES["uint64"]:
+ case ProtoBuf.TYPES["fixed64"]:
+ // Long-based fields support conversions from string already.
+ return this.verifyValue(str);
+
+ case ProtoBuf.TYPES["bool"]:
+ return str === "true";
+
+ case ProtoBuf.TYPES["string"]:
+ return this.verifyValue(str);
+
+ case ProtoBuf.TYPES["bytes"]:
+ return ByteBuffer.fromBinary(str);
+ }
+ };
+
+ /**
+ * Converts a value from the canonical element type to a string.
+ *
+ * It should be the case that `valueFromString(valueToString(val))` returns
+ * a value equivalent to `verifyValue(val)` for every legal value of `val`
+ * according to this element type.
+ *
+ * This may be used when the element must be stored or used as a string,
+ * e.g., as a map key on an Object.
+ *
+ * Legal only when isMapKey is true.
+ *
+ * @param {*} val The value
+ * @returns {string} The string form of the value.
+ */
+ ElementPrototype.valueToString = function (value) {
+ if (!this.isMapKey) {
+ throw Error("valueToString() called on non-map-key element");
+ }
+
+ if (this.type === ProtoBuf.TYPES["bytes"]) {
+ return value.toString("binary");
+ } else {
+ return value.toString();
+ }
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Element
+ * @expose
+ */
+ Reflect.Element = Element;
+
+ /**
+ * Constructs a new Message.
+ * @exports ProtoBuf.Reflect.Message
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Namespace} parent Parent message or namespace
+ * @param {string} name Message name
+ * @param {Object.<string,*>=} options Message options
+ * @param {boolean=} isGroup `true` if this is a legacy group
+ * @param {string?} syntax The syntax level of this definition (e.g., proto3)
+ * @constructor
+ * @extends ProtoBuf.Reflect.Namespace
+ */
+ var Message = function (builder, parent, name, options, isGroup, syntax) {
+ Namespace.call(this, builder, parent, name, options, syntax);
+
+ /**
+ * @override
+ */
+ this.className = "Message";
+
+ /**
+ * Extensions range.
+ * @type {!Array.<number>|undefined}
+ * @expose
+ */
+ this.extensions = undefined;
+
+ /**
+ * Runtime message class.
+ * @type {?function(new:ProtoBuf.Builder.Message)}
+ * @expose
+ */
+ this.clazz = null;
+
+ /**
+ * Whether this is a legacy group or not.
+ * @type {boolean}
+ * @expose
+ */
+ this.isGroup = !!isGroup;
+
+ // The following cached collections are used to efficiently iterate over or look up fields when decoding.
+
+ /**
+ * Cached fields.
+ * @type {?Array.<!ProtoBuf.Reflect.Message.Field>}
+ * @private
+ */
+ this._fields = null;
+
+ /**
+ * Cached fields by id.
+ * @type {?Object.<number,!ProtoBuf.Reflect.Message.Field>}
+ * @private
+ */
+ this._fieldsById = null;
+
+ /**
+ * Cached fields by name.
+ * @type {?Object.<string,!ProtoBuf.Reflect.Message.Field>}
+ * @private
+ */
+ this._fieldsByName = null;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Message.prototype
+ * @inner
+ */
+ var MessagePrototype = Message.prototype = Object.create(Namespace.prototype);
+
+ /**
+ * Builds the message and returns the runtime counterpart, which is a fully functional class.
+ * @see ProtoBuf.Builder.Message
+ * @param {boolean=} rebuild Whether to rebuild or not, defaults to false
+ * @return {ProtoBuf.Reflect.Message} Message class
+ * @throws {Error} If the message cannot be built
+ * @expose
+ */
+ MessagePrototype.build = function (rebuild) {
+ if (this.clazz && !rebuild)
+ return this.clazz;
+
+ // Create the runtime Message class in its own scope
+ var clazz = (function (ProtoBuf, T) {
+
+ var fields = T.getChildren(ProtoBuf.Reflect.Message.Field),
+ oneofs = T.getChildren(ProtoBuf.Reflect.Message.OneOf);
+
+ /**
+ * Constructs a new runtime Message.
+ * @name ProtoBuf.Builder.Message
+ * @class Barebone of all runtime messages.
+ * @param {!Object.<string,*>|string} values Preset values
+ * @param {...string} var_args
+ * @constructor
+ * @throws {Error} If the message cannot be created
+ */
+ var Message = function (values, var_args) {
+ ProtoBuf.Builder.Message.call(this);
+ // Create virtual oneof properties
+ for (var i = 0, k = oneofs.length; i < k; ++i)
+ this[oneofs[i].name] = null;
+ // Create fields and set default values
+ for (i = 0, k = fields.length; i < k; ++i) {
+ var field = fields[i];
+ this[field.name] =
+ field.repeated ? [] :
+ (field.map ? new ProtoBuf.Map(field) : null);
+ if ((field.required || T.syntax === 'proto3') &&
+ field.defaultValue !== null)
+ this[field.name] = field.defaultValue;
+ }
+
+ if (arguments.length > 0) {
+ var value;
+ // Set field values from a values object
+ if (arguments.length === 1 && values !== null && typeof values === 'object' &&
+ /* not _another_ Message */
+ (typeof values.encode !== 'function' || values instanceof Message) &&
+ /* not a repeated field */
+ !Array.isArray(values) &&
+ /* not a Map */
+ !(values instanceof ProtoBuf.Map) &&
+ /* not a ByteBuffer */
+ !ByteBuffer.isByteBuffer(values) &&
+ /* not an ArrayBuffer */
+ !(values instanceof ArrayBuffer) &&
+ /* not a Long */
+ !(ProtoBuf.Long && values instanceof ProtoBuf.Long)) {
+ this.$set(values);
+ } else // Set field values from arguments, in declaration order
+ for (i = 0, k = arguments.length; i < k; ++i)
+ if (typeof (value = arguments[i]) !== 'undefined')
+ this.$set(fields[i].name, value); // May throw
+ }
+ };
+
+ /**
+ * @alias ProtoBuf.Builder.Message.prototype
+ * @inner
+ */
+ var MessagePrototype = Message.prototype = Object.create(ProtoBuf.Builder.Message.prototype);
+
+ /**
+ * Adds a value to a repeated field.
+ * @name ProtoBuf.Builder.Message#add
+ * @function
+ * @param {string} key Field name
+ * @param {*} value Value to add
+ * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
+ * @returns {!ProtoBuf.Builder.Message} this
+ * @throws {Error} If the value cannot be added
+ * @expose
+ */
+ MessagePrototype.add = function (key, value, noAssert) {
+ var field = T._fieldsByName[key];
+ if (!noAssert) {
+ if (!field)
+ throw Error(this + "#" + key + " is undefined");
+ if (!(field instanceof ProtoBuf.Reflect.Message.Field))
+ throw Error(this + "#" + key + " is not a field: " + field.toString(true)); // May throw if it's an enum or embedded message
+ if (!field.repeated)
+ throw Error(this + "#" + key + " is not a repeated field");
+ value = field.verifyValue(value, true);
+ }
+ if (this[key] === null)
+ this[key] = [];
+ this[key].push(value);
+ return this;
+ };
+
+ /**
+ * Adds a value to a repeated field. This is an alias for {@link ProtoBuf.Builder.Message#add}.
+ * @name ProtoBuf.Builder.Message#$add
+ * @function
+ * @param {string} key Field name
+ * @param {*} value Value to add
+ * @param {boolean=} noAssert Whether to assert the value or not (asserts by default)
+ * @returns {!ProtoBuf.Builder.Message} this
+ * @throws {Error} If the value cannot be added
+ * @expose
+ */
+ MessagePrototype.$add = MessagePrototype.add;
+
+ /**
+ * Sets a field's value.
+ * @name ProtoBuf.Builder.Message#set
+ * @function
+ * @param {string|!Object.<string,*>} keyOrObj String key or plain object holding multiple values
+ * @param {(*|boolean)=} value Value to set if key is a string, otherwise omitted
+ * @param {boolean=} noAssert Whether to not assert for an actual field / proper value type, defaults to `false`
+ * @returns {!ProtoBuf.Builder.Message} this
+ * @throws {Error} If the value cannot be set
+ * @expose
+ */
+ MessagePrototype.set = function (keyOrObj, value, noAssert) {
+ if (keyOrObj && typeof keyOrObj === 'object') {
+ noAssert = value;
+ for (var ikey in keyOrObj)
+ if (keyOrObj.hasOwnProperty(ikey) && typeof (value = keyOrObj[ikey]) !== 'undefined')
+ this.$set(ikey, value, noAssert);
+ return this;
+ }
+ var field = T._fieldsByName[keyOrObj];
+ if (!noAssert) {
+ if (!field)
+ throw Error(this + "#" + keyOrObj + " is not a field: undefined");
+ if (!(field instanceof ProtoBuf.Reflect.Message.Field))
+ throw Error(this + "#" + keyOrObj + " is not a field: " + field.toString(true));
+ this[field.name] = (value = field.verifyValue(value)); // May throw
+ } else
+ this[keyOrObj] = value;
+ if (field && field.oneof) { // Field is part of an OneOf (not a virtual OneOf field)
+ var currentField = this[field.oneof.name]; // Virtual field references currently set field
+ if (value !== null) {
+ if (currentField !== null && currentField !== field.name)
+ this[currentField] = null; // Clear currently set field
+ this[field.oneof.name] = field.name; // Point virtual field at this field
+ } else if ( /* value === null && */ currentField === keyOrObj)
+ this[field.oneof.name] = null; // Clear virtual field (current field explicitly cleared)
+ }
+ return this;
+ };
+
+ /**
+ * Sets a field's value. This is an alias for [@link ProtoBuf.Builder.Message#set}.
+ * @name ProtoBuf.Builder.Message#$set
+ * @function
+ * @param {string|!Object.<string,*>} keyOrObj String key or plain object holding multiple values
+ * @param {(*|boolean)=} value Value to set if key is a string, otherwise omitted
+ * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
+ * @throws {Error} If the value cannot be set
+ * @expose
+ */
+ MessagePrototype.$set = MessagePrototype.set;
+
+ /**
+ * Gets a field's value.
+ * @name ProtoBuf.Builder.Message#get
+ * @function
+ * @param {string} key Key
+ * @param {boolean=} noAssert Whether to not assert for an actual field, defaults to `false`
+ * @return {*} Value
+ * @throws {Error} If there is no such field
+ * @expose
+ */
+ MessagePrototype.get = function (key, noAssert) {
+ if (noAssert)
+ return this[key];
+ var field = T._fieldsByName[key];
+ if (!field || !(field instanceof ProtoBuf.Reflect.Message.Field))
+ throw Error(this + "#" + key + " is not a field: undefined");
+ if (!(field instanceof ProtoBuf.Reflect.Message.Field))
+ throw Error(this + "#" + key + " is not a field: " + field.toString(true));
+ return this[field.name];
+ };
+
+ /**
+ * Gets a field's value. This is an alias for {@link ProtoBuf.Builder.Message#$get}.
+ * @name ProtoBuf.Builder.Message#$get
+ * @function
+ * @param {string} key Key
+ * @return {*} Value
+ * @throws {Error} If there is no such field
+ * @expose
+ */
+ MessagePrototype.$get = MessagePrototype.get;
+
+ // Getters and setters
+
+ for (var i = 0; i < fields.length; i++) {
+ var field = fields[i];
+ // no setters for extension fields as these are named by their fqn
+ if (field instanceof ProtoBuf.Reflect.Message.ExtensionField)
+ continue;
+
+ if (T.builder.options['populateAccessors'])
+ (function (field) {
+ // set/get[SomeValue]
+ var Name = field.originalName.replace(/(_[a-zA-Z])/g, function (match) {
+ return match.toUpperCase().replace('_', '');
+ });
+ Name = Name.substring(0, 1).toUpperCase() + Name.substring(1);
+
+ // set/get_[some_value] FIXME: Do we really need these?
+ var name = field.originalName.replace(/([A-Z])/g, function (match) {
+ return "_" + match;
+ });
+
+ /**
+ * The current field's unbound setter function.
+ * @function
+ * @param {*} value
+ * @param {boolean=} noAssert
+ * @returns {!ProtoBuf.Builder.Message}
+ * @inner
+ */
+ var setter = function (value, noAssert) {
+ this[field.name] = noAssert ? value : field.verifyValue(value);
+ return this;
+ };
+
+ /**
+ * The current field's unbound getter function.
+ * @function
+ * @returns {*}
+ * @inner
+ */
+ var getter = function () {
+ return this[field.name];
+ };
+
+ if (T.getChild("set" + Name) === null)
+ /**
+ * Sets a value. This method is present for each field, but only if there is no name conflict with
+ * another field.
+ * @name ProtoBuf.Builder.Message#set[SomeField]
+ * @function
+ * @param {*} value Value to set
+ * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
+ * @returns {!ProtoBuf.Builder.Message} this
+ * @abstract
+ * @throws {Error} If the value cannot be set
+ */
+ MessagePrototype["set" + Name] = setter;
+
+ if (T.getChild("set_" + name) === null)
+ /**
+ * Sets a value. This method is present for each field, but only if there is no name conflict with
+ * another field.
+ * @name ProtoBuf.Builder.Message#set_[some_field]
+ * @function
+ * @param {*} value Value to set
+ * @param {boolean=} noAssert Whether to not assert the value, defaults to `false`
+ * @returns {!ProtoBuf.Builder.Message} this
+ * @abstract
+ * @throws {Error} If the value cannot be set
+ */
+ MessagePrototype["set_" + name] = setter;
+
+ if (T.getChild("get" + Name) === null)
+ /**
+ * Gets a value. This method is present for each field, but only if there is no name conflict with
+ * another field.
+ * @name ProtoBuf.Builder.Message#get[SomeField]
+ * @function
+ * @abstract
+ * @return {*} The value
+ */
+ MessagePrototype["get" + Name] = getter;
+
+ if (T.getChild("get_" + name) === null)
+ /**
+ * Gets a value. This method is present for each field, but only if there is no name conflict with
+ * another field.
+ * @name ProtoBuf.Builder.Message#get_[some_field]
+ * @function
+ * @return {*} The value
+ * @abstract
+ */
+ MessagePrototype["get_" + name] = getter;
+
+ })(field);
+ }
+
+ // En-/decoding
+
+ /**
+ * Encodes the message.
+ * @name ProtoBuf.Builder.Message#$encode
+ * @function
+ * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
+ * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
+ * @return {!ByteBuffer} Encoded message as a ByteBuffer
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded ByteBuffer in the `encoded` property on the error.
+ * @expose
+ * @see ProtoBuf.Builder.Message#encode64
+ * @see ProtoBuf.Builder.Message#encodeHex
+ * @see ProtoBuf.Builder.Message#encodeAB
+ */
+ MessagePrototype.encode = function (buffer, noVerify) {
+ if (typeof buffer === 'boolean')
+ noVerify = buffer,
+ buffer = undefined;
+ var isNew = false;
+ if (!buffer)
+ buffer = new ByteBuffer(),
+ isNew = true;
+ var le = buffer.littleEndian;
+ try {
+ T.encode(this, buffer.LE(), noVerify);
+ return (isNew ? buffer.flip() : buffer).LE(le);
+ } catch (e) {
+ buffer.LE(le);
+ throw (e);
+ }
+ };
+
+ /**
+ * Encodes a message using the specified data payload.
+ * @param {!Object.<string,*>} data Data payload
+ * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
+ * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
+ * @return {!ByteBuffer} Encoded message as a ByteBuffer
+ * @expose
+ */
+ Message.encode = function (data, buffer, noVerify) {
+ return new Message(data).encode(buffer, noVerify);
+ };
+
+ /**
+ * Calculates the byte length of the message.
+ * @name ProtoBuf.Builder.Message#calculate
+ * @function
+ * @returns {number} Byte length
+ * @throws {Error} If the message cannot be calculated or if required fields are missing.
+ * @expose
+ */
+ MessagePrototype.calculate = function () {
+ return T.calculate(this);
+ };
+
+ /**
+ * Encodes the varint32 length-delimited message.
+ * @name ProtoBuf.Builder.Message#encodeDelimited
+ * @function
+ * @param {(!ByteBuffer|boolean)=} buffer ByteBuffer to encode to. Will create a new one and flip it if omitted.
+ * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
+ * @return {!ByteBuffer} Encoded message as a ByteBuffer
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded ByteBuffer in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.encodeDelimited = function (buffer, noVerify) {
+ var isNew = false;
+ if (!buffer)
+ buffer = new ByteBuffer(),
+ isNew = true;
+ var enc = new ByteBuffer().LE();
+ T.encode(this, enc, noVerify).flip();
+ buffer.writeVarint32(enc.remaining());
+ buffer.append(enc);
+ return isNew ? buffer.flip() : buffer;
+ };
+
+ /**
+ * Directly encodes the message to an ArrayBuffer.
+ * @name ProtoBuf.Builder.Message#encodeAB
+ * @function
+ * @return {ArrayBuffer} Encoded message as ArrayBuffer
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded ArrayBuffer in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.encodeAB = function () {
+ try {
+ return this.encode().toArrayBuffer();
+ } catch (e) {
+ if (e["encoded"]) e["encoded"] = e["encoded"].toArrayBuffer();
+ throw (e);
+ }
+ };
+
+ /**
+ * Returns the message as an ArrayBuffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeAB}.
+ * @name ProtoBuf.Builder.Message#toArrayBuffer
+ * @function
+ * @return {ArrayBuffer} Encoded message as ArrayBuffer
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded ArrayBuffer in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.toArrayBuffer = MessagePrototype.encodeAB;
+
+ /**
+ * Directly encodes the message to a node Buffer.
+ * @name ProtoBuf.Builder.Message#encodeNB
+ * @function
+ * @return {!Buffer}
+ * @throws {Error} If the message cannot be encoded, not running under node.js or if required fields are
+ * missing. The later still returns the encoded node Buffer in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.encodeNB = function () {
+ try {
+ return this.encode().toBuffer();
+ } catch (e) {
+ if (e["encoded"]) e["encoded"] = e["encoded"].toBuffer();
+ throw (e);
+ }
+ };
+
+ /**
+ * Returns the message as a node Buffer. This is an alias for {@link ProtoBuf.Builder.Message#encodeNB}.
+ * @name ProtoBuf.Builder.Message#toBuffer
+ * @function
+ * @return {!Buffer}
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded node Buffer in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.toBuffer = MessagePrototype.encodeNB;
+
+ /**
+ * Directly encodes the message to a base64 encoded string.
+ * @name ProtoBuf.Builder.Message#encode64
+ * @function
+ * @return {string} Base64 encoded string
+ * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later
+ * still returns the encoded base64 string in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.encode64 = function () {
+ try {
+ return this.encode().toBase64();
+ } catch (e) {
+ if (e["encoded"]) e["encoded"] = e["encoded"].toBase64();
+ throw (e);
+ }
+ };
+
+ /**
+ * Returns the message as a base64 encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encode64}.
+ * @name ProtoBuf.Builder.Message#toBase64
+ * @function
+ * @return {string} Base64 encoded string
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded base64 string in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.toBase64 = MessagePrototype.encode64;
+
+ /**
+ * Directly encodes the message to a hex encoded string.
+ * @name ProtoBuf.Builder.Message#encodeHex
+ * @function
+ * @return {string} Hex encoded string
+ * @throws {Error} If the underlying buffer cannot be encoded or if required fields are missing. The later
+ * still returns the encoded hex string in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.encodeHex = function () {
+ try {
+ return this.encode().toHex();
+ } catch (e) {
+ if (e["encoded"]) e["encoded"] = e["encoded"].toHex();
+ throw (e);
+ }
+ };
+
+ /**
+ * Returns the message as a hex encoded string. This is an alias for {@link ProtoBuf.Builder.Message#encodeHex}.
+ * @name ProtoBuf.Builder.Message#toHex
+ * @function
+ * @return {string} Hex encoded string
+ * @throws {Error} If the message cannot be encoded or if required fields are missing. The later still
+ * returns the encoded hex string in the `encoded` property on the error.
+ * @expose
+ */
+ MessagePrototype.toHex = MessagePrototype.encodeHex;
+
+ /**
+ * Clones a message object or field value to a raw object.
+ * @param {*} obj Object to clone
+ * @param {boolean} binaryAsBase64 Whether to include binary data as base64 strings or as a buffer otherwise
+ * @param {boolean} longsAsStrings Whether to encode longs as strings
+ * @param {!ProtoBuf.Reflect.T=} resolvedType The resolved field type if a field
+ * @returns {*} Cloned object
+ * @inner
+ */
+ function cloneRaw(obj, binaryAsBase64, longsAsStrings, resolvedType) {
+ if (obj === null || typeof obj !== 'object') {
+ // Convert enum values to their respective names
+ if (resolvedType && resolvedType instanceof ProtoBuf.Reflect.Enum) {
+ var name = ProtoBuf.Reflect.Enum.getName(resolvedType.object, obj);
+ if (name !== null)
+ return name;
+ }
+ // Pass-through string, number, boolean, null...
+ return obj;
+ }
+ // Convert ByteBuffers to raw buffer or strings
+ if (ByteBuffer.isByteBuffer(obj))
+ return binaryAsBase64 ? obj.toBase64() : obj.toBuffer();
+ // Convert Longs to proper objects or strings
+ if (ProtoBuf.Long.isLong(obj))
+ return longsAsStrings ? obj.toString() : ProtoBuf.Long.fromValue(obj);
+ var clone;
+ // Clone arrays
+ if (Array.isArray(obj)) {
+ clone = [];
+ obj.forEach(function (v, k) {
+ clone[k] = cloneRaw(v, binaryAsBase64, longsAsStrings, resolvedType);
+ });
+ return clone;
+ }
+ clone = {};
+ // Convert maps to objects
+ if (obj instanceof ProtoBuf.Map) {
+ var it = obj.entries();
+ for (var e = it.next(); !e.done; e = it.next())
+ clone[obj.keyElem.valueToString(e.value[0])] = cloneRaw(e.value[1], binaryAsBase64, longsAsStrings, obj.valueElem.resolvedType);
+ return clone;
+ }
+ // Everything else is a non-null object
+ var type = obj.$type,
+ field = undefined;
+ for (var i in obj)
+ if (obj.hasOwnProperty(i)) {
+ if (type && (field = type.getChild(i)))
+ clone[i] = cloneRaw(obj[i], binaryAsBase64, longsAsStrings, field.resolvedType);
+ else
+ clone[i] = cloneRaw(obj[i], binaryAsBase64, longsAsStrings);
+ }
+ return clone;
+ }
+
+ /**
+ * Returns the message's raw payload.
+ * @param {boolean=} binaryAsBase64 Whether to include binary data as base64 strings instead of Buffers, defaults to `false`
+ * @param {boolean} longsAsStrings Whether to encode longs as strings
+ * @returns {Object.<string,*>} Raw payload
+ * @expose
+ */
+ MessagePrototype.toRaw = function (binaryAsBase64, longsAsStrings) {
+ return cloneRaw(this, !!binaryAsBase64, !!longsAsStrings, this.$type);
+ };
+
+ /**
+ * Encodes a message to JSON.
+ * @returns {string} JSON string
+ * @expose
+ */
+ MessagePrototype.encodeJSON = function () {
+ return JSON.stringify(
+ cloneRaw(this,
+ /* binary-as-base64 */
+ true,
+ /* longs-as-strings */
+ true,
+ this.$type
+ )
+ );
+ };
+
+ /**
+ * Decodes a message from the specified buffer or string.
+ * @name ProtoBuf.Builder.Message.decode
+ * @function
+ * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from
+ * @param {(number|string)=} length Message length. Defaults to decode all the remainig data.
+ * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64
+ * @return {!ProtoBuf.Builder.Message} Decoded message
+ * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
+ * returns the decoded message with missing fields in the `decoded` property on the error.
+ * @expose
+ * @see ProtoBuf.Builder.Message.decode64
+ * @see ProtoBuf.Builder.Message.decodeHex
+ */
+ Message.decode = function (buffer, length, enc) {
+ if (typeof length === 'string')
+ enc = length,
+ length = -1;
+ if (typeof buffer === 'string')
+ buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64");
+ buffer = ByteBuffer.isByteBuffer(buffer) ? buffer : ByteBuffer.wrap(buffer); // May throw
+ var le = buffer.littleEndian;
+ try {
+ var msg = T.decode(buffer.LE());
+ buffer.LE(le);
+ return msg;
+ } catch (e) {
+ buffer.LE(le);
+ throw (e);
+ }
+ };
+
+ /**
+ * Decodes a varint32 length-delimited message from the specified buffer or string.
+ * @name ProtoBuf.Builder.Message.decodeDelimited
+ * @function
+ * @param {!ByteBuffer|!ArrayBuffer|!Buffer|string} buffer Buffer to decode from
+ * @param {string=} enc Encoding if buffer is a string: hex, utf8 (not recommended), defaults to base64
+ * @return {ProtoBuf.Builder.Message} Decoded message or `null` if not enough bytes are available yet
+ * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
+ * returns the decoded message with missing fields in the `decoded` property on the error.
+ * @expose
+ */
+ Message.decodeDelimited = function (buffer, enc) {
+ if (typeof buffer === 'string')
+ buffer = ByteBuffer.wrap(buffer, enc ? enc : "base64");
+ buffer = ByteBuffer.isByteBuffer(buffer) ? buffer : ByteBuffer.wrap(buffer); // May throw
+ if (buffer.remaining() < 1)
+ return null;
+ var off = buffer.offset,
+ len = buffer.readVarint32();
+ if (buffer.remaining() < len) {
+ buffer.offset = off;
+ return null;
+ }
+ try {
+ var msg = T.decode(buffer.slice(buffer.offset, buffer.offset + len).LE());
+ buffer.offset += len;
+ return msg;
+ } catch (err) {
+ buffer.offset += len;
+ throw err;
+ }
+ };
+
+ /**
+ * Decodes the message from the specified base64 encoded string.
+ * @name ProtoBuf.Builder.Message.decode64
+ * @function
+ * @param {string} str String to decode from
+ * @return {!ProtoBuf.Builder.Message} Decoded message
+ * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
+ * returns the decoded message with missing fields in the `decoded` property on the error.
+ * @expose
+ */
+ Message.decode64 = function (str) {
+ return Message.decode(str, "base64");
+ };
+
+ /**
+ * Decodes the message from the specified hex encoded string.
+ * @name ProtoBuf.Builder.Message.decodeHex
+ * @function
+ * @param {string} str String to decode from
+ * @return {!ProtoBuf.Builder.Message} Decoded message
+ * @throws {Error} If the message cannot be decoded or if required fields are missing. The later still
+ * returns the decoded message with missing fields in the `decoded` property on the error.
+ * @expose
+ */
+ Message.decodeHex = function (str) {
+ return Message.decode(str, "hex");
+ };
+
+ /**
+ * Decodes the message from a JSON string.
+ * @name ProtoBuf.Builder.Message.decodeJSON
+ * @function
+ * @param {string} str String to decode from
+ * @return {!ProtoBuf.Builder.Message} Decoded message
+ * @throws {Error} If the message cannot be decoded or if required fields are
+ * missing.
+ * @expose
+ */
+ Message.decodeJSON = function (str) {
+ return new Message(JSON.parse(str));
+ };
+
+ // Utility
+
+ /**
+ * Returns a string representation of this Message.
+ * @name ProtoBuf.Builder.Message#toString
+ * @function
+ * @return {string} String representation as of ".Fully.Qualified.MessageName"
+ * @expose
+ */
+ MessagePrototype.toString = function () {
+ return T.toString();
+ };
+
+ // Properties
+
+ /**
+ * Message options.
+ * @name ProtoBuf.Builder.Message.$options
+ * @type {Object.<string,*>}
+ * @expose
+ */
+ var $optionsS; // cc needs this
+
+ /**
+ * Message options.
+ * @name ProtoBuf.Builder.Message#$options
+ * @type {Object.<string,*>}
+ * @expose
+ */
+ var $options;
+
+ /**
+ * Reflection type.
+ * @name ProtoBuf.Builder.Message.$type
+ * @type {!ProtoBuf.Reflect.Message}
+ * @expose
+ */
+ var $typeS;
+
+ /**
+ * Reflection type.
+ * @name ProtoBuf.Builder.Message#$type
+ * @type {!ProtoBuf.Reflect.Message}
+ * @expose
+ */
+ var $type;
+
+ if (Object.defineProperty)
+ Object.defineProperty(Message, '$options', { "value": T.buildOpt() }),
+ Object.defineProperty(MessagePrototype, "$options", { "value": Message["$options"] }),
+ Object.defineProperty(Message, "$type", { "value": T }),
+ Object.defineProperty(MessagePrototype, "$type", { "value": T });
+
+ return Message;
+
+ })(ProtoBuf, this);
+
+ // Static enums and prototyped sub-messages / cached collections
+ this._fields = [];
+ this._fieldsById = {};
+ this._fieldsByName = {};
+ for (var i = 0, k = this.children.length, child; i < k; i++) {
+ child = this.children[i];
+ if (child instanceof Enum || child instanceof Message || child instanceof Service) {
+ if (clazz.hasOwnProperty(child.name))
+ throw Error("Illegal reflect child of " + this.toString(true) + ": " + child.toString(true) + " cannot override static property '" + child.name + "'");
+ clazz[child.name] = child.build();
+ } else if (child instanceof Message.Field)
+ child.build(),
+ this._fields.push(child),
+ this._fieldsById[child.id] = child,
+ this._fieldsByName[child.name] = child;
+ else if (!(child instanceof Message.OneOf) && !(child instanceof Extension)) // Not built
+ throw Error("Illegal reflect child of " + this.toString(true) + ": " + this.children[i].toString(true));
+ }
+
+ return this.clazz = clazz;
+ };
+
+ /**
+ * Encodes a runtime message's contents to the specified buffer.
+ * @param {!ProtoBuf.Builder.Message} message Runtime message to encode
+ * @param {ByteBuffer} buffer ByteBuffer to write to
+ * @param {boolean=} noVerify Whether to not verify field values, defaults to `false`
+ * @return {ByteBuffer} The ByteBuffer for chaining
+ * @throws {Error} If required fields are missing or the message cannot be encoded for another reason
+ * @expose
+ */
+ MessagePrototype.encode = function (message, buffer, noVerify) {
+ var fieldMissing = null,
+ field;
+ for (var i = 0, k = this._fields.length, val; i < k; ++i) {
+ field = this._fields[i];
+ val = message[field.name];
+ if (field.required && val === null) {
+ if (fieldMissing === null)
+ fieldMissing = field;
+ } else
+ field.encode(noVerify ? val : field.verifyValue(val), buffer, message);
+ }
+ if (fieldMissing !== null) {
+ var err = Error("Missing at least one required field for " + this.toString(true) + ": " + fieldMissing);
+ err["encoded"] = buffer; // Still expose what we got
+ throw (err);
+ }
+ return buffer;
+ };
+
+ /**
+ * Calculates a runtime message's byte length.
+ * @param {!ProtoBuf.Builder.Message} message Runtime message to encode
+ * @returns {number} Byte length
+ * @throws {Error} If required fields are missing or the message cannot be calculated for another reason
+ * @expose
+ */
+ MessagePrototype.calculate = function (message) {
+ for (var n = 0, i = 0, k = this._fields.length, field, val; i < k; ++i) {
+ field = this._fields[i];
+ val = message[field.name];
+ if (field.required && val === null)
+ throw Error("Missing at least one required field for " + this.toString(true) + ": " + field);
+ else
+ n += field.calculate(val, message);
+ }
+ return n;
+ };
+
+ /**
+ * Skips all data until the end of the specified group has been reached.
+ * @param {number} expectedId Expected GROUPEND id
+ * @param {!ByteBuffer} buf ByteBuffer
+ * @returns {boolean} `true` if a value as been skipped, `false` if the end has been reached
+ * @throws {Error} If it wasn't possible to find the end of the group (buffer overrun or end tag mismatch)
+ * @inner
+ */
+ function skipTillGroupEnd(expectedId, buf) {
+ var tag = buf.readVarint32(), // Throws on OOB
+ wireType = tag & 0x07,
+ id = tag >>> 3;
+ switch (wireType) {
+ case ProtoBuf.WIRE_TYPES.VARINT:
+ do tag = buf.readUint8();
+ while ((tag & 0x80) === 0x80);
+ break;
+ case ProtoBuf.WIRE_TYPES.BITS64:
+ buf.offset += 8;
+ break;
+ case ProtoBuf.WIRE_TYPES.LDELIM:
+ tag = buf.readVarint32(); // reads the varint
+ buf.offset += tag; // skips n bytes
+ break;
+ case ProtoBuf.WIRE_TYPES.STARTGROUP:
+ skipTillGroupEnd(id, buf);
+ break;
+ case ProtoBuf.WIRE_TYPES.ENDGROUP:
+ if (id === expectedId)
+ return false;
+ else
+ throw Error("Illegal GROUPEND after unknown group: " + id + " (" + expectedId + " expected)");
+ case ProtoBuf.WIRE_TYPES.BITS32:
+ buf.offset += 4;
+ break;
+ default:
+ throw Error("Illegal wire type in unknown group " + expectedId + ": " + wireType);
+ }
+ return true;
+ }
+
+ /**
+ * Decodes an encoded message and returns the decoded message.
+ * @param {ByteBuffer} buffer ByteBuffer to decode from
+ * @param {number=} length Message length. Defaults to decode all remaining data.
+ * @param {number=} expectedGroupEndId Expected GROUPEND id if this is a legacy group
+ * @return {ProtoBuf.Builder.Message} Decoded message
+ * @throws {Error} If the message cannot be decoded
+ * @expose
+ */
+ MessagePrototype.decode = function (buffer, length, expectedGroupEndId) {
+ length = typeof length === 'number' ? length : -1;
+ var start = buffer.offset,
+ msg = new(this.clazz)(),
+ tag, wireType, id, field;
+ while (buffer.offset < start + length || (length === -1 && buffer.remaining() > 0)) {
+ tag = buffer.readVarint32();
+ wireType = tag & 0x07;
+ id = tag >>> 3;
+ if (wireType === ProtoBuf.WIRE_TYPES.ENDGROUP) {
+ if (id !== expectedGroupEndId)
+ throw Error("Illegal group end indicator for " + this.toString(true) + ": " + id + " (" + (expectedGroupEndId ? expectedGroupEndId + " expected" : "not a group") + ")");
+ break;
+ }
+ if (!(field = this._fieldsById[id])) {
+ // "messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing."
+ switch (wireType) {
+ case ProtoBuf.WIRE_TYPES.VARINT:
+ buffer.readVarint32();
+ break;
+ case ProtoBuf.WIRE_TYPES.BITS32:
+ buffer.offset += 4;
+ break;
+ case ProtoBuf.WIRE_TYPES.BITS64:
+ buffer.offset += 8;
+ break;
+ case ProtoBuf.WIRE_TYPES.LDELIM:
+ var len = buffer.readVarint32();
+ buffer.offset += len;
+ break;
+ case ProtoBuf.WIRE_TYPES.STARTGROUP:
+ while (skipTillGroupEnd(id, buffer)) {}
+ break;
+ default:
+ throw Error("Illegal wire type for unknown field " + id + " in " + this.toString(true) + "#decode: " + wireType);
+ }
+ continue;
+ }
+ if (field.repeated && !field.options["packed"]) {
+ msg[field.name].push(field.decode(wireType, buffer));
+ } else if (field.map) {
+ var keyval = field.decode(wireType, buffer);
+ msg[field.name].set(keyval[0], keyval[1]);
+ } else {
+ msg[field.name] = field.decode(wireType, buffer);
+ if (field.oneof) { // Field is part of an OneOf (not a virtual OneOf field)
+ var currentField = msg[field.oneof.name]; // Virtual field references currently set field
+ if (currentField !== null && currentField !== field.name)
+ msg[currentField] = null; // Clear currently set field
+ msg[field.oneof.name] = field.name; // Point virtual field at this field
+ }
+ }
+ }
+
+ // Check if all required fields are present and set default values for optional fields that are not
+ for (var i = 0, k = this._fields.length; i < k; ++i) {
+ field = this._fields[i];
+ if (msg[field.name] === null) {
+ if (this.syntax === "proto3") { // Proto3 sets default values by specification
+ msg[field.name] = field.defaultValue;
+ } else if (field.required) {
+ var err = Error("Missing at least one required field for " + this.toString(true) + ": " + field.name);
+ err["decoded"] = msg; // Still expose what we got
+ throw (err);
+ } else if (ProtoBuf.populateDefaults && field.defaultValue !== null)
+ msg[field.name] = field.defaultValue;
+ }
+ }
+ return msg;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Message
+ * @expose
+ */
+ Reflect.Message = Message;
+
+ /**
+ * Constructs a new Message Field.
+ * @exports ProtoBuf.Reflect.Message.Field
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Message} message Message reference
+ * @param {string} rule Rule, one of requried, optional, repeated
+ * @param {string?} keytype Key data type, if any.
+ * @param {string} type Data type, e.g. int32
+ * @param {string} name Field name
+ * @param {number} id Unique field id
+ * @param {Object.<string,*>=} options Options
+ * @param {!ProtoBuf.Reflect.Message.OneOf=} oneof Enclosing OneOf
+ * @param {string?} syntax The syntax level of this definition (e.g., proto3)
+ * @constructor
+ * @extends ProtoBuf.Reflect.T
+ */
+ var Field = function (builder, message, rule, keytype, type, name, id, options, oneof, syntax) {
+ T.call(this, builder, message, name);
+
+ /**
+ * @override
+ */
+ this.className = "Message.Field";
+
+ /**
+ * Message field required flag.
+ * @type {boolean}
+ * @expose
+ */
+ this.required = rule === "required";
+
+ /**
+ * Message field repeated flag.
+ * @type {boolean}
+ * @expose
+ */
+ this.repeated = rule === "repeated";
+
+ /**
+ * Message field map flag.
+ * @type {boolean}
+ * @expose
+ */
+ this.map = rule === "map";
+
+ /**
+ * Message field key type. Type reference string if unresolved, protobuf
+ * type if resolved. Valid only if this.map === true, null otherwise.
+ * @type {string|{name: string, wireType: number}|null}
+ * @expose
+ */
+ this.keyType = keytype || null;
+
+ /**
+ * Message field type. Type reference string if unresolved, protobuf type if
+ * resolved. In a map field, this is the value type.
+ * @type {string|{name: string, wireType: number}}
+ * @expose
+ */
+ this.type = type;
+
+ /**
+ * Resolved type reference inside the global namespace.
+ * @type {ProtoBuf.Reflect.T|null}
+ * @expose
+ */
+ this.resolvedType = null;
+
+ /**
+ * Unique message field id.
+ * @type {number}
+ * @expose
+ */
+ this.id = id;
+
+ /**
+ * Message field options.
+ * @type {!Object.<string,*>}
+ * @dict
+ * @expose
+ */
+ this.options = options || {};
+
+ /**
+ * Default value.
+ * @type {*}
+ * @expose
+ */
+ this.defaultValue = null;
+
+ /**
+ * Enclosing OneOf.
+ * @type {?ProtoBuf.Reflect.Message.OneOf}
+ * @expose
+ */
+ this.oneof = oneof || null;
+
+ /**
+ * Syntax level of this definition (e.g., proto3).
+ * @type {string}
+ * @expose
+ */
+ this.syntax = syntax || 'proto2';
+
+ /**
+ * Original field name.
+ * @type {string}
+ * @expose
+ */
+ this.originalName = this.name; // Used to revert camelcase transformation on naming collisions
+
+ /**
+ * Element implementation. Created in build() after types are resolved.
+ * @type {ProtoBuf.Element}
+ * @expose
+ */
+ this.element = null;
+
+ /**
+ * Key element implementation, for map fields. Created in build() after
+ * types are resolved.
+ * @type {ProtoBuf.Element}
+ * @expose
+ */
+ this.keyElement = null;
+
+ // Convert field names to camel case notation if the override is set
+ if (this.builder.options['convertFieldsToCamelCase'] && !(this instanceof Message.ExtensionField))
+ this.name = ProtoBuf.Util.toCamelCase(this.name);
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Message.Field.prototype
+ * @inner
+ */
+ var FieldPrototype = Field.prototype = Object.create(T.prototype);
+
+ /**
+ * Builds the field.
+ * @override
+ * @expose
+ */
+ FieldPrototype.build = function () {
+ this.element = new Element(this.type, this.resolvedType, false, this.syntax);
+ if (this.map)
+ this.keyElement = new Element(this.keyType, undefined, true, this.syntax);
+
+ // In proto3, fields do not have field presence, and every field is set to
+ // its type's default value ("", 0, 0.0, or false).
+ if (this.syntax === 'proto3' && !this.repeated && !this.map)
+ this.defaultValue = Element.defaultFieldValue(this.type);
+
+ // Otherwise, default values are present when explicitly specified
+ else if (typeof this.options['default'] !== 'undefined')
+ this.defaultValue = this.verifyValue(this.options['default']);
+ };
+
+ /**
+ * Checks if the given value can be set for this field.
+ * @param {*} value Value to check
+ * @param {boolean=} skipRepeated Whether to skip the repeated value check or not. Defaults to false.
+ * @return {*} Verified, maybe adjusted, value
+ * @throws {Error} If the value cannot be set for this field
+ * @expose
+ */
+ FieldPrototype.verifyValue = function (value, skipRepeated) {
+ skipRepeated = skipRepeated || false;
+ var self = this;
+
+ function fail(val, msg) {
+ throw Error("Illegal value for " + self.toString(true) + " of type " + self.type.name + ": " + val + " (" + msg + ")");
+ }
+ if (value === null) { // NULL values for optional fields
+ if (this.required)
+ fail(typeof value, "required");
+ if (this.syntax === 'proto3' && this.type !== ProtoBuf.TYPES["message"])
+ fail(typeof value, "proto3 field without field presence cannot be null");
+ return null;
+ }
+ var i;
+ if (this.repeated && !skipRepeated) { // Repeated values as arrays
+ if (!Array.isArray(value))
+ value = [value];
+ var res = [];
+ for (i = 0; i < value.length; i++)
+ res.push(this.element.verifyValue(value[i]));
+ return res;
+ }
+ if (this.map && !skipRepeated) { // Map values as objects
+ if (!(value instanceof ProtoBuf.Map)) {
+ // If not already a Map, attempt to convert.
+ if (!(value instanceof Object)) {
+ fail(typeof value,
+ "expected ProtoBuf.Map or raw object for map field");
+ }
+ return new ProtoBuf.Map(this, value);
+ } else {
+ return value;
+ }
+ }
+ // All non-repeated fields expect no array
+ if (!this.repeated && Array.isArray(value))
+ fail(typeof value, "no array expected");
+
+ return this.element.verifyValue(value);
+ };
+
+ /**
+ * Determines whether the field will have a presence on the wire given its
+ * value.
+ * @param {*} value Verified field value
+ * @param {!ProtoBuf.Builder.Message} message Runtime message
+ * @return {boolean} Whether the field will be present on the wire
+ */
+ FieldPrototype.hasWirePresence = function (value, message) {
+ if (this.syntax !== 'proto3')
+ return (value !== null);
+ if (this.oneof && message[this.oneof.name] === this.name)
+ return true;
+ switch (this.type) {
+ case ProtoBuf.TYPES["int32"]:
+ case ProtoBuf.TYPES["sint32"]:
+ case ProtoBuf.TYPES["sfixed32"]:
+ case ProtoBuf.TYPES["uint32"]:
+ case ProtoBuf.TYPES["fixed32"]:
+ return value !== 0;
+
+ case ProtoBuf.TYPES["int64"]:
+ case ProtoBuf.TYPES["sint64"]:
+ case ProtoBuf.TYPES["sfixed64"]:
+ case ProtoBuf.TYPES["uint64"]:
+ case ProtoBuf.TYPES["fixed64"]:
+ return value.low !== 0 || value.high !== 0;
+
+ case ProtoBuf.TYPES["bool"]:
+ return value;
+
+ case ProtoBuf.TYPES["float"]:
+ case ProtoBuf.TYPES["double"]:
+ return value !== 0.0;
+
+ case ProtoBuf.TYPES["string"]:
+ return value.length > 0;
+
+ case ProtoBuf.TYPES["bytes"]:
+ return value.remaining() > 0;
+
+ case ProtoBuf.TYPES["enum"]:
+ return value !== 0;
+
+ case ProtoBuf.TYPES["message"]:
+ return value !== null;
+ default:
+ return true;
+ }
+ };
+
+ /**
+ * Encodes the specified field value to the specified buffer.
+ * @param {*} value Verified field value
+ * @param {ByteBuffer} buffer ByteBuffer to encode to
+ * @param {!ProtoBuf.Builder.Message} message Runtime message
+ * @return {ByteBuffer} The ByteBuffer for chaining
+ * @throws {Error} If the field cannot be encoded
+ * @expose
+ */
+ FieldPrototype.encode = function (value, buffer, message) {
+ if (this.type === null || typeof this.type !== 'object')
+ throw Error("[INTERNAL] Unresolved type in " + this.toString(true) + ": " + this.type);
+ if (value === null || (this.repeated && value.length == 0))
+ return buffer; // Optional omitted
+ try {
+ if (this.repeated) {
+ var i;
+ // "Only repeated fields of primitive numeric types (types which use the varint, 32-bit, or 64-bit wire
+ // types) can be declared 'packed'."
+ if (this.options["packed"] && ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
+ // "All of the elements of the field are packed into a single key-value pair with wire type 2
+ // (length-delimited). Each element is encoded the same way it would be normally, except without a
+ // tag preceding it."
+ buffer.writeVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.LDELIM);
+ buffer.ensureCapacity(buffer.offset += 1); // We do not know the length yet, so let's assume a varint of length 1
+ var start = buffer.offset; // Remember where the contents begin
+ for (i = 0; i < value.length; i++)
+ this.element.encodeValue(this.id, value[i], buffer);
+ var len = buffer.offset - start,
+ varintLen = ByteBuffer.calculateVarint32(len);
+ if (varintLen > 1) { // We need to move the contents
+ var contents = buffer.slice(start, buffer.offset);
+ start += varintLen - 1;
+ buffer.offset = start;
+ buffer.append(contents);
+ }
+ buffer.writeVarint32(len, start - varintLen);
+ } else {
+ // "If your message definition has repeated elements (without the [packed=true] option), the encoded
+ // message has zero or more key-value pairs with the same tag number"
+ for (i = 0; i < value.length; i++)
+ buffer.writeVarint32((this.id << 3) | this.type.wireType),
+ this.element.encodeValue(this.id, value[i], buffer);
+ }
+ } else if (this.map) {
+ // Write out each map entry as a submessage.
+ value.forEach(function (val, key, m) {
+ // Compute the length of the submessage (key, val) pair.
+ var length =
+ ByteBuffer.calculateVarint32((1 << 3) | this.keyType.wireType) +
+ this.keyElement.calculateLength(1, key) +
+ ByteBuffer.calculateVarint32((2 << 3) | this.type.wireType) +
+ this.element.calculateLength(2, val);
+
+ // Submessage with wire type of length-delimited.
+ buffer.writeVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.LDELIM);
+ buffer.writeVarint32(length);
+
+ // Write out the key and val.
+ buffer.writeVarint32((1 << 3) | this.keyType.wireType);
+ this.keyElement.encodeValue(1, key, buffer);
+ buffer.writeVarint32((2 << 3) | this.type.wireType);
+ this.element.encodeValue(2, val, buffer);
+ }, this);
+ } else {
+ if (this.hasWirePresence(value, message)) {
+ buffer.writeVarint32((this.id << 3) | this.type.wireType);
+ this.element.encodeValue(this.id, value, buffer);
+ }
+ }
+ } catch (e) {
+ throw Error("Illegal value for " + this.toString(true) + ": " + value + " (" + e + ")");
+ }
+ return buffer;
+ };
+
+ /**
+ * Calculates the length of this field's value on the network level.
+ * @param {*} value Field value
+ * @param {!ProtoBuf.Builder.Message} message Runtime message
+ * @returns {number} Byte length
+ * @expose
+ */
+ FieldPrototype.calculate = function (value, message) {
+ value = this.verifyValue(value); // May throw
+ if (this.type === null || typeof this.type !== 'object')
+ throw Error("[INTERNAL] Unresolved type in " + this.toString(true) + ": " + this.type);
+ if (value === null || (this.repeated && value.length == 0))
+ return 0; // Optional omitted
+ var n = 0;
+ try {
+ if (this.repeated) {
+ var i, ni;
+ if (this.options["packed"] && ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
+ n += ByteBuffer.calculateVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.LDELIM);
+ ni = 0;
+ for (i = 0; i < value.length; i++)
+ ni += this.element.calculateLength(this.id, value[i]);
+ n += ByteBuffer.calculateVarint32(ni);
+ n += ni;
+ } else {
+ for (i = 0; i < value.length; i++)
+ n += ByteBuffer.calculateVarint32((this.id << 3) | this.type.wireType),
+ n += this.element.calculateLength(this.id, value[i]);
+ }
+ } else if (this.map) {
+ // Each map entry becomes a submessage.
+ value.forEach(function (val, key, m) {
+ // Compute the length of the submessage (key, val) pair.
+ var length =
+ ByteBuffer.calculateVarint32((1 << 3) | this.keyType.wireType) +
+ this.keyElement.calculateLength(1, key) +
+ ByteBuffer.calculateVarint32((2 << 3) | this.type.wireType) +
+ this.element.calculateLength(2, val);
+
+ n += ByteBuffer.calculateVarint32((this.id << 3) | ProtoBuf.WIRE_TYPES.LDELIM);
+ n += ByteBuffer.calculateVarint32(length);
+ n += length;
+ }, this);
+ } else {
+ if (this.hasWirePresence(value, message)) {
+ n += ByteBuffer.calculateVarint32((this.id << 3) | this.type.wireType);
+ n += this.element.calculateLength(this.id, value);
+ }
+ }
+ } catch (e) {
+ throw Error("Illegal value for " + this.toString(true) + ": " + value + " (" + e + ")");
+ }
+ return n;
+ };
+
+ /**
+ * Decode the field value from the specified buffer.
+ * @param {number} wireType Leading wire type
+ * @param {ByteBuffer} buffer ByteBuffer to decode from
+ * @param {boolean=} skipRepeated Whether to skip the repeated check or not. Defaults to false.
+ * @return {*} Decoded value: array for packed repeated fields, [key, value] for
+ * map fields, or an individual value otherwise.
+ * @throws {Error} If the field cannot be decoded
+ * @expose
+ */
+ FieldPrototype.decode = function (wireType, buffer, skipRepeated) {
+ var value, nBytes;
+
+ // We expect wireType to match the underlying type's wireType unless we see
+ // a packed repeated field, or unless this is a map field.
+ var wireTypeOK =
+ (!this.map && wireType == this.type.wireType) ||
+ (!skipRepeated && this.repeated && this.options["packed"] &&
+ wireType == ProtoBuf.WIRE_TYPES.LDELIM) ||
+ (this.map && wireType == ProtoBuf.WIRE_TYPES.LDELIM);
+ if (!wireTypeOK)
+ throw Error("Illegal wire type for field " + this.toString(true) + ": " + wireType + " (" + this.type.wireType + " expected)");
+
+ // Handle packed repeated fields.
+ if (wireType == ProtoBuf.WIRE_TYPES.LDELIM && this.repeated && this.options["packed"] && ProtoBuf.PACKABLE_WIRE_TYPES.indexOf(this.type.wireType) >= 0) {
+ if (!skipRepeated) {
+ nBytes = buffer.readVarint32();
+ nBytes = buffer.offset + nBytes; // Limit
+ var values = [];
+ while (buffer.offset < nBytes)
+ values.push(this.decode(this.type.wireType, buffer, true));
+ return values;
+ }
+ // Read the next value otherwise...
+ }
+
+ // Handle maps.
+ if (this.map) {
+ // Read one (key, value) submessage, and return [key, value]
+ var key = Element.defaultFieldValue(this.keyType);
+ value = Element.defaultFieldValue(this.type);
+
+ // Read the length
+ nBytes = buffer.readVarint32();
+ if (buffer.remaining() < nBytes)
+ throw Error("Illegal number of bytes for " + this.toString(true) + ": " + nBytes + " required but got only " + buffer.remaining());
+
+ // Get a sub-buffer of this key/value submessage
+ var msgbuf = buffer.clone();
+ msgbuf.limit = msgbuf.offset + nBytes;
+ buffer.offset += nBytes;
+
+ while (msgbuf.remaining() > 0) {
+ var tag = msgbuf.readVarint32();
+ wireType = tag & 0x07;
+ var id = tag >>> 3;
+ if (id === 1) {
+ key = this.keyElement.decode(msgbuf, wireType, id);
+ } else if (id === 2) {
+ value = this.element.decode(msgbuf, wireType, id);
+ } else {
+ throw Error("Unexpected tag in map field key/value submessage");
+ }
+ }
+
+ return [key, value];
+ }
+
+ // Handle singular and non-packed repeated field values.
+ return this.element.decode(buffer, wireType, this.id);
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Message.Field
+ * @expose
+ */
+ Reflect.Message.Field = Field;
+
+ /**
+ * Constructs a new Message ExtensionField.
+ * @exports ProtoBuf.Reflect.Message.ExtensionField
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Message} message Message reference
+ * @param {string} rule Rule, one of requried, optional, repeated
+ * @param {string} type Data type, e.g. int32
+ * @param {string} name Field name
+ * @param {number} id Unique field id
+ * @param {!Object.<string,*>=} options Options
+ * @constructor
+ * @extends ProtoBuf.Reflect.Message.Field
+ */
+ var ExtensionField = function (builder, message, rule, type, name, id, options) {
+ Field.call(this, builder, message, rule, /* keytype = */ null, type, name, id, options);
+
+ /**
+ * Extension reference.
+ * @type {!ProtoBuf.Reflect.Extension}
+ * @expose
+ */
+ this.extension;
+ };
+
+ // Extends Field
+ ExtensionField.prototype = Object.create(Field.prototype);
+
+ /**
+ * @alias ProtoBuf.Reflect.Message.ExtensionField
+ * @expose
+ */
+ Reflect.Message.ExtensionField = ExtensionField;
+
+ /**
+ * Constructs a new Message OneOf.
+ * @exports ProtoBuf.Reflect.Message.OneOf
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Message} message Message reference
+ * @param {string} name OneOf name
+ * @constructor
+ * @extends ProtoBuf.Reflect.T
+ */
+ var OneOf = function (builder, message, name) {
+ T.call(this, builder, message, name);
+
+ /**
+ * Enclosed fields.
+ * @type {!Array.<!ProtoBuf.Reflect.Message.Field>}
+ * @expose
+ */
+ this.fields = [];
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Message.OneOf
+ * @expose
+ */
+ Reflect.Message.OneOf = OneOf;
+
+ /**
+ * Constructs a new Enum.
+ * @exports ProtoBuf.Reflect.Enum
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.T} parent Parent Reflect object
+ * @param {string} name Enum name
+ * @param {Object.<string,*>=} options Enum options
+ * @param {string?} syntax The syntax level (e.g., proto3)
+ * @constructor
+ * @extends ProtoBuf.Reflect.Namespace
+ */
+ var Enum = function (builder, parent, name, options, syntax) {
+ Namespace.call(this, builder, parent, name, options, syntax);
+
+ /**
+ * @override
+ */
+ this.className = "Enum";
+
+ /**
+ * Runtime enum object.
+ * @type {Object.<string,number>|null}
+ * @expose
+ */
+ this.object = null;
+ };
+
+ /**
+ * Gets the string name of an enum value.
+ * @param {!ProtoBuf.Builder.Enum} enm Runtime enum
+ * @param {number} value Enum value
+ * @returns {?string} Name or `null` if not present
+ * @expose
+ */
+ Enum.getName = function (enm, value) {
+ var keys = Object.keys(enm);
+ for (var i = 0, key; i < keys.length; ++i)
+ if (enm[key = keys[i]] === value)
+ return key;
+ return null;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Enum.prototype
+ * @inner
+ */
+ var EnumPrototype = Enum.prototype = Object.create(Namespace.prototype);
+
+ /**
+ * Builds this enum and returns the runtime counterpart.
+ * @param {boolean} rebuild Whether to rebuild or not, defaults to false
+ * @returns {!Object.<string,number>}
+ * @expose
+ */
+ EnumPrototype.build = function (rebuild) {
+ if (this.object && !rebuild)
+ return this.object;
+ var enm = new ProtoBuf.Builder.Enum(),
+ values = this.getChildren(Enum.Value);
+ for (var i = 0, k = values.length; i < k; ++i)
+ enm[values[i]['name']] = values[i]['id'];
+ if (Object.defineProperty)
+ Object.defineProperty(enm, '$options', {
+ "value": this.buildOpt(),
+ "enumerable": false
+ });
+ return this.object = enm;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Enum
+ * @expose
+ */
+ Reflect.Enum = Enum;
+
+ /**
+ * Constructs a new Enum Value.
+ * @exports ProtoBuf.Reflect.Enum.Value
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Enum} enm Enum reference
+ * @param {string} name Field name
+ * @param {number} id Unique field id
+ * @constructor
+ * @extends ProtoBuf.Reflect.T
+ */
+ var Value = function (builder, enm, name, id) {
+ T.call(this, builder, enm, name);
+
+ /**
+ * @override
+ */
+ this.className = "Enum.Value";
+
+ /**
+ * Unique enum value id.
+ * @type {number}
+ * @expose
+ */
+ this.id = id;
+ };
+
+ // Extends T
+ Value.prototype = Object.create(T.prototype);
+
+ /**
+ * @alias ProtoBuf.Reflect.Enum.Value
+ * @expose
+ */
+ Reflect.Enum.Value = Value;
+
+ /**
+ * An extension (field).
+ * @exports ProtoBuf.Reflect.Extension
+ * @constructor
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.T} parent Parent object
+ * @param {string} name Object name
+ * @param {!ProtoBuf.Reflect.Message.Field} field Extension field
+ */
+ var Extension = function (builder, parent, name, field) {
+ T.call(this, builder, parent, name);
+
+ /**
+ * Extended message field.
+ * @type {!ProtoBuf.Reflect.Message.Field}
+ * @expose
+ */
+ this.field = field;
+ };
+
+ // Extends T
+ Extension.prototype = Object.create(T.prototype);
+
+ /**
+ * @alias ProtoBuf.Reflect.Extension
+ * @expose
+ */
+ Reflect.Extension = Extension;
+
+ /**
+ * Constructs a new Service.
+ * @exports ProtoBuf.Reflect.Service
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Namespace} root Root
+ * @param {string} name Service name
+ * @param {Object.<string,*>=} options Options
+ * @constructor
+ * @extends ProtoBuf.Reflect.Namespace
+ */
+ var Service = function (builder, root, name, options) {
+ Namespace.call(this, builder, root, name, options);
+
+ /**
+ * @override
+ */
+ this.className = "Service";
+
+ /**
+ * Built runtime service class.
+ * @type {?function(new:ProtoBuf.Builder.Service)}
+ */
+ this.clazz = null;
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Service.prototype
+ * @inner
+ */
+ var ServicePrototype = Service.prototype = Object.create(Namespace.prototype);
+
+ /**
+ * Builds the service and returns the runtime counterpart, which is a fully functional class.
+ * @see ProtoBuf.Builder.Service
+ * @param {boolean=} rebuild Whether to rebuild or not
+ * @return {Function} Service class
+ * @throws {Error} If the message cannot be built
+ * @expose
+ */
+ ServicePrototype.build = function (rebuild) {
+ if (this.clazz && !rebuild)
+ return this.clazz;
+
+ // Create the runtime Service class in its own scope
+ return this.clazz = (function (ProtoBuf, T) {
+
+ /**
+ * Constructs a new runtime Service.
+ * @name ProtoBuf.Builder.Service
+ * @param {function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))=} rpcImpl RPC implementation receiving the method name and the message
+ * @class Barebone of all runtime services.
+ * @constructor
+ * @throws {Error} If the service cannot be created
+ */
+ var Service = function (rpcImpl) {
+ ProtoBuf.Builder.Service.call(this);
+
+ /**
+ * Service implementation.
+ * @name ProtoBuf.Builder.Service#rpcImpl
+ * @type {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))}
+ * @expose
+ */
+ this.rpcImpl = rpcImpl || function (name, msg, callback) {
+ // This is what a user has to implement: A function receiving the method name, the actual message to
+ // send (type checked) and the callback that's either provided with the error as its first
+ // argument or null and the actual response message.
+ setTimeout(callback.bind(this, Error("Not implemented, see: https://github.com/dcodeIO/ProtoBuf.js/wiki/Services")), 0); // Must be async!
+ };
+ };
+
+ /**
+ * @alias ProtoBuf.Builder.Service.prototype
+ * @inner
+ */
+ var ServicePrototype = Service.prototype = Object.create(ProtoBuf.Builder.Service.prototype);
+
+ /**
+ * Asynchronously performs an RPC call using the given RPC implementation.
+ * @name ProtoBuf.Builder.Service.[Method]
+ * @function
+ * @param {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))} rpcImpl RPC implementation
+ * @param {ProtoBuf.Builder.Message} req Request
+ * @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
+ * the error if any and the response either as a pre-parsed message or as its raw bytes
+ * @abstract
+ */
+
+ /**
+ * Asynchronously performs an RPC call using the instance's RPC implementation.
+ * @name ProtoBuf.Builder.Service#[Method]
+ * @function
+ * @param {ProtoBuf.Builder.Message} req Request
+ * @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
+ * the error if any and the response either as a pre-parsed message or as its raw bytes
+ * @abstract
+ */
+
+ var rpc = T.getChildren(ProtoBuf.Reflect.Service.RPCMethod);
+ for (var i = 0; i < rpc.length; i++) {
+ (function (method) {
+
+ // service#Method(message, callback)
+ ServicePrototype[method.name] = function (req, callback) {
+ try {
+ try {
+ // If given as a buffer, decode the request. Will throw a TypeError if not a valid buffer.
+ req = method.resolvedRequestType.clazz.decode(ByteBuffer.wrap(req));
+ } catch (err) {
+ if (!(err instanceof TypeError))
+ throw err;
+ }
+ if (req === null || typeof req !== 'object')
+ throw Error("Illegal arguments");
+ if (!(req instanceof method.resolvedRequestType.clazz))
+ req = new method.resolvedRequestType.clazz(req);
+ this.rpcImpl(method.fqn(), req, function (err, res) { // Assumes that this is properly async
+ if (err) {
+ callback(err);
+ return;
+ }
+ // Coalesce to empty string when service response has empty content
+ if (res === null)
+ res = ''
+ try { res = method.resolvedResponseType.clazz.decode(res); } catch (notABuffer) {}
+ if (!res || !(res instanceof method.resolvedResponseType.clazz)) {
+ callback(Error("Illegal response type received in service method " + T.name + "#" + method.name));
+ return;
+ }
+ callback(null, res);
+ });
+ } catch (err) {
+ setTimeout(callback.bind(this, err), 0);
+ }
+ };
+
+ // Service.Method(rpcImpl, message, callback)
+ Service[method.name] = function (rpcImpl, req, callback) {
+ new Service(rpcImpl)[method.name](req, callback);
+ };
+
+ if (Object.defineProperty)
+ Object.defineProperty(Service[method.name], "$options", { "value": method.buildOpt() }),
+ Object.defineProperty(ServicePrototype[method.name], "$options", { "value": Service[method.name]["$options"] });
+ })(rpc[i]);
+ }
+
+ // Properties
+
+ /**
+ * Service options.
+ * @name ProtoBuf.Builder.Service.$options
+ * @type {Object.<string,*>}
+ * @expose
+ */
+ var $optionsS; // cc needs this
+
+ /**
+ * Service options.
+ * @name ProtoBuf.Builder.Service#$options
+ * @type {Object.<string,*>}
+ * @expose
+ */
+ var $options;
+
+ /**
+ * Reflection type.
+ * @name ProtoBuf.Builder.Service.$type
+ * @type {!ProtoBuf.Reflect.Service}
+ * @expose
+ */
+ var $typeS;
+
+ /**
+ * Reflection type.
+ * @name ProtoBuf.Builder.Service#$type
+ * @type {!ProtoBuf.Reflect.Service}
+ * @expose
+ */
+ var $type;
+
+ if (Object.defineProperty)
+ Object.defineProperty(Service, "$options", { "value": T.buildOpt() }),
+ Object.defineProperty(ServicePrototype, "$options", { "value": Service["$options"] }),
+ Object.defineProperty(Service, "$type", { "value": T }),
+ Object.defineProperty(ServicePrototype, "$type", { "value": T });
+
+ return Service;
+
+ })(ProtoBuf, this);
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Service
+ * @expose
+ */
+ Reflect.Service = Service;
+
+ /**
+ * Abstract service method.
+ * @exports ProtoBuf.Reflect.Service.Method
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Service} svc Service
+ * @param {string} name Method name
+ * @param {Object.<string,*>=} options Options
+ * @constructor
+ * @extends ProtoBuf.Reflect.T
+ */
+ var Method = function (builder, svc, name, options) {
+ T.call(this, builder, svc, name);
+
+ /**
+ * @override
+ */
+ this.className = "Service.Method";
+
+ /**
+ * Options.
+ * @type {Object.<string, *>}
+ * @expose
+ */
+ this.options = options || {};
+ };
+
+ /**
+ * @alias ProtoBuf.Reflect.Service.Method.prototype
+ * @inner
+ */
+ var MethodPrototype = Method.prototype = Object.create(T.prototype);
+
+ /**
+ * Builds the method's '$options' property.
+ * @name ProtoBuf.Reflect.Service.Method#buildOpt
+ * @function
+ * @return {Object.<string,*>}
+ */
+ MethodPrototype.buildOpt = NamespacePrototype.buildOpt;
+
+ /**
+ * @alias ProtoBuf.Reflect.Service.Method
+ * @expose
+ */
+ Reflect.Service.Method = Method;
+
+ /**
+ * RPC service method.
+ * @exports ProtoBuf.Reflect.Service.RPCMethod
+ * @param {!ProtoBuf.Builder} builder Builder reference
+ * @param {!ProtoBuf.Reflect.Service} svc Service
+ * @param {string} name Method name
+ * @param {string} request Request message name
+ * @param {string} response Response message name
+ * @param {boolean} request_stream Whether requests are streamed
+ * @param {boolean} response_stream Whether responses are streamed
+ * @param {Object.<string,*>=} options Options
+ * @constructor
+ * @extends ProtoBuf.Reflect.Service.Method
+ */
+ var RPCMethod = function (builder, svc, name, request, response, request_stream, response_stream, options) {
+ Method.call(this, builder, svc, name, options);
+
+ /**
+ * @override
+ */
+ this.className = "Service.RPCMethod";
+
+ /**
+ * Request message name.
+ * @type {string}
+ * @expose
+ */
+ this.requestName = request;
+
+ /**
+ * Response message name.
+ * @type {string}
+ * @expose
+ */
+ this.responseName = response;
+
+ /**
+ * Whether requests are streamed
+ * @type {bool}
+ * @expose
+ */
+ this.requestStream = request_stream;
+
+ /**
+ * Whether responses are streamed
+ * @type {bool}
+ * @expose
+ */
+ this.responseStream = response_stream;
+
+ /**
+ * Resolved request message type.
+ * @type {ProtoBuf.Reflect.Message}
+ * @expose
+ */
+ this.resolvedRequestType = null;
+
+ /**
+ * Resolved response message type.
+ * @type {ProtoBuf.Reflect.Message}
+ * @expose
+ */
+ this.resolvedResponseType = null;
+ };
+
+ // Extends Method
+ RPCMethod.prototype = Object.create(Method.prototype);
+
+ /**
+ * @alias ProtoBuf.Reflect.Service.RPCMethod
+ * @expose
+ */
+ Reflect.Service.RPCMethod = RPCMethod;
+
+ return Reflect;
+
+ })(ProtoBuf);
+
+ /**
+ * @alias ProtoBuf.Builder
+ * @expose
+ */
+ ProtoBuf.Builder = (function (ProtoBuf, Lang, Reflect) {
+ "use strict";
+
+ /**
+ * Constructs a new Builder.
+ * @exports ProtoBuf.Builder
+ * @class Provides the functionality to build protocol messages.
+ * @param {Object.<string,*>=} options Options
+ * @constructor
+ */
+ var Builder = function (options) {
+
+ /**
+ * Namespace.
+ * @type {ProtoBuf.Reflect.Namespace}
+ * @expose
+ */
+ this.ns = new Reflect.Namespace(this, null, ""); // Global namespace
+
+ /**
+ * Namespace pointer.
+ * @type {ProtoBuf.Reflect.T}
+ * @expose
+ */
+ this.ptr = this.ns;
+
+ /**
+ * Resolved flag.
+ * @type {boolean}
+ * @expose
+ */
+ this.resolved = false;
+
+ /**
+ * The current building result.
+ * @type {Object.<string,ProtoBuf.Builder.Message|Object>|null}
+ * @expose
+ */
+ this.result = null;
+
+ /**
+ * Imported files.
+ * @type {Array.<string>}
+ * @expose
+ */
+ this.files = {};
+
+ /**
+ * Import root override.
+ * @type {?string}
+ * @expose
+ */
+ this.importRoot = null;
+
+ /**
+ * Options.
+ * @type {!Object.<string, *>}
+ * @expose
+ */
+ this.options = options || {};
+ };
+
+ /**
+ * @alias ProtoBuf.Builder.prototype
+ * @inner
+ */
+ var BuilderPrototype = Builder.prototype;
+
+ // ----- Definition tests -----
+
+ /**
+ * Tests if a definition most likely describes a message.
+ * @param {!Object} def
+ * @returns {boolean}
+ * @expose
+ */
+ Builder.isMessage = function (def) {
+ // Messages require a string name
+ if (typeof def["name"] !== 'string')
+ return false;
+ // Messages do not contain values (enum) or rpc methods (service)
+ if (typeof def["values"] !== 'undefined' || typeof def["rpc"] !== 'undefined')
+ return false;
+ return true;
+ };
+
+ /**
+ * Tests if a definition most likely describes a message field.
+ * @param {!Object} def
+ * @returns {boolean}
+ * @expose
+ */
+ Builder.isMessageField = function (def) {
+ // Message fields require a string rule, name and type and an id
+ if (typeof def["rule"] !== 'string' || typeof def["name"] !== 'string' || typeof def["type"] !== 'string' || typeof def["id"] === 'undefined')
+ return false;
+ return true;
+ };
+
+ /**
+ * Tests if a definition most likely describes an enum.
+ * @param {!Object} def
+ * @returns {boolean}
+ * @expose
+ */
+ Builder.isEnum = function (def) {
+ // Enums require a string name
+ if (typeof def["name"] !== 'string')
+ return false;
+ // Enums require at least one value
+ if (typeof def["values"] === 'undefined' || !Array.isArray(def["values"]) || def["values"].length === 0)
+ return false;
+ return true;
+ };
+
+ /**
+ * Tests if a definition most likely describes a service.
+ * @param {!Object} def
+ * @returns {boolean}
+ * @expose
+ */
+ Builder.isService = function (def) {
+ // Services require a string name and an rpc object
+ if (typeof def["name"] !== 'string' || typeof def["rpc"] !== 'object' || !def["rpc"])
+ return false;
+ return true;
+ };
+
+ /**
+ * Tests if a definition most likely describes an extended message
+ * @param {!Object} def
+ * @returns {boolean}
+ * @expose
+ */
+ Builder.isExtend = function (def) {
+ // Extends rquire a string ref
+ if (typeof def["ref"] !== 'string')
+ return false;
+ return true;
+ };
+
+ // ----- Building -----
+
+ /**
+ * Resets the pointer to the root namespace.
+ * @returns {!ProtoBuf.Builder} this
+ * @expose
+ */
+ BuilderPrototype.reset = function () {
+ this.ptr = this.ns;
+ return this;
+ };
+
+ /**
+ * Defines a namespace on top of the current pointer position and places the pointer on it.
+ * @param {string} namespace
+ * @return {!ProtoBuf.Builder} this
+ * @expose
+ */
+ BuilderPrototype.define = function (namespace) {
+ if (typeof namespace !== 'string' || !Lang.TYPEREF.test(namespace))
+ throw Error("illegal namespace: " + namespace);
+ namespace.split(".").forEach(function (part) {
+ var ns = this.ptr.getChild(part);
+ if (ns === null) // Keep existing
+ this.ptr.addChild(ns = new Reflect.Namespace(this, this.ptr, part));
+ this.ptr = ns;
+ }, this);
+ return this;
+ };
+
+ /**
+ * Creates the specified definitions at the current pointer position.
+ * @param {!Array.<!Object>} defs Messages, enums or services to create
+ * @returns {!ProtoBuf.Builder} this
+ * @throws {Error} If a message definition is invalid
+ * @expose
+ */
+ BuilderPrototype.create = function (defs) {
+ if (!defs)
+ return this; // Nothing to create
+ if (!Array.isArray(defs))
+ defs = [defs];
+ else {
+ if (defs.length === 0)
+ return this;
+ defs = defs.slice();
+ }
+
+ // It's quite hard to keep track of scopes and memory here, so let's do this iteratively.
+ var stack = [defs];
+ while (stack.length > 0) {
+ defs = stack.pop();
+
+ if (!Array.isArray(defs)) // Stack always contains entire namespaces
+ throw Error("not a valid namespace: " + JSON.stringify(defs));
+
+ while (defs.length > 0) {
+ var def = defs.shift(); // Namespaces always contain an array of messages, enums and services
+
+ if (Builder.isMessage(def)) {
+ var obj = new Reflect.Message(this, this.ptr, def["name"], def["options"], def["isGroup"], def["syntax"]);
+
+ // Create OneOfs
+ var oneofs = {};
+ if (def["oneofs"])
+ Object.keys(def["oneofs"]).forEach(function (name) {
+ obj.addChild(oneofs[name] = new Reflect.Message.OneOf(this, obj, name));
+ }, this);
+
+ // Create fields
+ if (def["fields"])
+ def["fields"].forEach(function (fld) {
+ if (obj.getChild(fld["id"] | 0) !== null)
+ throw Error("duplicate or invalid field id in " + obj.name + ": " + fld['id']);
+ if (fld["options"] && typeof fld["options"] !== 'object')
+ throw Error("illegal field options in " + obj.name + "#" + fld["name"]);
+ var oneof = null;
+ if (typeof fld["oneof"] === 'string' && !(oneof = oneofs[fld["oneof"]]))
+ throw Error("illegal oneof in " + obj.name + "#" + fld["name"] + ": " + fld["oneof"]);
+ fld = new Reflect.Message.Field(this, obj, fld["rule"], fld["keytype"], fld["type"], fld["name"], fld["id"], fld["options"], oneof, def["syntax"]);
+ if (oneof)
+ oneof.fields.push(fld);
+ obj.addChild(fld);
+ }, this);
+
+ // Push children to stack
+ var subObj = [];
+ if (def["enums"])
+ def["enums"].forEach(function (enm) {
+ subObj.push(enm);
+ });
+ if (def["messages"])
+ def["messages"].forEach(function (msg) {
+ subObj.push(msg);
+ });
+ if (def["services"])
+ def["services"].forEach(function (svc) {
+ subObj.push(svc);
+ });
+
+ // Set extension ranges
+ if (def["extensions"]) {
+ if (typeof def["extensions"][0] === 'number') // pre 5.0.1
+ obj.extensions = [def["extensions"]];
+ else
+ obj.extensions = def["extensions"];
+ }
+
+ // Create on top of current namespace
+ this.ptr.addChild(obj);
+ if (subObj.length > 0) {
+ stack.push(defs); // Push the current level back
+ defs = subObj; // Continue processing sub level
+ subObj = null;
+ this.ptr = obj; // And move the pointer to this namespace
+ obj = null;
+ continue;
+ }
+ subObj = null;
+
+ } else if (Builder.isEnum(def)) {
+
+ obj = new Reflect.Enum(this, this.ptr, def["name"], def["options"], def["syntax"]);
+ def["values"].forEach(function (val) {
+ obj.addChild(new Reflect.Enum.Value(this, obj, val["name"], val["id"]));
+ }, this);
+ this.ptr.addChild(obj);
+
+ } else if (Builder.isService(def)) {
+
+ obj = new Reflect.Service(this, this.ptr, def["name"], def["options"]);
+ Object.keys(def["rpc"]).forEach(function (name) {
+ var mtd = def["rpc"][name];
+ obj.addChild(new Reflect.Service.RPCMethod(this, obj, name, mtd["request"], mtd["response"], !!mtd["request_stream"], !!mtd["response_stream"], mtd["options"]));
+ }, this);
+ this.ptr.addChild(obj);
+
+ } else if (Builder.isExtend(def)) {
+
+ obj = this.ptr.resolve(def["ref"], true);
+ if (obj) {
+ def["fields"].forEach(function (fld) {
+ if (obj.getChild(fld['id'] | 0) !== null)
+ throw Error("duplicate extended field id in " + obj.name + ": " + fld['id']);
+ // Check if field id is allowed to be extended
+ if (obj.extensions) {
+ var valid = false;
+ obj.extensions.forEach(function (range) {
+ if (fld["id"] >= range[0] && fld["id"] <= range[1])
+ valid = true;
+ });
+ if (!valid)
+ throw Error("illegal extended field id in " + obj.name + ": " + fld['id'] + " (not within valid ranges)");
+ }
+ // Convert extension field names to camel case notation if the override is set
+ var name = fld["name"];
+ if (this.options['convertFieldsToCamelCase'])
+ name = ProtoBuf.Util.toCamelCase(name);
+ // see #161: Extensions use their fully qualified name as their runtime key and...
+ var field = new Reflect.Message.ExtensionField(this, obj, fld["rule"], fld["type"], this.ptr.fqn() + '.' + name, fld["id"], fld["options"]);
+ // ...are added on top of the current namespace as an extension which is used for
+ // resolving their type later on (the extension always keeps the original name to
+ // prevent naming collisions)
+ var ext = new Reflect.Extension(this, this.ptr, fld["name"], field);
+ field.extension = ext;
+ this.ptr.addChild(ext);
+ obj.addChild(field);
+ }, this);
+
+ } else if (!/\.?google\.protobuf\./.test(def["ref"])) // Silently skip internal extensions
+ throw Error("extended message " + def["ref"] + " is not defined");
+
+ } else
+ throw Error("not a valid definition: " + JSON.stringify(def));
+
+ def = null;
+ obj = null;
+ }
+ // Break goes here
+ defs = null;
+ this.ptr = this.ptr.parent; // Namespace done, continue at parent
+ }
+ this.resolved = false; // Require re-resolve
+ this.result = null; // Require re-build
+ return this;
+ };
+
+ /**
+ * Propagates syntax to all children.
+ * @param {!Object} parent
+ * @inner
+ */
+ function propagateSyntax(parent) {
+ if (parent['messages']) {
+ parent['messages'].forEach(function (child) {
+ child["syntax"] = parent["syntax"];
+ propagateSyntax(child);
+ });
+ }
+ if (parent['enums']) {
+ parent['enums'].forEach(function (child) {
+ child["syntax"] = parent["syntax"];
+ });
+ }
+ }
+
+ /**
+ * Imports another definition into this builder.
+ * @param {Object.<string,*>} json Parsed import
+ * @param {(string|{root: string, file: string})=} filename Imported file name
+ * @returns {!ProtoBuf.Builder} this
+ * @throws {Error} If the definition or file cannot be imported
+ * @expose
+ */
+ BuilderPrototype["import"] = function (json, filename) {
+ var delim = '/';
+
+ // Make sure to skip duplicate imports
+
+ if (typeof filename === 'string') {
+
+ if (ProtoBuf.Util.IS_NODE)
+ filename = __webpack_require__(32)['resolve'](filename);
+ if (this.files[filename] === true)
+ return this.reset();
+ this.files[filename] = true;
+
+ } else if (typeof filename === 'object') { // Object with root, file.
+
+ var root = filename.root;
+ if (ProtoBuf.Util.IS_NODE)
+ root = __webpack_require__(32)['resolve'](root);
+ if (root.indexOf("\\") >= 0 || filename.file.indexOf("\\") >= 0)
+ delim = '\\';
+ var fname = root + delim + filename.file;
+ if (this.files[fname] === true)
+ return this.reset();
+ this.files[fname] = true;
+ }
+
+ // Import imports
+
+ if (json['imports'] && json['imports'].length > 0) {
+ var importRoot,
+ resetRoot = false;
+
+ if (typeof filename === 'object') { // If an import root is specified, override
+
+ this.importRoot = filename["root"];
+ resetRoot = true; // ... and reset afterwards
+ importRoot = this.importRoot;
+ filename = filename["file"];
+ if (importRoot.indexOf("\\") >= 0 || filename.indexOf("\\") >= 0)
+ delim = '\\';
+
+ } else if (typeof filename === 'string') {
+
+ if (this.importRoot) // If import root is overridden, use it
+ importRoot = this.importRoot;
+ else { // Otherwise compute from filename
+ if (filename.indexOf("/") >= 0) { // Unix
+ importRoot = filename.replace(/\/[^\/]*$/, "");
+ if ( /* /file.proto */ importRoot === "")
+ importRoot = "/";
+ } else if (filename.indexOf("\\") >= 0) { // Windows
+ importRoot = filename.replace(/\\[^\\]*$/, "");
+ delim = '\\';
+ } else
+ importRoot = ".";
+ }
+
+ } else
+ importRoot = null;
+
+ for (var i = 0; i < json['imports'].length; i++) {
+ if (typeof json['imports'][i] === 'string') { // Import file
+ if (!importRoot)
+ throw Error("cannot determine import root");
+ var importFilename = json['imports'][i];
+ if (importFilename === "google/protobuf/descriptor.proto")
+ continue; // Not needed and therefore not used
+ importFilename = importRoot + delim + importFilename;
+ if (this.files[importFilename] === true)
+ continue; // Already imported
+ if (/\.proto$/i.test(importFilename) && !ProtoBuf.DotProto) // If this is a light build
+ importFilename = importFilename.replace(/\.proto$/, ".json"); // always load the JSON file
+ var contents = ProtoBuf.Util.fetch(importFilename);
+ if (contents === null)
+ throw Error("failed to import '" + importFilename + "' in '" + filename + "': file not found");
+ if (/\.json$/i.test(importFilename)) // Always possible
+ this["import"](JSON.parse(contents + ""), importFilename); // May throw
+ else
+ this["import"](ProtoBuf.DotProto.Parser.parse(contents), importFilename); // May throw
+ } else // Import structure
+ if (!filename)
+ this["import"](json['imports'][i]);
+ else if (/\.(\w+)$/.test(filename)) // With extension: Append _importN to the name portion to make it unique
+ this["import"](json['imports'][i], filename.replace(/^(.+)\.(\w+)$/, function ($0, $1, $2) {
+ return $1 + "_import" + i + "." + $2;
+ }));
+ else // Without extension: Append _importN to make it unique
+ this["import"](json['imports'][i], filename + "_import" + i);
+ }
+ if (resetRoot) // Reset import root override when all imports are done
+ this.importRoot = null;
+ }
+
+ // Import structures
+
+ if (json['package'])
+ this.define(json['package']);
+ if (json['syntax'])
+ propagateSyntax(json);
+ var base = this.ptr;
+ if (json['options'])
+ Object.keys(json['options']).forEach(function (key) {
+ base.options[key] = json['options'][key];
+ });
+ if (json['messages'])
+ this.create(json['messages']),
+ this.ptr = base;
+ if (json['enums'])
+ this.create(json['enums']),
+ this.ptr = base;
+ if (json['services'])
+ this.create(json['services']),
+ this.ptr = base;
+ if (json['extends'])
+ this.create(json['extends']);
+
+ return this.reset();
+ };
+
+ /**
+ * Resolves all namespace objects.
+ * @throws {Error} If a type cannot be resolved
+ * @returns {!ProtoBuf.Builder} this
+ * @expose
+ */
+ BuilderPrototype.resolveAll = function () {
+ // Resolve all reflected objects
+ var res;
+ if (this.ptr == null || typeof this.ptr.type === 'object')
+ return this; // Done (already resolved)
+
+ if (this.ptr instanceof Reflect.Namespace) { // Resolve children
+
+ this.ptr.children.forEach(function (child) {
+ this.ptr = child;
+ this.resolveAll();
+ }, this);
+
+ } else if (this.ptr instanceof Reflect.Message.Field) { // Resolve type
+
+ if (!Lang.TYPE.test(this.ptr.type)) {
+ if (!Lang.TYPEREF.test(this.ptr.type))
+ throw Error("illegal type reference in " + this.ptr.toString(true) + ": " + this.ptr.type);
+ res = (this.ptr instanceof Reflect.Message.ExtensionField ? this.ptr.extension.parent : this.ptr.parent).resolve(this.ptr.type, true);
+ if (!res)
+ throw Error("unresolvable type reference in " + this.ptr.toString(true) + ": " + this.ptr.type);
+ this.ptr.resolvedType = res;
+ if (res instanceof Reflect.Enum) {
+ this.ptr.type = ProtoBuf.TYPES["enum"];
+ if (this.ptr.syntax === 'proto3' && res.syntax !== 'proto3')
+ throw Error("proto3 message cannot reference proto2 enum");
+ } else if (res instanceof Reflect.Message)
+ this.ptr.type = res.isGroup ? ProtoBuf.TYPES["group"] : ProtoBuf.TYPES["message"];
+ else
+ throw Error("illegal type reference in " + this.ptr.toString(true) + ": " + this.ptr.type);
+ } else
+ this.ptr.type = ProtoBuf.TYPES[this.ptr.type];
+
+ // If it's a map field, also resolve the key type. The key type can be only a numeric, string, or bool type
+ // (i.e., no enums or messages), so we don't need to resolve against the current namespace.
+ if (this.ptr.map) {
+ if (!Lang.TYPE.test(this.ptr.keyType))
+ throw Error("illegal key type for map field in " + this.ptr.toString(true) + ": " + this.ptr.keyType);
+ this.ptr.keyType = ProtoBuf.TYPES[this.ptr.keyType];
+ }
+
+ } else if (this.ptr instanceof ProtoBuf.Reflect.Service.Method) {
+
+ if (this.ptr instanceof ProtoBuf.Reflect.Service.RPCMethod) {
+ res = this.ptr.parent.resolve(this.ptr.requestName, true);
+ if (!res || !(res instanceof ProtoBuf.Reflect.Message))
+ throw Error("Illegal type reference in " + this.ptr.toString(true) + ": " + this.ptr.requestName);
+ this.ptr.resolvedRequestType = res;
+ res = this.ptr.parent.resolve(this.ptr.responseName, true);
+ if (!res || !(res instanceof ProtoBuf.Reflect.Message))
+ throw Error("Illegal type reference in " + this.ptr.toString(true) + ": " + this.ptr.responseName);
+ this.ptr.resolvedResponseType = res;
+ } else // Should not happen as nothing else is implemented
+ throw Error("illegal service type in " + this.ptr.toString(true));
+
+ } else if (!(this.ptr instanceof ProtoBuf.Reflect.Message.OneOf) && // Not built
+ !(this.ptr instanceof ProtoBuf.Reflect.Extension) && // Not built
+ !(this.ptr instanceof ProtoBuf.Reflect.Enum.Value) // Built in enum
+ )
+ throw Error("illegal object in namespace: " + typeof (this.ptr) + ": " + this.ptr);
+
+ return this.reset();
+ };
+
+ /**
+ * Builds the protocol. This will first try to resolve all definitions and, if this has been successful,
+ * return the built package.
+ * @param {(string|Array.<string>)=} path Specifies what to return. If omitted, the entire namespace will be returned.
+ * @returns {!ProtoBuf.Builder.Message|!Object.<string,*>}
+ * @throws {Error} If a type could not be resolved
+ * @expose
+ */
+ BuilderPrototype.build = function (path) {
+ this.reset();
+ if (!this.resolved)
+ this.resolveAll(),
+ this.resolved = true,
+ this.result = null; // Require re-build
+ if (this.result === null) // (Re-)Build
+ this.result = this.ns.build();
+ if (!path)
+ return this.result;
+ var part = typeof path === 'string' ? path.split(".") : path,
+ ptr = this.result; // Build namespace pointer (no hasChild etc.)
+ for (var i = 0; i < part.length; i++)
+ if (ptr[part[i]])
+ ptr = ptr[part[i]];
+ else {
+ ptr = null;
+ break;
+ }
+ return ptr;
+ };
+
+ /**
+ * Similar to {@link ProtoBuf.Builder#build}, but looks up the internal reflection descriptor.
+ * @param {string=} path Specifies what to return. If omitted, the entire namespace wiil be returned.
+ * @param {boolean=} excludeNonNamespace Excludes non-namespace types like fields, defaults to `false`
+ * @returns {?ProtoBuf.Reflect.T} Reflection descriptor or `null` if not found
+ */
+ BuilderPrototype.lookup = function (path, excludeNonNamespace) {
+ return path ? this.ns.resolve(path, excludeNonNamespace) : this.ns;
+ };
+
+ /**
+ * Returns a string representation of this object.
+ * @return {string} String representation as of "Builder"
+ * @expose
+ */
+ BuilderPrototype.toString = function () {
+ return "Builder";
+ };
+
+ // ----- Base classes -----
+ // Exist for the sole purpose of being able to "... instanceof ProtoBuf.Builder.Message" etc.
+
+ /**
+ * @alias ProtoBuf.Builder.Message
+ */
+ Builder.Message = function () {};
+
+ /**
+ * @alias ProtoBuf.Builder.Enum
+ */
+ Builder.Enum = function () {};
+
+ /**
+ * @alias ProtoBuf.Builder.Message
+ */
+ Builder.Service = function () {};
+
+ return Builder;
+
+ })(ProtoBuf, ProtoBuf.Lang, ProtoBuf.Reflect);
+
+ /**
+ * @alias ProtoBuf.Map
+ * @expose
+ */
+ ProtoBuf.Map = (function (ProtoBuf, Reflect) {
+ "use strict";
+
+ /**
+ * Constructs a new Map. A Map is a container that is used to implement map
+ * fields on message objects. It closely follows the ES6 Map API; however,
+ * it is distinct because we do not want to depend on external polyfills or
+ * on ES6 itself.
+ *
+ * @exports ProtoBuf.Map
+ * @param {!ProtoBuf.Reflect.Field} field Map field
+ * @param {Object.<string,*>=} contents Initial contents
+ * @constructor
+ */
+ var Map = function (field, contents) {
+ if (!field.map)
+ throw Error("field is not a map");
+
+ /**
+ * The field corresponding to this map.
+ * @type {!ProtoBuf.Reflect.Field}
+ */
+ this.field = field;
+
+ /**
+ * Element instance corresponding to key type.
+ * @type {!ProtoBuf.Reflect.Element}
+ */
+ this.keyElem = new Reflect.Element(field.keyType, null, true, field.syntax);
+
+ /**
+ * Element instance corresponding to value type.
+ * @type {!ProtoBuf.Reflect.Element}
+ */
+ this.valueElem = new Reflect.Element(field.type, field.resolvedType, false, field.syntax);
+
+ /**
+ * Internal map: stores mapping of (string form of key) -> (key, value)
+ * pair.
+ *
+ * We provide map semantics for arbitrary key types, but we build on top
+ * of an Object, which has only string keys. In order to avoid the need
+ * to convert a string key back to its native type in many situations,
+ * we store the native key value alongside the value. Thus, we only need
+ * a one-way mapping from a key type to its string form that guarantees
+ * uniqueness and equality (i.e., str(K1) === str(K2) if and only if K1
+ * === K2).
+ *
+ * @type {!Object<string, {key: *, value: *}>}
+ */
+ this.map = {};
+
+ /**
+ * Returns the number of elements in the map.
+ */
+ Object.defineProperty(this, "size", {
+ get: function () {
+ return Object.keys(this.map).length;
+ }
+ });
+
+ // Fill initial contents from a raw object.
+ if (contents) {
+ var keys = Object.keys(contents);
+ for (var i = 0; i < keys.length; i++) {
+ var key = this.keyElem.valueFromString(keys[i]);
+ var val = this.valueElem.verifyValue(contents[keys[i]]);
+ this.map[this.keyElem.valueToString(key)] = { key: key, value: val };
+ }
+ }
+ };
+
+ var MapPrototype = Map.prototype;
+
+ /**
+ * Helper: return an iterator over an array.
+ * @param {!Array<*>} arr the array
+ * @returns {!Object} an iterator
+ * @inner
+ */
+ function arrayIterator(arr) {
+ var idx = 0;
+ return {
+ next: function () {
+ if (idx < arr.length)
+ return { done: false, value: arr[idx++] };
+ return { done: true };
+ }
+ }
+ }
+
+ /**
+ * Clears the map.
+ */
+ MapPrototype.clear = function () {
+ this.map = {};
+ };
+
+ /**
+ * Deletes a particular key from the map.
+ * @returns {boolean} Whether any entry with this key was deleted.
+ */
+ MapPrototype["delete"] = function (key) {
+ var keyValue = this.keyElem.valueToString(this.keyElem.verifyValue(key));
+ var hadKey = keyValue in this.map;
+ delete this.map[keyValue];
+ return hadKey;
+ };
+
+ /**
+ * Returns an iterator over [key, value] pairs in the map.
+ * @returns {Object} The iterator
+ */
+ MapPrototype.entries = function () {
+ var entries = [];
+ var strKeys = Object.keys(this.map);
+ for (var i = 0, entry; i < strKeys.length; i++)
+ entries.push([(entry = this.map[strKeys[i]]).key, entry.value]);
+ return arrayIterator(entries);
+ };
+
+ /**
+ * Returns an iterator over keys in the map.
+ * @returns {Object} The iterator
+ */
+ MapPrototype.keys = function () {
+ var keys = [];
+ var strKeys = Object.keys(this.map);
+ for (var i = 0; i < strKeys.length; i++)
+ keys.push(this.map[strKeys[i]].key);
+ return arrayIterator(keys);
+ };
+
+ /**
+ * Returns an iterator over values in the map.
+ * @returns {!Object} The iterator
+ */
+ MapPrototype.values = function () {
+ var values = [];
+ var strKeys = Object.keys(this.map);
+ for (var i = 0; i < strKeys.length; i++)
+ values.push(this.map[strKeys[i]].value);
+ return arrayIterator(values);
+ };
+
+ /**
+ * Iterates over entries in the map, calling a function on each.
+ * @param {function(this:*, *, *, *)} cb The callback to invoke with value, key, and map arguments.
+ * @param {Object=} thisArg The `this` value for the callback
+ */
+ MapPrototype.forEach = function (cb, thisArg) {
+ var strKeys = Object.keys(this.map);
+ for (var i = 0, entry; i < strKeys.length; i++)
+ cb.call(thisArg, (entry = this.map[strKeys[i]]).value, entry.key, this);
+ };
+
+ /**
+ * Sets a key in the map to the given value.
+ * @param {*} key The key
+ * @param {*} value The value
+ * @returns {!ProtoBuf.Map} The map instance
+ */
+ MapPrototype.set = function (key, value) {
+ var keyValue = this.keyElem.verifyValue(key);
+ var valValue = this.valueElem.verifyValue(value);
+ this.map[this.keyElem.valueToString(keyValue)] = { key: keyValue, value: valValue };
+ return this;
+ };
+
+ /**
+ * Gets the value corresponding to a key in the map.
+ * @param {*} key The key
+ * @returns {*|undefined} The value, or `undefined` if key not present
+ */
+ MapPrototype.get = function (key) {
+ var keyValue = this.keyElem.valueToString(this.keyElem.verifyValue(key));
+ if (!(keyValue in this.map))
+ return undefined;
+ return this.map[keyValue].value;
+ };
+
+ /**
+ * Determines whether the given key is present in the map.
+ * @param {*} key The key
+ * @returns {boolean} `true` if the key is present
+ */
+ MapPrototype.has = function (key) {
+ var keyValue = this.keyElem.valueToString(this.keyElem.verifyValue(key));
+ return (keyValue in this.map);
+ };
+
+ return Map;
+ })(ProtoBuf, ProtoBuf.Reflect);
+
+ /**
+ * Loads a .proto string and returns the Builder.
+ * @param {string} proto .proto file contents
+ * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
+ * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
+ * @return {ProtoBuf.Builder} Builder to create new messages
+ * @throws {Error} If the definition cannot be parsed or built
+ * @expose
+ */
+ ProtoBuf.loadProto = function (proto, builder, filename) {
+ if (typeof builder === 'string' || (builder && typeof builder["file"] === 'string' && typeof builder["root"] === 'string'))
+ filename = builder,
+ builder = undefined;
+ return ProtoBuf.loadJson(ProtoBuf.DotProto.Parser.parse(proto), builder, filename);
+ };
+
+ /**
+ * Loads a .proto string and returns the Builder. This is an alias of {@link ProtoBuf.loadProto}.
+ * @function
+ * @param {string} proto .proto file contents
+ * @param {(ProtoBuf.Builder|string)=} builder Builder to append to. Will create a new one if omitted.
+ * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
+ * @return {ProtoBuf.Builder} Builder to create new messages
+ * @throws {Error} If the definition cannot be parsed or built
+ * @expose
+ */
+ ProtoBuf.protoFromString = ProtoBuf.loadProto; // Legacy
+
+ /**
+ * Loads a .proto file and returns the Builder.
+ * @param {string|{root: string, file: string}} filename Path to proto file or an object specifying 'file' with
+ * an overridden 'root' path for all imported files.
+ * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
+ * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
+ * file will be read synchronously and this function will return the Builder.
+ * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
+ * @return {?ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
+ * request has failed), else undefined
+ * @expose
+ */
+ ProtoBuf.loadProtoFile = function (filename, callback, builder) {
+ if (callback && typeof callback === 'object')
+ builder = callback,
+ callback = null;
+ else if (!callback || typeof callback !== 'function')
+ callback = null;
+ if (callback)
+ return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"] + "/" + filename["file"], function (contents) {
+ if (contents === null) {
+ callback(Error("Failed to fetch file"));
+ return;
+ }
+ try {
+ callback(null, ProtoBuf.loadProto(contents, builder, filename));
+ } catch (e) {
+ callback(e);
+ }
+ });
+ var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"] + "/" + filename["file"] : filename);
+ return contents === null ? null : ProtoBuf.loadProto(contents, builder, filename);
+ };
+
+ /**
+ * Loads a .proto file and returns the Builder. This is an alias of {@link ProtoBuf.loadProtoFile}.
+ * @function
+ * @param {string|{root: string, file: string}} filename Path to proto file or an object specifying 'file' with
+ * an overridden 'root' path for all imported files.
+ * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
+ * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
+ * file will be read synchronously and this function will return the Builder.
+ * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
+ * @return {!ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
+ * request has failed), else undefined
+ * @expose
+ */
+ ProtoBuf.protoFromFile = ProtoBuf.loadProtoFile; // Legacy
+
+ /**
+ * Constructs a new empty Builder.
+ * @param {Object.<string,*>=} options Builder options, defaults to global options set on ProtoBuf
+ * @return {!ProtoBuf.Builder} Builder
+ * @expose
+ */
+ ProtoBuf.newBuilder = function (options) {
+ options = options || {};
+ if (typeof options['convertFieldsToCamelCase'] === 'undefined')
+ options['convertFieldsToCamelCase'] = ProtoBuf.convertFieldsToCamelCase;
+ if (typeof options['populateAccessors'] === 'undefined')
+ options['populateAccessors'] = ProtoBuf.populateAccessors;
+ return new ProtoBuf.Builder(options);
+ };
+
+ /**
+ * Loads a .json definition and returns the Builder.
+ * @param {!*|string} json JSON definition
+ * @param {(ProtoBuf.Builder|string|{root: string, file: string})=} builder Builder to append to. Will create a new one if omitted.
+ * @param {(string|{root: string, file: string})=} filename The corresponding file name if known. Must be specified for imports.
+ * @return {ProtoBuf.Builder} Builder to create new messages
+ * @throws {Error} If the definition cannot be parsed or built
+ * @expose
+ */
+ ProtoBuf.loadJson = function (json, builder, filename) {
+ if (typeof builder === 'string' || (builder && typeof builder["file"] === 'string' && typeof builder["root"] === 'string'))
+ filename = builder,
+ builder = null;
+ if (!builder || typeof builder !== 'object')
+ builder = ProtoBuf.newBuilder();
+ if (typeof json === 'string')
+ json = JSON.parse(json);
+ builder["import"](json, filename);
+ builder.resolveAll();
+ return builder;
+ };
+
+ /**
+ * Loads a .json file and returns the Builder.
+ * @param {string|!{root: string, file: string}} filename Path to json file or an object specifying 'file' with
+ * an overridden 'root' path for all imported files.
+ * @param {function(?Error, !ProtoBuf.Builder=)=} callback Callback that will receive `null` as the first and
+ * the Builder as its second argument on success, otherwise the error as its first argument. If omitted, the
+ * file will be read synchronously and this function will return the Builder.
+ * @param {ProtoBuf.Builder=} builder Builder to append to. Will create a new one if omitted.
+ * @return {?ProtoBuf.Builder|undefined} The Builder if synchronous (no callback specified, will be NULL if the
+ * request has failed), else undefined
+ * @expose
+ */
+ ProtoBuf.loadJsonFile = function (filename, callback, builder) {
+ if (callback && typeof callback === 'object')
+ builder = callback,
+ callback = null;
+ else if (!callback || typeof callback !== 'function')
+ callback = null;
+ if (callback)
+ return ProtoBuf.Util.fetch(typeof filename === 'string' ? filename : filename["root"] + "/" + filename["file"], function (contents) {
+ if (contents === null) {
+ callback(Error("Failed to fetch file"));
+ return;
+ }
+ try {
+ callback(null, ProtoBuf.loadJson(JSON.parse(contents), builder, filename));
+ } catch (e) {
+ callback(e);
+ }
+ });
+ var contents = ProtoBuf.Util.fetch(typeof filename === 'object' ? filename["root"] + "/" + filename["file"] : filename);
+ return contents === null ? null : ProtoBuf.loadJson(JSON.parse(contents), builder, filename);
+ };
+
+ return ProtoBuf;
+ });
+
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(27), __webpack_require__(12)(module)))
+
+/***/ },
+/* 27 */
+/***/ function(module, exports) {
+
+ // shim for using process in browser
+ var process = module.exports = {};
+
+ // cached from whatever global is present so that test runners that stub it
+ // don't break things. But we need to wrap it in a try catch in case it is
+ // wrapped in strict mode code which doesn't define any globals. It's inside a
+ // function because try/catches deoptimize in certain engines.
+
+ var cachedSetTimeout;
+ var cachedClearTimeout;
+
+ function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+ }
+ function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+ }
+ (function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } ())
+ function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+ }
+ function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+ }
+ var queue = [];
+ var draining = false;
+ var currentQueue;
+ var queueIndex = -1;
+
+ function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+ }
+
+ function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+ }
+
+ process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+ };
+
+ // v8 likes predictible objects
+ function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+ }
+ Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+ };
+ process.title = 'browser';
+ process.browser = true;
+ process.env = {};
+ process.argv = [];
+ process.version = ''; // empty string to avoid regexp issues
+ process.versions = {};
+
+ function noop() {}
+
+ process.on = noop;
+ process.addListener = noop;
+ process.once = noop;
+ process.off = noop;
+ process.removeListener = noop;
+ process.removeAllListeners = noop;
+ process.emit = noop;
+
+ process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+ };
+
+ process.cwd = function () { return '/' };
+ process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+ };
+ process.umask = function() { return 0; };
+
+
+/***/ },
+/* 28 */
+/***/ function(module, exports) {
+
+ module.exports = function() { throw new Error("define cannot be used indirect"); };
+
+
+/***/ },
+/* 29 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module) {/*
+ Copyright 2013-2014 Daniel Wirtz <dcode@dcode.io>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+ /**
+ * @license bytebuffer.js (c) 2015 Daniel Wirtz <dcode@dcode.io>
+ * Backing buffer: ArrayBuffer, Accessor: Uint8Array
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/bytebuffer.js for details
+ */
+ (function(global, factory) {
+
+ /* AMD */ if ("function" === 'function' && __webpack_require__(28)["amd"])
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(30)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ /* CommonJS */ else if ("function" === 'function' && typeof module === "object" && module && module["exports"])
+ module['exports'] = (function() {
+ var Long; try { Long = __webpack_require__(30); } catch (e) {}
+ return factory(Long);
+ })();
+ /* Global */ else
+ (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = factory(global["dcodeIO"]["Long"]);
+
+ })(this, function(Long) {
+ "use strict";
+
+ /**
+ * Constructs a new ByteBuffer.
+ * @class The swiss army knife for binary data in JavaScript.
+ * @exports ByteBuffer
+ * @constructor
+ * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @expose
+ */
+ var ByteBuffer = function(capacity, littleEndian, noAssert) {
+ if (typeof capacity === 'undefined')
+ capacity = ByteBuffer.DEFAULT_CAPACITY;
+ if (typeof littleEndian === 'undefined')
+ littleEndian = ByteBuffer.DEFAULT_ENDIAN;
+ if (typeof noAssert === 'undefined')
+ noAssert = ByteBuffer.DEFAULT_NOASSERT;
+ if (!noAssert) {
+ capacity = capacity | 0;
+ if (capacity < 0)
+ throw RangeError("Illegal capacity");
+ littleEndian = !!littleEndian;
+ noAssert = !!noAssert;
+ }
+
+ /**
+ * Backing ArrayBuffer.
+ * @type {!ArrayBuffer}
+ * @expose
+ */
+ this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity);
+
+ /**
+ * Uint8Array utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`.
+ * @type {?Uint8Array}
+ * @expose
+ */
+ this.view = capacity === 0 ? null : new Uint8Array(this.buffer);
+
+ /**
+ * Absolute read/write offset.
+ * @type {number}
+ * @expose
+ * @see ByteBuffer#flip
+ * @see ByteBuffer#clear
+ */
+ this.offset = 0;
+
+ /**
+ * Marked offset.
+ * @type {number}
+ * @expose
+ * @see ByteBuffer#mark
+ * @see ByteBuffer#reset
+ */
+ this.markedOffset = -1;
+
+ /**
+ * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation.
+ * @type {number}
+ * @expose
+ * @see ByteBuffer#flip
+ * @see ByteBuffer#clear
+ */
+ this.limit = capacity;
+
+ /**
+ * Whether to use little endian byte order, defaults to `false` for big endian.
+ * @type {boolean}
+ * @expose
+ */
+ this.littleEndian = littleEndian;
+
+ /**
+ * Whether to skip assertions of offsets and values, defaults to `false`.
+ * @type {boolean}
+ * @expose
+ */
+ this.noAssert = noAssert;
+ };
+
+ /**
+ * ByteBuffer version.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ByteBuffer.VERSION = "5.0.1";
+
+ /**
+ * Little endian constant that can be used instead of its boolean value. Evaluates to `true`.
+ * @type {boolean}
+ * @const
+ * @expose
+ */
+ ByteBuffer.LITTLE_ENDIAN = true;
+
+ /**
+ * Big endian constant that can be used instead of its boolean value. Evaluates to `false`.
+ * @type {boolean}
+ * @const
+ * @expose
+ */
+ ByteBuffer.BIG_ENDIAN = false;
+
+ /**
+ * Default initial capacity of `16`.
+ * @type {number}
+ * @expose
+ */
+ ByteBuffer.DEFAULT_CAPACITY = 16;
+
+ /**
+ * Default endianess of `false` for big endian.
+ * @type {boolean}
+ * @expose
+ */
+ ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN;
+
+ /**
+ * Default no assertions flag of `false`.
+ * @type {boolean}
+ * @expose
+ */
+ ByteBuffer.DEFAULT_NOASSERT = false;
+
+ /**
+ * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded
+ * and int64 support is not available.
+ * @type {?Long}
+ * @const
+ * @see https://github.com/dcodeIO/long.js
+ * @expose
+ */
+ ByteBuffer.Long = Long || null;
+
+ /**
+ * @alias ByteBuffer.prototype
+ * @inner
+ */
+ var ByteBufferPrototype = ByteBuffer.prototype;
+
+ /**
+ * An indicator used to reliably determine if an object is a ByteBuffer or not.
+ * @type {boolean}
+ * @const
+ * @expose
+ * @private
+ */
+ ByteBufferPrototype.__isByteBuffer__;
+
+ Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", {
+ value: true,
+ enumerable: false,
+ configurable: false
+ });
+
+ // helpers
+
+ /**
+ * @type {!ArrayBuffer}
+ * @inner
+ */
+ var EMPTY_BUFFER = new ArrayBuffer(0);
+
+ /**
+ * String.fromCharCode reference for compile-time renaming.
+ * @type {function(...number):string}
+ * @inner
+ */
+ var stringFromCharCode = String.fromCharCode;
+
+ /**
+ * Creates a source function for a string.
+ * @param {string} s String to read from
+ * @returns {function():number|null} Source function returning the next char code respectively `null` if there are
+ * no more characters left.
+ * @throws {TypeError} If the argument is invalid
+ * @inner
+ */
+ function stringSource(s) {
+ var i=0; return function() {
+ return i < s.length ? s.charCodeAt(i++) : null;
+ };
+ }
+
+ /**
+ * Creates a destination function for a string.
+ * @returns {function(number=):undefined|string} Destination function successively called with the next char code.
+ * Returns the final string when called without arguments.
+ * @inner
+ */
+ function stringDestination() {
+ var cs = [], ps = []; return function() {
+ if (arguments.length === 0)
+ return ps.join('')+stringFromCharCode.apply(String, cs);
+ if (cs.length + arguments.length > 1024)
+ ps.push(stringFromCharCode.apply(String, cs)),
+ cs.length = 0;
+ Array.prototype.push.apply(cs, arguments);
+ };
+ }
+
+ /**
+ * Gets the accessor type.
+ * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes)
+ * @expose
+ */
+ ByteBuffer.accessor = function() {
+ return Uint8Array;
+ };
+ /**
+ * Allocates a new ByteBuffer backed by a buffer of the specified capacity.
+ * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}.
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer}
+ * @expose
+ */
+ ByteBuffer.allocate = function(capacity, littleEndian, noAssert) {
+ return new ByteBuffer(capacity, littleEndian, noAssert);
+ };
+
+ /**
+ * Concatenates multiple ByteBuffers into one.
+ * @param {!Array.<!ByteBuffer|!ArrayBuffer|!Uint8Array|string>} buffers Buffers to concatenate
+ * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary",
+ * defaults to "utf8")
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults
+ * to {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} Concatenated ByteBuffer
+ * @expose
+ */
+ ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) {
+ if (typeof encoding === 'boolean' || typeof encoding !== 'string') {
+ noAssert = littleEndian;
+ littleEndian = encoding;
+ encoding = undefined;
+ }
+ var capacity = 0;
+ for (var i=0, k=buffers.length, length; i<k; ++i) {
+ if (!ByteBuffer.isByteBuffer(buffers[i]))
+ buffers[i] = ByteBuffer.wrap(buffers[i], encoding);
+ length = buffers[i].limit - buffers[i].offset;
+ if (length > 0) capacity += length;
+ }
+ if (capacity === 0)
+ return new ByteBuffer(0, littleEndian, noAssert);
+ var bb = new ByteBuffer(capacity, littleEndian, noAssert),
+ bi;
+ i=0; while (i<k) {
+ bi = buffers[i++];
+ length = bi.limit - bi.offset;
+ if (length <= 0) continue;
+ bb.view.set(bi.view.subarray(bi.offset, bi.limit), bb.offset);
+ bb.offset += length;
+ }
+ bb.limit = bb.offset;
+ bb.offset = 0;
+ return bb;
+ };
+
+ /**
+ * Tests if the specified type is a ByteBuffer.
+ * @param {*} bb ByteBuffer to test
+ * @returns {boolean} `true` if it is a ByteBuffer, otherwise `false`
+ * @expose
+ */
+ ByteBuffer.isByteBuffer = function(bb) {
+ return (bb && bb["__isByteBuffer__"]) === true;
+ };
+ /**
+ * Gets the backing buffer type.
+ * @returns {Function} `Buffer` under node.js, `ArrayBuffer` in the browser (classes)
+ * @expose
+ */
+ ByteBuffer.type = function() {
+ return ArrayBuffer;
+ };
+ /**
+ * Wraps a buffer or a string. Sets the allocated ByteBuffer's {@link ByteBuffer#offset} to `0` and its
+ * {@link ByteBuffer#limit} to the length of the wrapped data.
+ * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string|!Array.<number>} buffer Anything that can be wrapped
+ * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to
+ * "utf8")
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer`
+ * @expose
+ */
+ ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) {
+ if (typeof encoding !== 'string') {
+ noAssert = littleEndian;
+ littleEndian = encoding;
+ encoding = undefined;
+ }
+ if (typeof buffer === 'string') {
+ if (typeof encoding === 'undefined')
+ encoding = "utf8";
+ switch (encoding) {
+ case "base64":
+ return ByteBuffer.fromBase64(buffer, littleEndian);
+ case "hex":
+ return ByteBuffer.fromHex(buffer, littleEndian);
+ case "binary":
+ return ByteBuffer.fromBinary(buffer, littleEndian);
+ case "utf8":
+ return ByteBuffer.fromUTF8(buffer, littleEndian);
+ case "debug":
+ return ByteBuffer.fromDebug(buffer, littleEndian);
+ default:
+ throw Error("Unsupported encoding: "+encoding);
+ }
+ }
+ if (buffer === null || typeof buffer !== 'object')
+ throw TypeError("Illegal buffer");
+ var bb;
+ if (ByteBuffer.isByteBuffer(buffer)) {
+ bb = ByteBufferPrototype.clone.call(buffer);
+ bb.markedOffset = -1;
+ return bb;
+ }
+ if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array
+ bb = new ByteBuffer(0, littleEndian, noAssert);
+ if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER
+ bb.buffer = buffer.buffer;
+ bb.offset = buffer.byteOffset;
+ bb.limit = buffer.byteOffset + buffer.byteLength;
+ bb.view = new Uint8Array(buffer.buffer);
+ }
+ } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer
+ bb = new ByteBuffer(0, littleEndian, noAssert);
+ if (buffer.byteLength > 0) {
+ bb.buffer = buffer;
+ bb.offset = 0;
+ bb.limit = buffer.byteLength;
+ bb.view = buffer.byteLength > 0 ? new Uint8Array(buffer) : null;
+ }
+ } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets
+ bb = new ByteBuffer(buffer.length, littleEndian, noAssert);
+ bb.limit = buffer.length;
+ for (var i=0; i<buffer.length; ++i)
+ bb.view[i] = buffer[i];
+ } else
+ throw TypeError("Illegal buffer"); // Otherwise fail
+ return bb;
+ };
+
+ /**
+ * Writes the array as a bitset.
+ * @param {Array<boolean>} value Array of booleans to write
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted.
+ * @returns {!ByteBuffer}
+ * @expose
+ */
+ ByteBufferPrototype.writeBitSet = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (!(value instanceof Array))
+ throw TypeError("Illegal BitSet: Not an array");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+
+ var start = offset,
+ bits = value.length,
+ bytes = (bits >> 3),
+ bit = 0,
+ k;
+
+ offset += this.writeVarint32(bits,offset);
+
+ while(bytes--) {
+ k = (!!value[bit++] & 1) |
+ ((!!value[bit++] & 1) << 1) |
+ ((!!value[bit++] & 1) << 2) |
+ ((!!value[bit++] & 1) << 3) |
+ ((!!value[bit++] & 1) << 4) |
+ ((!!value[bit++] & 1) << 5) |
+ ((!!value[bit++] & 1) << 6) |
+ ((!!value[bit++] & 1) << 7);
+ this.writeByte(k,offset++);
+ }
+
+ if(bit < bits) {
+ var m = 0; k = 0;
+ while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++));
+ this.writeByte(k,offset++);
+ }
+
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ }
+
+ /**
+ * Reads a BitSet as an array of booleans.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted.
+ * @returns {Array<boolean>
+ * @expose
+ */
+ ByteBufferPrototype.readBitSet = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+
+ var ret = this.readVarint32(offset),
+ bits = ret.value,
+ bytes = (bits >> 3),
+ bit = 0,
+ value = [],
+ k;
+
+ offset += ret.length;
+
+ while(bytes--) {
+ k = this.readByte(offset++);
+ value[bit++] = !!(k & 0x01);
+ value[bit++] = !!(k & 0x02);
+ value[bit++] = !!(k & 0x04);
+ value[bit++] = !!(k & 0x08);
+ value[bit++] = !!(k & 0x10);
+ value[bit++] = !!(k & 0x20);
+ value[bit++] = !!(k & 0x40);
+ value[bit++] = !!(k & 0x80);
+ }
+
+ if(bit < bits) {
+ var m = 0;
+ k = this.readByte(offset++);
+ while(bit < bits) value[bit++] = !!((k >> (m++)) & 1);
+ }
+
+ if (relative) {
+ this.offset = offset;
+ }
+ return value;
+ }
+ /**
+ * Reads the specified number of bytes.
+ * @param {number} length Number of bytes to read
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted.
+ * @returns {!ByteBuffer}
+ * @expose
+ */
+ ByteBufferPrototype.readBytes = function(length, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + length > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength);
+ }
+ var slice = this.slice(offset, offset + length);
+ if (relative) this.offset += length;
+ return slice;
+ };
+
+ /**
+ * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}.
+ * @function
+ * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its offsets
+ * will be modified according to the performed read operation.
+ * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeBytes = ByteBufferPrototype.append;
+
+ // types/ints/int8
+
+ /**
+ * Writes an 8bit signed integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeInt8 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 1;
+ var capacity0 = this.buffer.byteLength;
+ if (offset > capacity0)
+ this.resize((capacity0 *= 2) > offset ? capacity0 : offset);
+ offset -= 1;
+ this.view[offset] = value;
+ if (relative) this.offset += 1;
+ return this;
+ };
+
+ /**
+ * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8;
+
+ /**
+ * Reads an 8bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readInt8 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view[offset];
+ if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed
+ if (relative) this.offset += 1;
+ return value;
+ };
+
+ /**
+ * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8;
+
+ /**
+ * Writes an 8bit unsigned integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeUint8 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value >>>= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 1;
+ var capacity1 = this.buffer.byteLength;
+ if (offset > capacity1)
+ this.resize((capacity1 *= 2) > offset ? capacity1 : offset);
+ offset -= 1;
+ this.view[offset] = value;
+ if (relative) this.offset += 1;
+ return this;
+ };
+
+ /**
+ * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8;
+
+ /**
+ * Reads an 8bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readUint8 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var value = this.view[offset];
+ if (relative) this.offset += 1;
+ return value;
+ };
+
+ /**
+ * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8;
+
+ // types/ints/int16
+
+ /**
+ * Writes a 16bit signed integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeInt16 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 2;
+ var capacity2 = this.buffer.byteLength;
+ if (offset > capacity2)
+ this.resize((capacity2 *= 2) > offset ? capacity2 : offset);
+ offset -= 2;
+ if (this.littleEndian) {
+ this.view[offset+1] = (value & 0xFF00) >>> 8;
+ this.view[offset ] = value & 0x00FF;
+ } else {
+ this.view[offset] = (value & 0xFF00) >>> 8;
+ this.view[offset+1] = value & 0x00FF;
+ }
+ if (relative) this.offset += 2;
+ return this;
+ };
+
+ /**
+ * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16;
+
+ /**
+ * Reads a 16bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readInt16 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 2 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
+ }
+ var value = 0;
+ if (this.littleEndian) {
+ value = this.view[offset ];
+ value |= this.view[offset+1] << 8;
+ } else {
+ value = this.view[offset ] << 8;
+ value |= this.view[offset+1];
+ }
+ if ((value & 0x8000) === 0x8000) value = -(0xFFFF - value + 1); // Cast to signed
+ if (relative) this.offset += 2;
+ return value;
+ };
+
+ /**
+ * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16;
+
+ /**
+ * Writes a 16bit unsigned integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeUint16 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value >>>= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 2;
+ var capacity3 = this.buffer.byteLength;
+ if (offset > capacity3)
+ this.resize((capacity3 *= 2) > offset ? capacity3 : offset);
+ offset -= 2;
+ if (this.littleEndian) {
+ this.view[offset+1] = (value & 0xFF00) >>> 8;
+ this.view[offset ] = value & 0x00FF;
+ } else {
+ this.view[offset] = (value & 0xFF00) >>> 8;
+ this.view[offset+1] = value & 0x00FF;
+ }
+ if (relative) this.offset += 2;
+ return this;
+ };
+
+ /**
+ * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @throws {TypeError} If `offset` or `value` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16;
+
+ /**
+ * Reads a 16bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readUint16 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 2 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength);
+ }
+ var value = 0;
+ if (this.littleEndian) {
+ value = this.view[offset ];
+ value |= this.view[offset+1] << 8;
+ } else {
+ value = this.view[offset ] << 8;
+ value |= this.view[offset+1];
+ }
+ if (relative) this.offset += 2;
+ return value;
+ };
+
+ /**
+ * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted.
+ * @returns {number} Value read
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16;
+
+ // types/ints/int32
+
+ /**
+ * Writes a 32bit signed integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeInt32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 4;
+ var capacity4 = this.buffer.byteLength;
+ if (offset > capacity4)
+ this.resize((capacity4 *= 2) > offset ? capacity4 : offset);
+ offset -= 4;
+ if (this.littleEndian) {
+ this.view[offset+3] = (value >>> 24) & 0xFF;
+ this.view[offset+2] = (value >>> 16) & 0xFF;
+ this.view[offset+1] = (value >>> 8) & 0xFF;
+ this.view[offset ] = value & 0xFF;
+ } else {
+ this.view[offset ] = (value >>> 24) & 0xFF;
+ this.view[offset+1] = (value >>> 16) & 0xFF;
+ this.view[offset+2] = (value >>> 8) & 0xFF;
+ this.view[offset+3] = value & 0xFF;
+ }
+ if (relative) this.offset += 4;
+ return this;
+ };
+
+ /**
+ * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32;
+
+ /**
+ * Reads a 32bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readInt32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var value = 0;
+ if (this.littleEndian) {
+ value = this.view[offset+2] << 16;
+ value |= this.view[offset+1] << 8;
+ value |= this.view[offset ];
+ value += this.view[offset+3] << 24 >>> 0;
+ } else {
+ value = this.view[offset+1] << 16;
+ value |= this.view[offset+2] << 8;
+ value |= this.view[offset+3];
+ value += this.view[offset ] << 24 >>> 0;
+ }
+ value |= 0; // Cast to signed
+ if (relative) this.offset += 4;
+ return value;
+ };
+
+ /**
+ * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}.
+ * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32;
+
+ /**
+ * Writes a 32bit unsigned integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeUint32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value >>>= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 4;
+ var capacity5 = this.buffer.byteLength;
+ if (offset > capacity5)
+ this.resize((capacity5 *= 2) > offset ? capacity5 : offset);
+ offset -= 4;
+ if (this.littleEndian) {
+ this.view[offset+3] = (value >>> 24) & 0xFF;
+ this.view[offset+2] = (value >>> 16) & 0xFF;
+ this.view[offset+1] = (value >>> 8) & 0xFF;
+ this.view[offset ] = value & 0xFF;
+ } else {
+ this.view[offset ] = (value >>> 24) & 0xFF;
+ this.view[offset+1] = (value >>> 16) & 0xFF;
+ this.view[offset+2] = (value >>> 8) & 0xFF;
+ this.view[offset+3] = value & 0xFF;
+ }
+ if (relative) this.offset += 4;
+ return this;
+ };
+
+ /**
+ * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @expose
+ */
+ ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32;
+
+ /**
+ * Reads a 32bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readUint32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var value = 0;
+ if (this.littleEndian) {
+ value = this.view[offset+2] << 16;
+ value |= this.view[offset+1] << 8;
+ value |= this.view[offset ];
+ value += this.view[offset+3] << 24 >>> 0;
+ } else {
+ value = this.view[offset+1] << 16;
+ value |= this.view[offset+2] << 8;
+ value |= this.view[offset+3];
+ value += this.view[offset ] << 24 >>> 0;
+ }
+ if (relative) this.offset += 4;
+ return value;
+ };
+
+ /**
+ * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number} Value read
+ * @expose
+ */
+ ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32;
+
+ // types/ints/int64
+
+ if (Long) {
+
+ /**
+ * Writes a 64bit signed integer.
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeInt64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (typeof value === 'string')
+ value = Long.fromString(value);
+ else if (!(value && value instanceof Long))
+ throw TypeError("Illegal value: "+value+" (not an integer or Long)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (typeof value === 'string')
+ value = Long.fromString(value);
+ offset += 8;
+ var capacity6 = this.buffer.byteLength;
+ if (offset > capacity6)
+ this.resize((capacity6 *= 2) > offset ? capacity6 : offset);
+ offset -= 8;
+ var lo = value.low,
+ hi = value.high;
+ if (this.littleEndian) {
+ this.view[offset+3] = (lo >>> 24) & 0xFF;
+ this.view[offset+2] = (lo >>> 16) & 0xFF;
+ this.view[offset+1] = (lo >>> 8) & 0xFF;
+ this.view[offset ] = lo & 0xFF;
+ offset += 4;
+ this.view[offset+3] = (hi >>> 24) & 0xFF;
+ this.view[offset+2] = (hi >>> 16) & 0xFF;
+ this.view[offset+1] = (hi >>> 8) & 0xFF;
+ this.view[offset ] = hi & 0xFF;
+ } else {
+ this.view[offset ] = (hi >>> 24) & 0xFF;
+ this.view[offset+1] = (hi >>> 16) & 0xFF;
+ this.view[offset+2] = (hi >>> 8) & 0xFF;
+ this.view[offset+3] = hi & 0xFF;
+ offset += 4;
+ this.view[offset ] = (lo >>> 24) & 0xFF;
+ this.view[offset+1] = (lo >>> 16) & 0xFF;
+ this.view[offset+2] = (lo >>> 8) & 0xFF;
+ this.view[offset+3] = lo & 0xFF;
+ }
+ if (relative) this.offset += 8;
+ return this;
+ };
+
+ /**
+ * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}.
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64;
+
+ /**
+ * Reads a 64bit signed integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readInt64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 8 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
+ }
+ var lo = 0,
+ hi = 0;
+ if (this.littleEndian) {
+ lo = this.view[offset+2] << 16;
+ lo |= this.view[offset+1] << 8;
+ lo |= this.view[offset ];
+ lo += this.view[offset+3] << 24 >>> 0;
+ offset += 4;
+ hi = this.view[offset+2] << 16;
+ hi |= this.view[offset+1] << 8;
+ hi |= this.view[offset ];
+ hi += this.view[offset+3] << 24 >>> 0;
+ } else {
+ hi = this.view[offset+1] << 16;
+ hi |= this.view[offset+2] << 8;
+ hi |= this.view[offset+3];
+ hi += this.view[offset ] << 24 >>> 0;
+ offset += 4;
+ lo = this.view[offset+1] << 16;
+ lo |= this.view[offset+2] << 8;
+ lo |= this.view[offset+3];
+ lo += this.view[offset ] << 24 >>> 0;
+ }
+ var value = new Long(lo, hi, false);
+ if (relative) this.offset += 8;
+ return value;
+ };
+
+ /**
+ * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64;
+
+ /**
+ * Writes a 64bit unsigned integer.
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeUint64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (typeof value === 'string')
+ value = Long.fromString(value);
+ else if (!(value && value instanceof Long))
+ throw TypeError("Illegal value: "+value+" (not an integer or Long)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (typeof value === 'string')
+ value = Long.fromString(value);
+ offset += 8;
+ var capacity7 = this.buffer.byteLength;
+ if (offset > capacity7)
+ this.resize((capacity7 *= 2) > offset ? capacity7 : offset);
+ offset -= 8;
+ var lo = value.low,
+ hi = value.high;
+ if (this.littleEndian) {
+ this.view[offset+3] = (lo >>> 24) & 0xFF;
+ this.view[offset+2] = (lo >>> 16) & 0xFF;
+ this.view[offset+1] = (lo >>> 8) & 0xFF;
+ this.view[offset ] = lo & 0xFF;
+ offset += 4;
+ this.view[offset+3] = (hi >>> 24) & 0xFF;
+ this.view[offset+2] = (hi >>> 16) & 0xFF;
+ this.view[offset+1] = (hi >>> 8) & 0xFF;
+ this.view[offset ] = hi & 0xFF;
+ } else {
+ this.view[offset ] = (hi >>> 24) & 0xFF;
+ this.view[offset+1] = (hi >>> 16) & 0xFF;
+ this.view[offset+2] = (hi >>> 8) & 0xFF;
+ this.view[offset+3] = hi & 0xFF;
+ offset += 4;
+ this.view[offset ] = (lo >>> 24) & 0xFF;
+ this.view[offset+1] = (lo >>> 16) & 0xFF;
+ this.view[offset+2] = (lo >>> 8) & 0xFF;
+ this.view[offset+3] = lo & 0xFF;
+ }
+ if (relative) this.offset += 8;
+ return this;
+ };
+
+ /**
+ * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}.
+ * @function
+ * @param {number|!Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64;
+
+ /**
+ * Reads a 64bit unsigned integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readUint64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 8 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
+ }
+ var lo = 0,
+ hi = 0;
+ if (this.littleEndian) {
+ lo = this.view[offset+2] << 16;
+ lo |= this.view[offset+1] << 8;
+ lo |= this.view[offset ];
+ lo += this.view[offset+3] << 24 >>> 0;
+ offset += 4;
+ hi = this.view[offset+2] << 16;
+ hi |= this.view[offset+1] << 8;
+ hi |= this.view[offset ];
+ hi += this.view[offset+3] << 24 >>> 0;
+ } else {
+ hi = this.view[offset+1] << 16;
+ hi |= this.view[offset+2] << 8;
+ hi |= this.view[offset+3];
+ hi += this.view[offset ] << 24 >>> 0;
+ offset += 4;
+ lo = this.view[offset+1] << 16;
+ lo |= this.view[offset+2] << 8;
+ lo |= this.view[offset+3];
+ lo += this.view[offset ] << 24 >>> 0;
+ }
+ var value = new Long(lo, hi, true);
+ if (relative) this.offset += 8;
+ return value;
+ };
+
+ /**
+ * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!Long}
+ * @expose
+ */
+ ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64;
+
+ } // Long
+
+
+ // types/floats/float32
+
+ /*
+ ieee754 - https://github.com/feross/ieee754
+
+ The MIT License (MIT)
+
+ Copyright (c) Feross Aboukhadijeh
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+ /**
+ * Reads an IEEE754 float from a byte array.
+ * @param {!Array} buffer
+ * @param {number} offset
+ * @param {boolean} isLE
+ * @param {number} mLen
+ * @param {number} nBytes
+ * @returns {number}
+ * @inner
+ */
+ function ieee754_read(buffer, offset, isLE, mLen, nBytes) {
+ var e, m,
+ eLen = nBytes * 8 - mLen - 1,
+ eMax = (1 << eLen) - 1,
+ eBias = eMax >> 1,
+ nBits = -7,
+ i = isLE ? (nBytes - 1) : 0,
+ d = isLE ? -1 : 1,
+ s = buffer[offset + i];
+
+ i += d;
+
+ e = s & ((1 << (-nBits)) - 1);
+ s >>= (-nBits);
+ nBits += eLen;
+ for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+ m = e & ((1 << (-nBits)) - 1);
+ e >>= (-nBits);
+ nBits += mLen;
+ for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}
+
+ if (e === 0) {
+ e = 1 - eBias;
+ } else if (e === eMax) {
+ return m ? NaN : ((s ? -1 : 1) * Infinity);
+ } else {
+ m = m + Math.pow(2, mLen);
+ e = e - eBias;
+ }
+ return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
+ }
+
+ /**
+ * Writes an IEEE754 float to a byte array.
+ * @param {!Array} buffer
+ * @param {number} value
+ * @param {number} offset
+ * @param {boolean} isLE
+ * @param {number} mLen
+ * @param {number} nBytes
+ * @inner
+ */
+ function ieee754_write(buffer, value, offset, isLE, mLen, nBytes) {
+ var e, m, c,
+ eLen = nBytes * 8 - mLen - 1,
+ eMax = (1 << eLen) - 1,
+ eBias = eMax >> 1,
+ rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
+ i = isLE ? 0 : (nBytes - 1),
+ d = isLE ? 1 : -1,
+ s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
+
+ value = Math.abs(value);
+
+ if (isNaN(value) || value === Infinity) {
+ m = isNaN(value) ? 1 : 0;
+ e = eMax;
+ } else {
+ e = Math.floor(Math.log(value) / Math.LN2);
+ if (value * (c = Math.pow(2, -e)) < 1) {
+ e--;
+ c *= 2;
+ }
+ if (e + eBias >= 1) {
+ value += rt / c;
+ } else {
+ value += rt * Math.pow(2, 1 - eBias);
+ }
+ if (value * c >= 2) {
+ e++;
+ c /= 2;
+ }
+
+ if (e + eBias >= eMax) {
+ m = 0;
+ e = eMax;
+ } else if (e + eBias >= 1) {
+ m = (value * c - 1) * Math.pow(2, mLen);
+ e = e + eBias;
+ } else {
+ m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
+ e = 0;
+ }
+ }
+
+ for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}
+
+ e = (e << mLen) | m;
+ eLen += mLen;
+ for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}
+
+ buffer[offset + i - d] |= s * 128;
+ }
+
+ /**
+ * Writes a 32bit float.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeFloat32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number')
+ throw TypeError("Illegal value: "+value+" (not a number)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 4;
+ var capacity8 = this.buffer.byteLength;
+ if (offset > capacity8)
+ this.resize((capacity8 *= 2) > offset ? capacity8 : offset);
+ offset -= 4;
+ ieee754_write(this.view, value, offset, this.littleEndian, 23, 4);
+ if (relative) this.offset += 4;
+ return this;
+ };
+
+ /**
+ * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32;
+
+ /**
+ * Reads a 32bit float.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readFloat32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var value = ieee754_read(this.view, offset, this.littleEndian, 23, 4);
+ if (relative) this.offset += 4;
+ return value;
+ };
+
+ /**
+ * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32;
+
+ // types/floats/float64
+
+ /**
+ * Writes a 64bit float.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeFloat64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number')
+ throw TypeError("Illegal value: "+value+" (not a number)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ offset += 8;
+ var capacity9 = this.buffer.byteLength;
+ if (offset > capacity9)
+ this.resize((capacity9 *= 2) > offset ? capacity9 : offset);
+ offset -= 8;
+ ieee754_write(this.view, value, offset, this.littleEndian, 52, 8);
+ if (relative) this.offset += 8;
+ return this;
+ };
+
+ /**
+ * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}.
+ * @function
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64;
+
+ /**
+ * Reads a 64bit float.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readFloat64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 8 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength);
+ }
+ var value = ieee754_read(this.view, offset, this.littleEndian, 52, 8);
+ if (relative) this.offset += 8;
+ return value;
+ };
+
+ /**
+ * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}.
+ * @function
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted.
+ * @returns {number}
+ * @expose
+ */
+ ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64;
+
+
+ // types/varints/varint32
+
+ /**
+ * Maximum number of bytes required to store a 32bit base 128 variable-length integer.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ByteBuffer.MAX_VARINT32_BYTES = 5;
+
+ /**
+ * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer.
+ * @param {number} value Value to encode
+ * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES}
+ * @expose
+ */
+ ByteBuffer.calculateVarint32 = function(value) {
+ // ref: src/google/protobuf/io/coded_stream.cc
+ value = value >>> 0;
+ if (value < 1 << 7 ) return 1;
+ else if (value < 1 << 14) return 2;
+ else if (value < 1 << 21) return 3;
+ else if (value < 1 << 28) return 4;
+ else return 5;
+ };
+
+ /**
+ * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding.
+ * @param {number} n Signed 32bit integer
+ * @returns {number} Unsigned zigzag encoded 32bit integer
+ * @expose
+ */
+ ByteBuffer.zigZagEncode32 = function(n) {
+ return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h
+ };
+
+ /**
+ * Decodes a zigzag encoded signed 32bit integer.
+ * @param {number} n Unsigned zigzag encoded 32bit integer
+ * @returns {number} Signed 32bit integer
+ * @expose
+ */
+ ByteBuffer.zigZagDecode32 = function(n) {
+ return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h
+ };
+
+ /**
+ * Writes a 32bit base 128 variable-length integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint32 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var size = ByteBuffer.calculateVarint32(value),
+ b;
+ offset += size;
+ var capacity10 = this.buffer.byteLength;
+ if (offset > capacity10)
+ this.resize((capacity10 *= 2) > offset ? capacity10 : offset);
+ offset -= size;
+ value >>>= 0;
+ while (value >= 0x80) {
+ b = (value & 0x7f) | 0x80;
+ this.view[offset++] = b;
+ value >>>= 7;
+ }
+ this.view[offset++] = value;
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return size;
+ };
+
+ /**
+ * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer.
+ * @param {number} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) {
+ return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset);
+ };
+
+ /**
+ * Reads a 32bit base 128 variable-length integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
+ * and the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available
+ * to fully decode the varint.
+ * @expose
+ */
+ ByteBufferPrototype.readVarint32 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var c = 0,
+ value = 0 >>> 0,
+ b;
+ do {
+ if (!this.noAssert && offset > this.limit) {
+ var err = Error("Truncated");
+ err['truncated'] = true;
+ throw err;
+ }
+ b = this.view[offset++];
+ if (c < 5)
+ value |= (b & 0x7f) << (7*c);
+ ++c;
+ } while ((b & 0x80) !== 0);
+ value |= 0;
+ if (relative) {
+ this.offset = offset;
+ return value;
+ }
+ return {
+ "value": value,
+ "length": c
+ };
+ };
+
+ /**
+ * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read
+ * and the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint
+ * @expose
+ */
+ ByteBufferPrototype.readVarint32ZigZag = function(offset) {
+ var val = this.readVarint32(offset);
+ if (typeof val === 'object')
+ val["value"] = ByteBuffer.zigZagDecode32(val["value"]);
+ else
+ val = ByteBuffer.zigZagDecode32(val);
+ return val;
+ };
+
+ // types/varints/varint64
+
+ if (Long) {
+
+ /**
+ * Maximum number of bytes required to store a 64bit base 128 variable-length integer.
+ * @type {number}
+ * @const
+ * @expose
+ */
+ ByteBuffer.MAX_VARINT64_BYTES = 10;
+
+ /**
+ * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer.
+ * @param {number|!Long} value Value to encode
+ * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES}
+ * @expose
+ */
+ ByteBuffer.calculateVarint64 = function(value) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (typeof value === 'string')
+ value = Long.fromString(value);
+ // ref: src/google/protobuf/io/coded_stream.cc
+ var part0 = value.toInt() >>> 0,
+ part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
+ part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
+ if (part2 == 0) {
+ if (part1 == 0) {
+ if (part0 < 1 << 14)
+ return part0 < 1 << 7 ? 1 : 2;
+ else
+ return part0 < 1 << 21 ? 3 : 4;
+ } else {
+ if (part1 < 1 << 14)
+ return part1 < 1 << 7 ? 5 : 6;
+ else
+ return part1 < 1 << 21 ? 7 : 8;
+ }
+ } else
+ return part2 < 1 << 7 ? 9 : 10;
+ };
+
+ /**
+ * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding.
+ * @param {number|!Long} value Signed long
+ * @returns {!Long} Unsigned zigzag encoded long
+ * @expose
+ */
+ ByteBuffer.zigZagEncode64 = function(value) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value, false);
+ else if (typeof value === 'string')
+ value = Long.fromString(value, false);
+ else if (value.unsigned !== false) value = value.toSigned();
+ // ref: src/google/protobuf/wire_format_lite.h
+ return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned();
+ };
+
+ /**
+ * Decodes a zigzag encoded signed 64bit integer.
+ * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number
+ * @returns {!Long} Signed long
+ * @expose
+ */
+ ByteBuffer.zigZagDecode64 = function(value) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value, false);
+ else if (typeof value === 'string')
+ value = Long.fromString(value, false);
+ else if (value.unsigned !== false) value = value.toSigned();
+ // ref: src/google/protobuf/wire_format_lite.h
+ return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned();
+ };
+
+ /**
+ * Writes a 64bit base 128 variable-length integer.
+ * @param {number|Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint64 = function(value, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof value === 'number')
+ value = Long.fromNumber(value);
+ else if (typeof value === 'string')
+ value = Long.fromString(value);
+ else if (!(value && value instanceof Long))
+ throw TypeError("Illegal value: "+value+" (not an integer or Long)");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (typeof value === 'number')
+ value = Long.fromNumber(value, false);
+ else if (typeof value === 'string')
+ value = Long.fromString(value, false);
+ else if (value.unsigned !== false) value = value.toSigned();
+ var size = ByteBuffer.calculateVarint64(value),
+ part0 = value.toInt() >>> 0,
+ part1 = value.shiftRightUnsigned(28).toInt() >>> 0,
+ part2 = value.shiftRightUnsigned(56).toInt() >>> 0;
+ offset += size;
+ var capacity11 = this.buffer.byteLength;
+ if (offset > capacity11)
+ this.resize((capacity11 *= 2) > offset ? capacity11 : offset);
+ offset -= size;
+ switch (size) {
+ case 10: this.view[offset+9] = (part2 >>> 7) & 0x01;
+ case 9 : this.view[offset+8] = size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F;
+ case 8 : this.view[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F;
+ case 7 : this.view[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F;
+ case 6 : this.view[offset+5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F;
+ case 5 : this.view[offset+4] = size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F;
+ case 4 : this.view[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F;
+ case 3 : this.view[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F;
+ case 2 : this.view[offset+1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F;
+ case 1 : this.view[offset ] = size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F;
+ }
+ if (relative) {
+ this.offset += size;
+ return this;
+ } else {
+ return size;
+ }
+ };
+
+ /**
+ * Writes a zig-zag encoded 64bit base 128 variable-length integer.
+ * @param {number|Long} value Value to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) {
+ return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset);
+ };
+
+ /**
+ * Reads a 64bit base 128 variable-length integer. Requires Long.js.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
+ * the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint
+ * @expose
+ */
+ ByteBufferPrototype.readVarint64 = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ // ref: src/google/protobuf/io/coded_stream.cc
+ var start = offset,
+ part0 = 0,
+ part1 = 0,
+ part2 = 0,
+ b = 0;
+ b = this.view[offset++]; part0 = (b & 0x7F) ; if ( b & 0x80 ) {
+ b = this.view[offset++]; part0 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part1 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part1 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part2 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ b = this.view[offset++]; part2 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) {
+ throw Error("Buffer overrun"); }}}}}}}}}}
+ var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false);
+ if (relative) {
+ this.offset = offset;
+ return value;
+ } else {
+ return {
+ 'value': value,
+ 'length': offset-start
+ };
+ }
+ };
+
+ /**
+ * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and
+ * the actual number of bytes read.
+ * @throws {Error} If it's not a valid varint
+ * @expose
+ */
+ ByteBufferPrototype.readVarint64ZigZag = function(offset) {
+ var val = this.readVarint64(offset);
+ if (val && val['value'] instanceof Long)
+ val["value"] = ByteBuffer.zigZagDecode64(val["value"]);
+ else
+ val = ByteBuffer.zigZagDecode64(val);
+ return val;
+ };
+
+ } // Long
+
+
+ // types/strings/cstring
+
+ /**
+ * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL
+ * characters itself.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * contained in `str` + 1 if omitted.
+ * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written
+ * @expose
+ */
+ ByteBufferPrototype.writeCString = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ var i,
+ k = str.length;
+ if (!this.noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ for (i=0; i<k; ++i) {
+ if (str.charCodeAt(i) === 0)
+ throw RangeError("Illegal str: Contains NULL-characters");
+ }
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ // UTF8 strings do not contain zero bytes in between except for the zero character, so:
+ k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
+ offset += k+1;
+ var capacity12 = this.buffer.byteLength;
+ if (offset > capacity12)
+ this.resize((capacity12 *= 2) > offset ? capacity12 : offset);
+ offset -= k+1;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view[offset++] = b;
+ }.bind(this));
+ this.view[offset++] = 0;
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return k;
+ };
+
+ /**
+ * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters
+ * itself.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ */
+ ByteBufferPrototype.readCString = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var start = offset,
+ temp;
+ // UTF8 strings do not contain zero bytes in between except for the zero character itself, so:
+ var sd, b = -1;
+ utfx.decodeUTF8toUTF16(function() {
+ if (b === 0) return null;
+ if (offset >= this.limit)
+ throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit);
+ b = this.view[offset++];
+ return b === 0 ? null : b;
+ }.bind(this), sd = stringDestination(), true);
+ if (relative) {
+ this.offset = offset;
+ return sd();
+ } else {
+ return {
+ "string": sd(),
+ "length": offset - start
+ };
+ }
+ };
+
+ // types/strings/istring
+
+ /**
+ * Writes a length as uint32 prefixed UTF8 encoded string.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ * @see ByteBuffer#writeVarint32
+ */
+ ByteBufferPrototype.writeIString = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var start = offset,
+ k;
+ k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
+ offset += 4+k;
+ var capacity13 = this.buffer.byteLength;
+ if (offset > capacity13)
+ this.resize((capacity13 *= 2) > offset ? capacity13 : offset);
+ offset -= 4+k;
+ if (this.littleEndian) {
+ this.view[offset+3] = (k >>> 24) & 0xFF;
+ this.view[offset+2] = (k >>> 16) & 0xFF;
+ this.view[offset+1] = (k >>> 8) & 0xFF;
+ this.view[offset ] = k & 0xFF;
+ } else {
+ this.view[offset ] = (k >>> 24) & 0xFF;
+ this.view[offset+1] = (k >>> 16) & 0xFF;
+ this.view[offset+2] = (k >>> 8) & 0xFF;
+ this.view[offset+3] = k & 0xFF;
+ }
+ offset += 4;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view[offset++] = b;
+ }.bind(this));
+ if (offset !== start + 4 + k)
+ throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k));
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ };
+
+ /**
+ * Reads a length as uint32 prefixed UTF8 encoded string.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ * @see ByteBuffer#readVarint32
+ */
+ ByteBufferPrototype.readIString = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 4 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength);
+ }
+ var start = offset;
+ var len = this.readUint32(offset);
+ var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4);
+ offset += str['length'];
+ if (relative) {
+ this.offset = offset;
+ return str['string'];
+ } else {
+ return {
+ 'string': str['string'],
+ 'length': offset - start
+ };
+ }
+ };
+
+ // types/strings/utf8string
+
+ /**
+ * Metrics representing number of UTF8 characters. Evaluates to `c`.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ByteBuffer.METRICS_CHARS = 'c';
+
+ /**
+ * Metrics representing number of bytes. Evaluates to `b`.
+ * @type {string}
+ * @const
+ * @expose
+ */
+ ByteBuffer.METRICS_BYTES = 'b';
+
+ /**
+ * Writes an UTF8 encoded string.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
+ * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeUTF8String = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var k;
+ var start = offset;
+ k = utfx.calculateUTF16asUTF8(stringSource(str))[1];
+ offset += k;
+ var capacity14 = this.buffer.byteLength;
+ if (offset > capacity14)
+ this.resize((capacity14 *= 2) > offset ? capacity14 : offset);
+ offset -= k;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view[offset++] = b;
+ }.bind(this));
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ };
+
+ /**
+ * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}.
+ * @function
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted.
+ * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written.
+ * @expose
+ */
+ ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String;
+
+ /**
+ * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's
+ * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF.
+ * @param {string} str String to calculate
+ * @returns {number} Number of UTF8 characters
+ * @expose
+ */
+ ByteBuffer.calculateUTF8Chars = function(str) {
+ return utfx.calculateUTF16asUTF8(stringSource(str))[0];
+ };
+
+ /**
+ * Calculates the number of UTF8 bytes of a string.
+ * @param {string} str String to calculate
+ * @returns {number} Number of UTF8 bytes
+ * @expose
+ */
+ ByteBuffer.calculateUTF8Bytes = function(str) {
+ return utfx.calculateUTF16asUTF8(stringSource(str))[1];
+ };
+
+ /**
+ * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}.
+ * @function
+ * @param {string} str String to calculate
+ * @returns {number} Number of UTF8 bytes
+ * @expose
+ */
+ ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes;
+
+ /**
+ * Reads an UTF8 encoded string.
+ * @param {number} length Number of characters or bytes to read.
+ * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to
+ * {@link ByteBuffer.METRICS_CHARS}.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ */
+ ByteBufferPrototype.readUTF8String = function(length, metrics, offset) {
+ if (typeof metrics === 'number') {
+ offset = metrics;
+ metrics = undefined;
+ }
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS;
+ if (!this.noAssert) {
+ if (typeof length !== 'number' || length % 1 !== 0)
+ throw TypeError("Illegal length: "+length+" (not an integer)");
+ length |= 0;
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var i = 0,
+ start = offset,
+ sd;
+ if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser
+ sd = stringDestination();
+ utfx.decodeUTF8(function() {
+ return i < length && offset < this.limit ? this.view[offset++] : null;
+ }.bind(this), function(cp) {
+ ++i; utfx.UTF8toUTF16(cp, sd);
+ });
+ if (i !== length)
+ throw RangeError("Illegal range: Truncated data, "+i+" == "+length);
+ if (relative) {
+ this.offset = offset;
+ return sd();
+ } else {
+ return {
+ "string": sd(),
+ "length": offset - start
+ };
+ }
+ } else if (metrics === ByteBuffer.METRICS_BYTES) {
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + length > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength);
+ }
+ var k = offset + length;
+ utfx.decodeUTF8toUTF16(function() {
+ return offset < k ? this.view[offset++] : null;
+ }.bind(this), sd = stringDestination(), this.noAssert);
+ if (offset !== k)
+ throw RangeError("Illegal range: Truncated data, "+offset+" == "+k);
+ if (relative) {
+ this.offset = offset;
+ return sd();
+ } else {
+ return {
+ 'string': sd(),
+ 'length': offset - start
+ };
+ }
+ } else
+ throw TypeError("Unsupported metrics: "+metrics);
+ };
+
+ /**
+ * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}.
+ * @function
+ * @param {number} length Number of characters or bytes to read
+ * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to
+ * {@link ByteBuffer.METRICS_CHARS}.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ */
+ ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String;
+
+ // types/strings/vstring
+
+ /**
+ * Writes a length as varint32 prefixed UTF8 encoded string.
+ * @param {string} str String to write
+ * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written
+ * @expose
+ * @see ByteBuffer#writeVarint32
+ */
+ ByteBufferPrototype.writeVString = function(str, offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ var start = offset,
+ k, l;
+ k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1];
+ l = ByteBuffer.calculateVarint32(k);
+ offset += l+k;
+ var capacity15 = this.buffer.byteLength;
+ if (offset > capacity15)
+ this.resize((capacity15 *= 2) > offset ? capacity15 : offset);
+ offset -= l+k;
+ offset += this.writeVarint32(k, offset);
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ this.view[offset++] = b;
+ }.bind(this));
+ if (offset !== start+k+l)
+ throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l));
+ if (relative) {
+ this.offset = offset;
+ return this;
+ }
+ return offset - start;
+ };
+
+ /**
+ * Reads a length as varint32 prefixed UTF8 encoded string.
+ * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string
+ * read and the actual number of bytes read.
+ * @expose
+ * @see ByteBuffer#readVarint32
+ */
+ ByteBufferPrototype.readVString = function(offset) {
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 1 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength);
+ }
+ var start = offset;
+ var len = this.readVarint32(offset);
+ var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']);
+ offset += str['length'];
+ if (relative) {
+ this.offset = offset;
+ return str['string'];
+ } else {
+ return {
+ 'string': str['string'],
+ 'length': offset - start
+ };
+ }
+ };
+
+
+ /**
+ * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended
+ * data's length.
+ * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets
+ * will be modified according to the performed read operation.
+ * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
+ * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|`
+ * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|`
+ */
+ ByteBufferPrototype.append = function(source, encoding, offset) {
+ if (typeof encoding === 'number' || typeof encoding !== 'string') {
+ offset = encoding;
+ encoding = undefined;
+ }
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (!(source instanceof ByteBuffer))
+ source = ByteBuffer.wrap(source, encoding);
+ var length = source.limit - source.offset;
+ if (length <= 0) return this; // Nothing to append
+ offset += length;
+ var capacity16 = this.buffer.byteLength;
+ if (offset > capacity16)
+ this.resize((capacity16 *= 2) > offset ? capacity16 : offset);
+ offset -= length;
+ this.view.set(source.view.subarray(source.offset, source.limit), offset);
+ source.offset += length;
+ if (relative) this.offset += length;
+ return this;
+ };
+
+ /**
+ * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the
+ specified offset up to the length of this ByteBuffer's data.
+ * @param {!ByteBuffer} target Target ByteBuffer
+ * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * read if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @see ByteBuffer#append
+ */
+ ByteBufferPrototype.appendTo = function(target, offset) {
+ target.append(this, offset);
+ return this;
+ };
+
+ /**
+ * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to
+ * disable them if your code already makes sure that everything is valid.
+ * @param {boolean} assert `true` to enable assertions, otherwise `false`
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.assert = function(assert) {
+ this.noAssert = !assert;
+ return this;
+ };
+
+ /**
+ * Gets the capacity of this ByteBuffer's backing buffer.
+ * @returns {number} Capacity of the backing buffer
+ * @expose
+ */
+ ByteBufferPrototype.capacity = function() {
+ return this.buffer.byteLength;
+ };
+ /**
+ * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the
+ * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.clear = function() {
+ this.offset = 0;
+ this.limit = this.buffer.byteLength;
+ this.markedOffset = -1;
+ return this;
+ };
+
+ /**
+ * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset},
+ * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}.
+ * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false`
+ * @returns {!ByteBuffer} Cloned instance
+ * @expose
+ */
+ ByteBufferPrototype.clone = function(copy) {
+ var bb = new ByteBuffer(0, this.littleEndian, this.noAssert);
+ if (copy) {
+ bb.buffer = new ArrayBuffer(this.buffer.byteLength);
+ bb.view = new Uint8Array(bb.buffer);
+ } else {
+ bb.buffer = this.buffer;
+ bb.view = this.view;
+ }
+ bb.offset = this.offset;
+ bb.markedOffset = this.markedOffset;
+ bb.limit = this.limit;
+ return bb;
+ };
+
+ /**
+ * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes
+ * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and
+ * adapt {@link ByteBuffer#markedOffset} to the same relative position if set.
+ * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.compact = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === 0 && end === this.buffer.byteLength)
+ return this; // Already compacted
+ var len = end - begin;
+ if (len === 0) {
+ this.buffer = EMPTY_BUFFER;
+ this.view = null;
+ if (this.markedOffset >= 0) this.markedOffset -= begin;
+ this.offset = 0;
+ this.limit = 0;
+ return this;
+ }
+ var buffer = new ArrayBuffer(len);
+ var view = new Uint8Array(buffer);
+ view.set(this.view.subarray(begin, end));
+ this.buffer = buffer;
+ this.view = view;
+ if (this.markedOffset >= 0) this.markedOffset -= begin;
+ this.offset = 0;
+ this.limit = len;
+ return this;
+ };
+
+ /**
+ * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and
+ * {@link ByteBuffer#limit}.
+ * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
+ * @returns {!ByteBuffer} Copy
+ * @expose
+ */
+ ByteBufferPrototype.copy = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === end)
+ return new ByteBuffer(0, this.littleEndian, this.noAssert);
+ var capacity = end - begin,
+ bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert);
+ bb.offset = 0;
+ bb.limit = capacity;
+ if (bb.markedOffset >= 0) bb.markedOffset -= begin;
+ this.copyTo(bb, 0, begin, end);
+ return bb;
+ };
+
+ /**
+ * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and
+ * {@link ByteBuffer#limit}.
+ * @param {!ByteBuffer} target Target ByteBuffer
+ * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset}
+ * by the number of bytes copied if omitted.
+ * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the
+ * number of bytes copied if omitted.
+ * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit}
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) {
+ var relative,
+ targetRelative;
+ if (!this.noAssert) {
+ if (!ByteBuffer.isByteBuffer(target))
+ throw TypeError("Illegal target: Not a ByteBuffer");
+ }
+ targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0;
+ sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0;
+ sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0;
+
+ if (targetOffset < 0 || targetOffset > target.buffer.byteLength)
+ throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength);
+ if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength)
+ throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength);
+
+ var len = sourceLimit - sourceOffset;
+ if (len === 0)
+ return target; // Nothing to copy
+
+ target.ensureCapacity(targetOffset + len);
+
+ target.view.set(this.view.subarray(sourceOffset, sourceLimit), targetOffset);
+
+ if (relative) this.offset += len;
+ if (targetRelative) target.offset += len;
+
+ return this;
+ };
+
+ /**
+ * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the
+ * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity,
+ * the required capacity will be used instead.
+ * @param {number} capacity Required capacity
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.ensureCapacity = function(capacity) {
+ var current = this.buffer.byteLength;
+ if (current < capacity)
+ return this.resize((current *= 2) > capacity ? current : capacity);
+ return this;
+ };
+
+ /**
+ * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between
+ * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}.
+ * @param {number|string} value Byte value to fill with. If given as a string, the first character is used.
+ * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes
+ * written if omitted. defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes
+ */
+ ByteBufferPrototype.fill = function(value, begin, end) {
+ var relative = typeof begin === 'undefined';
+ if (relative) begin = this.offset;
+ if (typeof value === 'string' && value.length > 0)
+ value = value.charCodeAt(0);
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof value !== 'number' || value % 1 !== 0)
+ throw TypeError("Illegal value: "+value+" (not an integer)");
+ value |= 0;
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin >= end)
+ return this; // Nothing to fill
+ while (begin < end) this.view[begin++] = value;
+ if (relative) this.offset = begin;
+ return this;
+ };
+
+ /**
+ * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and
+ * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.flip = function() {
+ this.limit = this.offset;
+ this.offset = 0;
+ return this;
+ };
+ /**
+ * Marks an offset on this ByteBuffer to be used later.
+ * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}.
+ * @returns {!ByteBuffer} this
+ * @throws {TypeError} If `offset` is not a valid number
+ * @throws {RangeError} If `offset` is out of bounds
+ * @see ByteBuffer#reset
+ * @expose
+ */
+ ByteBufferPrototype.mark = function(offset) {
+ offset = typeof offset === 'undefined' ? this.offset : offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ this.markedOffset = offset;
+ return this;
+ };
+ /**
+ * Sets the byte order.
+ * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.order = function(littleEndian) {
+ if (!this.noAssert) {
+ if (typeof littleEndian !== 'boolean')
+ throw TypeError("Illegal littleEndian: Not a boolean");
+ }
+ this.littleEndian = !!littleEndian;
+ return this;
+ };
+
+ /**
+ * Switches (to) little endian byte order.
+ * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.LE = function(littleEndian) {
+ this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true;
+ return this;
+ };
+
+ /**
+ * Switches (to) big endian byte order.
+ * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.BE = function(bigEndian) {
+ this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false;
+ return this;
+ };
+ /**
+ * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the
+ * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
+ * will be resized and its contents moved accordingly.
+ * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be
+ * modified according to the performed read operation.
+ * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8")
+ * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
+ * prepended if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|`
+ * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|`
+ */
+ ByteBufferPrototype.prepend = function(source, encoding, offset) {
+ if (typeof encoding === 'number' || typeof encoding !== 'string') {
+ offset = encoding;
+ encoding = undefined;
+ }
+ var relative = typeof offset === 'undefined';
+ if (relative) offset = this.offset;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: "+offset+" (not an integer)");
+ offset >>>= 0;
+ if (offset < 0 || offset + 0 > this.buffer.byteLength)
+ throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength);
+ }
+ if (!(source instanceof ByteBuffer))
+ source = ByteBuffer.wrap(source, encoding);
+ var len = source.limit - source.offset;
+ if (len <= 0) return this; // Nothing to prepend
+ var diff = len - offset;
+ if (diff > 0) { // Not enough space before offset, so resize + move
+ var buffer = new ArrayBuffer(this.buffer.byteLength + diff);
+ var view = new Uint8Array(buffer);
+ view.set(this.view.subarray(offset, this.buffer.byteLength), len);
+ this.buffer = buffer;
+ this.view = view;
+ this.offset += diff;
+ if (this.markedOffset >= 0) this.markedOffset += diff;
+ this.limit += diff;
+ offset += diff;
+ } else {
+ var arrayView = new Uint8Array(this.buffer);
+ }
+ this.view.set(source.view.subarray(source.offset, source.limit), offset - len);
+
+ source.offset = source.limit;
+ if (relative)
+ this.offset -= len;
+ return this;
+ };
+
+ /**
+ * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the
+ * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer
+ * will be resized and its contents moved accordingly.
+ * @param {!ByteBuffer} target Target ByteBuffer
+ * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes
+ * prepended if omitted.
+ * @returns {!ByteBuffer} this
+ * @expose
+ * @see ByteBuffer#prepend
+ */
+ ByteBufferPrototype.prependTo = function(target, offset) {
+ target.prepend(this, offset);
+ return this;
+ };
+ /**
+ * Prints debug information about this ByteBuffer's contents.
+ * @param {function(string)=} out Output function to call, defaults to console.log
+ * @expose
+ */
+ ByteBufferPrototype.printDebug = function(out) {
+ if (typeof out !== 'function') out = console.log.bind(console);
+ out(
+ this.toString()+"\n"+
+ "-------------------------------------------------------------------\n"+
+ this.toDebug(/* columns */ true)
+ );
+ };
+
+ /**
+ * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and
+ * {@link ByteBuffer#limit}, so this returns `limit - offset`.
+ * @returns {number} Remaining readable bytes. May be negative if `offset > limit`.
+ * @expose
+ */
+ ByteBufferPrototype.remaining = function() {
+ return this.limit - this.offset;
+ };
+ /**
+ * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark}
+ * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been
+ * marked, sets `offset = 0`.
+ * @returns {!ByteBuffer} this
+ * @see ByteBuffer#mark
+ * @expose
+ */
+ ByteBufferPrototype.reset = function() {
+ if (this.markedOffset >= 0) {
+ this.offset = this.markedOffset;
+ this.markedOffset = -1;
+ } else {
+ this.offset = 0;
+ }
+ return this;
+ };
+ /**
+ * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that
+ * large or larger.
+ * @param {number} capacity Capacity required
+ * @returns {!ByteBuffer} this
+ * @throws {TypeError} If `capacity` is not a number
+ * @throws {RangeError} If `capacity < 0`
+ * @expose
+ */
+ ByteBufferPrototype.resize = function(capacity) {
+ if (!this.noAssert) {
+ if (typeof capacity !== 'number' || capacity % 1 !== 0)
+ throw TypeError("Illegal capacity: "+capacity+" (not an integer)");
+ capacity |= 0;
+ if (capacity < 0)
+ throw RangeError("Illegal capacity: 0 <= "+capacity);
+ }
+ if (this.buffer.byteLength < capacity) {
+ var buffer = new ArrayBuffer(capacity);
+ var view = new Uint8Array(buffer);
+ view.set(this.view);
+ this.buffer = buffer;
+ this.view = view;
+ }
+ return this;
+ };
+ /**
+ * Reverses this ByteBuffer's contents.
+ * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset}
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.reverse = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ if (begin === end)
+ return this; // Nothing to reverse
+ Array.prototype.reverse.call(this.view.subarray(begin, end));
+ return this;
+ };
+ /**
+ * Skips the next `length` bytes. This will just advance
+ * @param {number} length Number of bytes to skip. May also be negative to move the offset back.
+ * @returns {!ByteBuffer} this
+ * @expose
+ */
+ ByteBufferPrototype.skip = function(length) {
+ if (!this.noAssert) {
+ if (typeof length !== 'number' || length % 1 !== 0)
+ throw TypeError("Illegal length: "+length+" (not an integer)");
+ length |= 0;
+ }
+ var offset = this.offset + length;
+ if (!this.noAssert) {
+ if (offset < 0 || offset > this.buffer.byteLength)
+ throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength);
+ }
+ this.offset = offset;
+ return this;
+ };
+
+ /**
+ * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`.
+ * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}.
+ * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer}
+ * @expose
+ */
+ ByteBufferPrototype.slice = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var bb = this.clone();
+ bb.offset = begin;
+ bb.limit = end;
+ return bb;
+ };
+ /**
+ * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between
+ * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}.
+ * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if
+ * possible. Defaults to `false`
+ * @returns {!ArrayBuffer} Contents as an ArrayBuffer
+ * @expose
+ */
+ ByteBufferPrototype.toBuffer = function(forceCopy) {
+ var offset = this.offset,
+ limit = this.limit;
+ if (!this.noAssert) {
+ if (typeof offset !== 'number' || offset % 1 !== 0)
+ throw TypeError("Illegal offset: Not an integer");
+ offset >>>= 0;
+ if (typeof limit !== 'number' || limit % 1 !== 0)
+ throw TypeError("Illegal limit: Not an integer");
+ limit >>>= 0;
+ if (offset < 0 || offset > limit || limit > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength);
+ }
+ // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is
+ // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So:
+ if (!forceCopy && offset === 0 && limit === this.buffer.byteLength)
+ return this.buffer;
+ if (offset === limit)
+ return EMPTY_BUFFER;
+ var buffer = new ArrayBuffer(limit - offset);
+ new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0);
+ return buffer;
+ };
+
+ /**
+ * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between
+ * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. This is an alias of {@link ByteBuffer#toBuffer}.
+ * @function
+ * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory.
+ * Defaults to `false`
+ * @returns {!ArrayBuffer} Contents as an ArrayBuffer
+ * @expose
+ */
+ ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer;
+
+ /**
+ * Converts the ByteBuffer's contents to a string.
+ * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows
+ * direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with
+ * highlighted offsets.
+ * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}
+ * @returns {string} String representation
+ * @throws {Error} If `encoding` is invalid
+ * @expose
+ */
+ ByteBufferPrototype.toString = function(encoding, begin, end) {
+ if (typeof encoding === 'undefined')
+ return "ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";
+ if (typeof encoding === 'number')
+ encoding = "utf8",
+ begin = encoding,
+ end = begin;
+ switch (encoding) {
+ case "utf8":
+ return this.toUTF8(begin, end);
+ case "base64":
+ return this.toBase64(begin, end);
+ case "hex":
+ return this.toHex(begin, end);
+ case "binary":
+ return this.toBinary(begin, end);
+ case "debug":
+ return this.toDebug();
+ case "columns":
+ return this.toColumns();
+ default:
+ throw Error("Unsupported encoding: "+encoding);
+ }
+ };
+
+ // lxiv-embeddable
+
+ /**
+ * lxiv-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/lxiv for details
+ */
+ var lxiv = function() {
+ "use strict";
+
+ /**
+ * lxiv namespace.
+ * @type {!Object.<string,*>}
+ * @exports lxiv
+ */
+ var lxiv = {};
+
+ /**
+ * Character codes for output.
+ * @type {!Array.<number>}
+ * @inner
+ */
+ var aout = [
+ 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
+ 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102,
+ 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118,
+ 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47
+ ];
+
+ /**
+ * Character codes for input.
+ * @type {!Array.<number>}
+ * @inner
+ */
+ var ain = [];
+ for (var i=0, k=aout.length; i<k; ++i)
+ ain[aout[i]] = i;
+
+ /**
+ * Encodes bytes to base64 char codes.
+ * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if
+ * there are no more bytes left.
+ * @param {!function(number)} dst Characters destination as a function successively called with each encoded char
+ * code.
+ */
+ lxiv.encode = function(src, dst) {
+ var b, t;
+ while ((b = src()) !== null) {
+ dst(aout[(b>>2)&0x3f]);
+ t = (b&0x3)<<4;
+ if ((b = src()) !== null) {
+ t |= (b>>4)&0xf;
+ dst(aout[(t|((b>>4)&0xf))&0x3f]);
+ t = (b&0xf)<<2;
+ if ((b = src()) !== null)
+ dst(aout[(t|((b>>6)&0x3))&0x3f]),
+ dst(aout[b&0x3f]);
+ else
+ dst(aout[t&0x3f]),
+ dst(61);
+ } else
+ dst(aout[t&0x3f]),
+ dst(61),
+ dst(61);
+ }
+ };
+
+ /**
+ * Decodes base64 char codes to bytes.
+ * @param {!function():number|null} src Characters source as a function returning the next char code respectively
+ * `null` if there are no more characters left.
+ * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
+ * @throws {Error} If a character code is invalid
+ */
+ lxiv.decode = function(src, dst) {
+ var c, t1, t2;
+ function fail(c) {
+ throw Error("Illegal character code: "+c);
+ }
+ while ((c = src()) !== null) {
+ t1 = ain[c];
+ if (typeof t1 === 'undefined') fail(c);
+ if ((c = src()) !== null) {
+ t2 = ain[c];
+ if (typeof t2 === 'undefined') fail(c);
+ dst((t1<<2)>>>0|(t2&0x30)>>4);
+ if ((c = src()) !== null) {
+ t1 = ain[c];
+ if (typeof t1 === 'undefined')
+ if (c === 61) break; else fail(c);
+ dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2);
+ if ((c = src()) !== null) {
+ t2 = ain[c];
+ if (typeof t2 === 'undefined')
+ if (c === 61) break; else fail(c);
+ dst(((t1&0x3)<<6)>>>0|t2);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Tests if a string is valid base64.
+ * @param {string} str String to test
+ * @returns {boolean} `true` if valid, otherwise `false`
+ */
+ lxiv.test = function(str) {
+ return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str);
+ };
+
+ return lxiv;
+ }();
+
+ // encodings/base64
+
+ /**
+ * Encodes this ByteBuffer's contents to a base64 encoded string.
+ * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}.
+ * @returns {string} Base64 encoded string
+ * @throws {RangeError} If `begin` or `end` is out of bounds
+ * @expose
+ */
+ ByteBufferPrototype.toBase64 = function(begin, end) {
+ if (typeof begin === 'undefined')
+ begin = this.offset;
+ if (typeof end === 'undefined')
+ end = this.limit;
+ begin = begin | 0; end = end | 0;
+ if (begin < 0 || end > this.capacity || begin > end)
+ throw RangeError("begin, end");
+ var sd; lxiv.encode(function() {
+ return begin < end ? this.view[begin++] : null;
+ }.bind(this), sd = stringDestination());
+ return sd();
+ };
+
+ /**
+ * Decodes a base64 encoded string to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromBase64 = function(str, littleEndian) {
+ if (typeof str !== 'string')
+ throw TypeError("str");
+ var bb = new ByteBuffer(str.length/4*3, littleEndian),
+ i = 0;
+ lxiv.decode(stringSource(str), function(b) {
+ bb.view[i++] = b;
+ });
+ bb.limit = i;
+ return bb;
+ };
+
+ /**
+ * Encodes a binary string to base64 like `window.btoa` does.
+ * @param {string} str Binary string
+ * @returns {string} Base64 encoded string
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa
+ * @expose
+ */
+ ByteBuffer.btoa = function(str) {
+ return ByteBuffer.fromBinary(str).toBase64();
+ };
+
+ /**
+ * Decodes a base64 encoded string to binary like `window.atob` does.
+ * @param {string} b64 Base64 encoded string
+ * @returns {string} Binary string
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob
+ * @expose
+ */
+ ByteBuffer.atob = function(b64) {
+ return ByteBuffer.fromBase64(b64).toBinary();
+ };
+
+ // encodings/binary
+
+ /**
+ * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes.
+ * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
+ * @returns {string} Binary encoded string
+ * @throws {RangeError} If `offset > limit`
+ * @expose
+ */
+ ByteBufferPrototype.toBinary = function(begin, end) {
+ if (typeof begin === 'undefined')
+ begin = this.offset;
+ if (typeof end === 'undefined')
+ end = this.limit;
+ begin |= 0; end |= 0;
+ if (begin < 0 || end > this.capacity() || begin > end)
+ throw RangeError("begin, end");
+ if (begin === end)
+ return "";
+ var chars = [],
+ parts = [];
+ while (begin < end) {
+ chars.push(this.view[begin++]);
+ if (chars.length >= 1024)
+ parts.push(String.fromCharCode.apply(String, chars)),
+ chars = [];
+ }
+ return parts.join('') + String.fromCharCode.apply(String, chars);
+ };
+
+ /**
+ * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromBinary = function(str, littleEndian) {
+ if (typeof str !== 'string')
+ throw TypeError("str");
+ var i = 0,
+ k = str.length,
+ charCode,
+ bb = new ByteBuffer(k, littleEndian);
+ while (i<k) {
+ charCode = str.charCodeAt(i);
+ if (charCode > 0xff)
+ throw RangeError("illegal char code: "+charCode);
+ bb.view[i++] = charCode;
+ }
+ bb.limit = k;
+ return bb;
+ };
+
+ // encodings/debug
+
+ /**
+ * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are:
+ * * `<` : offset,
+ * * `'` : markedOffset,
+ * * `>` : limit,
+ * * `|` : offset and limit,
+ * * `[` : offset and markedOffset,
+ * * `]` : markedOffset and limit,
+ * * `!` : offset, markedOffset and limit
+ * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false`
+ * @returns {string|!Array.<string>} Debug string or array of lines if `asArray = true`
+ * @expose
+ * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3`
+ * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4`
+ * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1`
+ * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1`
+ */
+ ByteBufferPrototype.toDebug = function(columns) {
+ var i = -1,
+ k = this.buffer.byteLength,
+ b,
+ hex = "",
+ asc = "",
+ out = "";
+ while (i<k) {
+ if (i !== -1) {
+ b = this.view[i];
+ if (b < 0x10) hex += "0"+b.toString(16).toUpperCase();
+ else hex += b.toString(16).toUpperCase();
+ if (columns)
+ asc += b > 32 && b < 127 ? String.fromCharCode(b) : '.';
+ }
+ ++i;
+ if (columns) {
+ if (i > 0 && i % 16 === 0 && i !== k) {
+ while (hex.length < 3*16+3) hex += " ";
+ out += hex+asc+"\n";
+ hex = asc = "";
+ }
+ }
+ if (i === this.offset && i === this.limit)
+ hex += i === this.markedOffset ? "!" : "|";
+ else if (i === this.offset)
+ hex += i === this.markedOffset ? "[" : "<";
+ else if (i === this.limit)
+ hex += i === this.markedOffset ? "]" : ">";
+ else
+ hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : "");
+ }
+ if (columns && hex !== " ") {
+ while (hex.length < 3*16+3)
+ hex += " ";
+ out += hex + asc + "\n";
+ }
+ return columns ? out : hex;
+ };
+
+ /**
+ * Decodes a hex encoded string with marked offsets to a ByteBuffer.
+ * @param {string} str Debug string to decode (not be generated with `columns = true`)
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ * @see ByteBuffer#toDebug
+ */
+ ByteBuffer.fromDebug = function(str, littleEndian, noAssert) {
+ var k = str.length,
+ bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert);
+ var i = 0, j = 0, ch, b,
+ rs = false, // Require symbol next
+ ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)?
+ fail = false;
+ while (i<k) {
+ switch (ch = str.charAt(i++)) {
+ case '!':
+ if (!noAssert) {
+ if (ho || hm || hl) {
+ fail = true;
+ break;
+ }
+ ho = hm = hl = true;
+ }
+ bb.offset = bb.markedOffset = bb.limit = j;
+ rs = false;
+ break;
+ case '|':
+ if (!noAssert) {
+ if (ho || hl) {
+ fail = true;
+ break;
+ }
+ ho = hl = true;
+ }
+ bb.offset = bb.limit = j;
+ rs = false;
+ break;
+ case '[':
+ if (!noAssert) {
+ if (ho || hm) {
+ fail = true;
+ break;
+ }
+ ho = hm = true;
+ }
+ bb.offset = bb.markedOffset = j;
+ rs = false;
+ break;
+ case '<':
+ if (!noAssert) {
+ if (ho) {
+ fail = true;
+ break;
+ }
+ ho = true;
+ }
+ bb.offset = j;
+ rs = false;
+ break;
+ case ']':
+ if (!noAssert) {
+ if (hl || hm) {
+ fail = true;
+ break;
+ }
+ hl = hm = true;
+ }
+ bb.limit = bb.markedOffset = j;
+ rs = false;
+ break;
+ case '>':
+ if (!noAssert) {
+ if (hl) {
+ fail = true;
+ break;
+ }
+ hl = true;
+ }
+ bb.limit = j;
+ rs = false;
+ break;
+ case "'":
+ if (!noAssert) {
+ if (hm) {
+ fail = true;
+ break;
+ }
+ hm = true;
+ }
+ bb.markedOffset = j;
+ rs = false;
+ break;
+ case ' ':
+ rs = false;
+ break;
+ default:
+ if (!noAssert) {
+ if (rs) {
+ fail = true;
+ break;
+ }
+ }
+ b = parseInt(ch+str.charAt(i++), 16);
+ if (!noAssert) {
+ if (isNaN(b) || b < 0 || b > 255)
+ throw TypeError("Illegal str: Not a debug encoded string");
+ }
+ bb.view[j++] = b;
+ rs = true;
+ }
+ if (fail)
+ throw TypeError("Illegal str: Invalid symbol at "+i);
+ }
+ if (!noAssert) {
+ if (!ho || !hl)
+ throw TypeError("Illegal str: Missing offset or limit");
+ if (j<bb.buffer.byteLength)
+ throw TypeError("Illegal str: Not a debug encoded string (is it hex?) "+j+" < "+k);
+ }
+ return bb;
+ };
+
+ // encodings/hex
+
+ /**
+ * Encodes this ByteBuffer's contents to a hex encoded string.
+ * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}.
+ * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}.
+ * @returns {string} Hex encoded string
+ * @expose
+ */
+ ByteBufferPrototype.toHex = function(begin, end) {
+ begin = typeof begin === 'undefined' ? this.offset : begin;
+ end = typeof end === 'undefined' ? this.limit : end;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var out = new Array(end - begin),
+ b;
+ while (begin < end) {
+ b = this.view[begin++];
+ if (b < 0x10)
+ out.push("0", b.toString(16));
+ else out.push(b.toString(16));
+ }
+ return out.join('');
+ };
+
+ /**
+ * Decodes a hex encoded string to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromHex = function(str, littleEndian, noAssert) {
+ if (!noAssert) {
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ if (str.length % 2 !== 0)
+ throw TypeError("Illegal str: Length not a multiple of 2");
+ }
+ var k = str.length,
+ bb = new ByteBuffer((k / 2) | 0, littleEndian),
+ b;
+ for (var i=0, j=0; i<k; i+=2) {
+ b = parseInt(str.substring(i, i+2), 16);
+ if (!noAssert)
+ if (!isFinite(b) || b < 0 || b > 255)
+ throw TypeError("Illegal str: Contains non-hex characters");
+ bb.view[j++] = b;
+ }
+ bb.limit = j;
+ return bb;
+ };
+
+ // utfx-embeddable
+
+ /**
+ * utfx-embeddable (c) 2014 Daniel Wirtz <dcode@dcode.io>
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/utfx for details
+ */
+ var utfx = function() {
+ "use strict";
+
+ /**
+ * utfx namespace.
+ * @inner
+ * @type {!Object.<string,*>}
+ */
+ var utfx = {};
+
+ /**
+ * Maximum valid code point.
+ * @type {number}
+ * @const
+ */
+ utfx.MAX_CODEPOINT = 0x10FFFF;
+
+ /**
+ * Encodes UTF8 code points to UTF8 bytes.
+ * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
+ * respectively `null` if there are no more code points left or a single numeric code point.
+ * @param {!function(number)} dst Bytes destination as a function successively called with the next byte
+ */
+ utfx.encodeUTF8 = function(src, dst) {
+ var cp = null;
+ if (typeof src === 'number')
+ cp = src,
+ src = function() { return null; };
+ while (cp !== null || (cp = src()) !== null) {
+ if (cp < 0x80)
+ dst(cp&0x7F);
+ else if (cp < 0x800)
+ dst(((cp>>6)&0x1F)|0xC0),
+ dst((cp&0x3F)|0x80);
+ else if (cp < 0x10000)
+ dst(((cp>>12)&0x0F)|0xE0),
+ dst(((cp>>6)&0x3F)|0x80),
+ dst((cp&0x3F)|0x80);
+ else
+ dst(((cp>>18)&0x07)|0xF0),
+ dst(((cp>>12)&0x3F)|0x80),
+ dst(((cp>>6)&0x3F)|0x80),
+ dst((cp&0x3F)|0x80);
+ cp = null;
+ }
+ };
+
+ /**
+ * Decodes UTF8 bytes to UTF8 code points.
+ * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
+ * are no more bytes left.
+ * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point.
+ * @throws {RangeError} If a starting byte is invalid in UTF8
+ * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the
+ * remaining bytes.
+ */
+ utfx.decodeUTF8 = function(src, dst) {
+ var a, b, c, d, fail = function(b) {
+ b = b.slice(0, b.indexOf(null));
+ var err = Error(b.toString());
+ err.name = "TruncatedError";
+ err['bytes'] = b;
+ throw err;
+ };
+ while ((a = src()) !== null) {
+ if ((a&0x80) === 0)
+ dst(a);
+ else if ((a&0xE0) === 0xC0)
+ ((b = src()) === null) && fail([a, b]),
+ dst(((a&0x1F)<<6) | (b&0x3F));
+ else if ((a&0xF0) === 0xE0)
+ ((b=src()) === null || (c=src()) === null) && fail([a, b, c]),
+ dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F));
+ else if ((a&0xF8) === 0xF0)
+ ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]),
+ dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F));
+ else throw RangeError("Illegal starting byte: "+a);
+ }
+ };
+
+ /**
+ * Converts UTF16 characters to UTF8 code points.
+ * @param {!function():number|null} src Characters source as a function returning the next char code respectively
+ * `null` if there are no more characters left.
+ * @param {!function(number)} dst Code points destination as a function successively called with each converted code
+ * point.
+ */
+ utfx.UTF16toUTF8 = function(src, dst) {
+ var c1, c2 = null;
+ while (true) {
+ if ((c1 = c2 !== null ? c2 : src()) === null)
+ break;
+ if (c1 >= 0xD800 && c1 <= 0xDFFF) {
+ if ((c2 = src()) !== null) {
+ if (c2 >= 0xDC00 && c2 <= 0xDFFF) {
+ dst((c1-0xD800)*0x400+c2-0xDC00+0x10000);
+ c2 = null; continue;
+ }
+ }
+ }
+ dst(c1);
+ }
+ if (c2 !== null) dst(c2);
+ };
+
+ /**
+ * Converts UTF8 code points to UTF16 characters.
+ * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point
+ * respectively `null` if there are no more code points left or a single numeric code point.
+ * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
+ * @throws {RangeError} If a code point is out of range
+ */
+ utfx.UTF8toUTF16 = function(src, dst) {
+ var cp = null;
+ if (typeof src === 'number')
+ cp = src, src = function() { return null; };
+ while (cp !== null || (cp = src()) !== null) {
+ if (cp <= 0xFFFF)
+ dst(cp);
+ else
+ cp -= 0x10000,
+ dst((cp>>10)+0xD800),
+ dst((cp%0x400)+0xDC00);
+ cp = null;
+ }
+ };
+
+ /**
+ * Converts and encodes UTF16 characters to UTF8 bytes.
+ * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null`
+ * if there are no more characters left.
+ * @param {!function(number)} dst Bytes destination as a function successively called with the next byte.
+ */
+ utfx.encodeUTF16toUTF8 = function(src, dst) {
+ utfx.UTF16toUTF8(src, function(cp) {
+ utfx.encodeUTF8(cp, dst);
+ });
+ };
+
+ /**
+ * Decodes and converts UTF8 bytes to UTF16 characters.
+ * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there
+ * are no more bytes left.
+ * @param {!function(number)} dst Characters destination as a function successively called with each converted char code.
+ * @throws {RangeError} If a starting byte is invalid in UTF8
+ * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes.
+ */
+ utfx.decodeUTF8toUTF16 = function(src, dst) {
+ utfx.decodeUTF8(src, function(cp) {
+ utfx.UTF8toUTF16(cp, dst);
+ });
+ };
+
+ /**
+ * Calculates the byte length of an UTF8 code point.
+ * @param {number} cp UTF8 code point
+ * @returns {number} Byte length
+ */
+ utfx.calculateCodePoint = function(cp) {
+ return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
+ };
+
+ /**
+ * Calculates the number of UTF8 bytes required to store UTF8 code points.
+ * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively
+ * `null` if there are no more code points left.
+ * @returns {number} The number of UTF8 bytes required
+ */
+ utfx.calculateUTF8 = function(src) {
+ var cp, l=0;
+ while ((cp = src()) !== null)
+ l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
+ return l;
+ };
+
+ /**
+ * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes.
+ * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively
+ * `null` if there are no more characters left.
+ * @returns {!Array.<number>} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1.
+ */
+ utfx.calculateUTF16asUTF8 = function(src) {
+ var n=0, l=0;
+ utfx.UTF16toUTF8(src, function(cp) {
+ ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4;
+ });
+ return [n,l];
+ };
+
+ return utfx;
+ }();
+
+ // encodings/utf8
+
+ /**
+ * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded
+ * string.
+ * @returns {string} Hex encoded string
+ * @throws {RangeError} If `offset > limit`
+ * @expose
+ */
+ ByteBufferPrototype.toUTF8 = function(begin, end) {
+ if (typeof begin === 'undefined') begin = this.offset;
+ if (typeof end === 'undefined') end = this.limit;
+ if (!this.noAssert) {
+ if (typeof begin !== 'number' || begin % 1 !== 0)
+ throw TypeError("Illegal begin: Not an integer");
+ begin >>>= 0;
+ if (typeof end !== 'number' || end % 1 !== 0)
+ throw TypeError("Illegal end: Not an integer");
+ end >>>= 0;
+ if (begin < 0 || begin > end || end > this.buffer.byteLength)
+ throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength);
+ }
+ var sd; try {
+ utfx.decodeUTF8toUTF16(function() {
+ return begin < end ? this.view[begin++] : null;
+ }.bind(this), sd = stringDestination());
+ } catch (e) {
+ if (begin !== end)
+ throw RangeError("Illegal range: Truncated data, "+begin+" != "+end);
+ }
+ return sd();
+ };
+
+ /**
+ * Decodes an UTF8 encoded string to a ByteBuffer.
+ * @param {string} str String to decode
+ * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to
+ * {@link ByteBuffer.DEFAULT_ENDIAN}.
+ * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to
+ * {@link ByteBuffer.DEFAULT_NOASSERT}.
+ * @returns {!ByteBuffer} ByteBuffer
+ * @expose
+ */
+ ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) {
+ if (!noAssert)
+ if (typeof str !== 'string')
+ throw TypeError("Illegal str: Not a string");
+ var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert),
+ i = 0;
+ utfx.encodeUTF16toUTF8(stringSource(str), function(b) {
+ bb.view[i++] = b;
+ });
+ bb.limit = i;
+ return bb;
+ };
+
+ return ByteBuffer;
+ });
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module)))
+
+/***/ },
+/* 30 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(module) {/*
+ Copyright 2013 Daniel Wirtz <dcode@dcode.io>
+ Copyright 2009 The Closure Library Authors. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS-IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+
+ /**
+ * @license long.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/long.js for details
+ */
+ (function(global, factory) {
+
+ /* AMD */ if ("function" === 'function' && __webpack_require__(28)["amd"])
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ /* CommonJS */ else if ("function" === 'function' && typeof module === "object" && module && module["exports"])
+ module["exports"] = factory();
+ /* Global */ else
+ (global["dcodeIO"] = global["dcodeIO"] || {})["Long"] = factory();
+
+ })(this, function() {
+ "use strict";
+
+ /**
+ * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
+ * See the from* functions below for more convenient ways of constructing Longs.
+ * @exports Long
+ * @class A Long class for representing a 64 bit two's-complement integer value.
+ * @param {number} low The low (signed) 32 bits of the long
+ * @param {number} high The high (signed) 32 bits of the long
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @constructor
+ */
+ function Long(low, high, unsigned) {
+
+ /**
+ * The low 32 bits as a signed value.
+ * @type {number}
+ */
+ this.low = low | 0;
+
+ /**
+ * The high 32 bits as a signed value.
+ * @type {number}
+ */
+ this.high = high | 0;
+
+ /**
+ * Whether unsigned or not.
+ * @type {boolean}
+ */
+ this.unsigned = !!unsigned;
+ }
+
+ // The internal representation of a long is the two given signed, 32-bit values.
+ // We use 32-bit pieces because these are the size of integers on which
+ // Javascript performs bit-operations. For operations like addition and
+ // multiplication, we split each number into 16 bit pieces, which can easily be
+ // multiplied within Javascript's floating-point representation without overflow
+ // or change in sign.
+ //
+ // In the algorithms below, we frequently reduce the negative case to the
+ // positive case by negating the input(s) and then post-processing the result.
+ // Note that we must ALWAYS check specially whether those values are MIN_VALUE
+ // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
+ // a positive number, it overflows back into a negative). Not handling this
+ // case would often result in infinite recursion.
+ //
+ // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
+ // methods on which they depend.
+
+ /**
+ * An indicator used to reliably determine if an object is a Long or not.
+ * @type {boolean}
+ * @const
+ * @private
+ */
+ Long.prototype.__isLong__;
+
+ Object.defineProperty(Long.prototype, "__isLong__", {
+ value: true,
+ enumerable: false,
+ configurable: false
+ });
+
+ /**
+ * @function
+ * @param {*} obj Object
+ * @returns {boolean}
+ * @inner
+ */
+ function isLong(obj) {
+ return (obj && obj["__isLong__"]) === true;
+ }
+
+ /**
+ * Tests if the specified object is a Long.
+ * @function
+ * @param {*} obj Object
+ * @returns {boolean}
+ */
+ Long.isLong = isLong;
+
+ /**
+ * A cache of the Long representations of small integer values.
+ * @type {!Object}
+ * @inner
+ */
+ var INT_CACHE = {};
+
+ /**
+ * A cache of the Long representations of small unsigned integer values.
+ * @type {!Object}
+ * @inner
+ */
+ var UINT_CACHE = {};
+
+ /**
+ * @param {number} value
+ * @param {boolean=} unsigned
+ * @returns {!Long}
+ * @inner
+ */
+ function fromInt(value, unsigned) {
+ var obj, cachedObj, cache;
+ if (unsigned) {
+ value >>>= 0;
+ if (cache = (0 <= value && value < 256)) {
+ cachedObj = UINT_CACHE[value];
+ if (cachedObj)
+ return cachedObj;
+ }
+ obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
+ if (cache)
+ UINT_CACHE[value] = obj;
+ return obj;
+ } else {
+ value |= 0;
+ if (cache = (-128 <= value && value < 128)) {
+ cachedObj = INT_CACHE[value];
+ if (cachedObj)
+ return cachedObj;
+ }
+ obj = fromBits(value, value < 0 ? -1 : 0, false);
+ if (cache)
+ INT_CACHE[value] = obj;
+ return obj;
+ }
+ }
+
+ /**
+ * Returns a Long representing the given 32 bit integer value.
+ * @function
+ * @param {number} value The 32 bit integer in question
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @returns {!Long} The corresponding Long value
+ */
+ Long.fromInt = fromInt;
+
+ /**
+ * @param {number} value
+ * @param {boolean=} unsigned
+ * @returns {!Long}
+ * @inner
+ */
+ function fromNumber(value, unsigned) {
+ if (isNaN(value) || !isFinite(value))
+ return unsigned ? UZERO : ZERO;
+ if (unsigned) {
+ if (value < 0)
+ return UZERO;
+ if (value >= TWO_PWR_64_DBL)
+ return MAX_UNSIGNED_VALUE;
+ } else {
+ if (value <= -TWO_PWR_63_DBL)
+ return MIN_VALUE;
+ if (value + 1 >= TWO_PWR_63_DBL)
+ return MAX_VALUE;
+ }
+ if (value < 0)
+ return fromNumber(-value, unsigned).neg();
+ return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
+ }
+
+ /**
+ * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned.
+ * @function
+ * @param {number} value The number in question
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @returns {!Long} The corresponding Long value
+ */
+ Long.fromNumber = fromNumber;
+
+ /**
+ * @param {number} lowBits
+ * @param {number} highBits
+ * @param {boolean=} unsigned
+ * @returns {!Long}
+ * @inner
+ */
+ function fromBits(lowBits, highBits, unsigned) {
+ return new Long(lowBits, highBits, unsigned);
+ }
+
+ /**
+ * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
+ * assumed to use 32 bits.
+ * @function
+ * @param {number} lowBits The low 32 bits
+ * @param {number} highBits The high 32 bits
+ * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @returns {!Long} The corresponding Long value
+ */
+ Long.fromBits = fromBits;
+
+ /**
+ * @function
+ * @param {number} base
+ * @param {number} exponent
+ * @returns {number}
+ * @inner
+ */
+ var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
+
+ /**
+ * @param {string} str
+ * @param {(boolean|number)=} unsigned
+ * @param {number=} radix
+ * @returns {!Long}
+ * @inner
+ */
+ function fromString(str, unsigned, radix) {
+ if (str.length === 0)
+ throw Error('empty string');
+ if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
+ return ZERO;
+ if (typeof unsigned === 'number') {
+ // For goog.math.long compatibility
+ radix = unsigned,
+ unsigned = false;
+ } else {
+ unsigned = !! unsigned;
+ }
+ radix = radix || 10;
+ if (radix < 2 || 36 < radix)
+ throw RangeError('radix');
+
+ var p;
+ if ((p = str.indexOf('-')) > 0)
+ throw Error('interior hyphen');
+ else if (p === 0) {
+ return fromString(str.substring(1), unsigned, radix).neg();
+ }
+
+ // Do several (8) digits each time through the loop, so as to
+ // minimize the calls to the very expensive emulated div.
+ var radixToPower = fromNumber(pow_dbl(radix, 8));
+
+ var result = ZERO;
+ for (var i = 0; i < str.length; i += 8) {
+ var size = Math.min(8, str.length - i),
+ value = parseInt(str.substring(i, i + size), radix);
+ if (size < 8) {
+ var power = fromNumber(pow_dbl(radix, size));
+ result = result.mul(power).add(fromNumber(value));
+ } else {
+ result = result.mul(radixToPower);
+ result = result.add(fromNumber(value));
+ }
+ }
+ result.unsigned = unsigned;
+ return result;
+ }
+
+ /**
+ * Returns a Long representation of the given string, written using the specified radix.
+ * @function
+ * @param {string} str The textual representation of the Long
+ * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
+ * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
+ * @returns {!Long} The corresponding Long value
+ */
+ Long.fromString = fromString;
+
+ /**
+ * @function
+ * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val
+ * @returns {!Long}
+ * @inner
+ */
+ function fromValue(val) {
+ if (val /* is compatible */ instanceof Long)
+ return val;
+ if (typeof val === 'number')
+ return fromNumber(val);
+ if (typeof val === 'string')
+ return fromString(val);
+ // Throws for non-objects, converts non-instanceof Long:
+ return fromBits(val.low, val.high, val.unsigned);
+ }
+
+ /**
+ * Converts the specified value to a Long.
+ * @function
+ * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value
+ * @returns {!Long}
+ */
+ Long.fromValue = fromValue;
+
+ // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
+ // no runtime penalty for these.
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_16_DBL = 1 << 16;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_24_DBL = 1 << 24;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
+
+ /**
+ * @type {number}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
+
+ /**
+ * @type {!Long}
+ * @const
+ * @inner
+ */
+ var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var ZERO = fromInt(0);
+
+ /**
+ * Signed zero.
+ * @type {!Long}
+ */
+ Long.ZERO = ZERO;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var UZERO = fromInt(0, true);
+
+ /**
+ * Unsigned zero.
+ * @type {!Long}
+ */
+ Long.UZERO = UZERO;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var ONE = fromInt(1);
+
+ /**
+ * Signed one.
+ * @type {!Long}
+ */
+ Long.ONE = ONE;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var UONE = fromInt(1, true);
+
+ /**
+ * Unsigned one.
+ * @type {!Long}
+ */
+ Long.UONE = UONE;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var NEG_ONE = fromInt(-1);
+
+ /**
+ * Signed negative one.
+ * @type {!Long}
+ */
+ Long.NEG_ONE = NEG_ONE;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
+
+ /**
+ * Maximum signed value.
+ * @type {!Long}
+ */
+ Long.MAX_VALUE = MAX_VALUE;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
+
+ /**
+ * Maximum unsigned value.
+ * @type {!Long}
+ */
+ Long.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
+
+ /**
+ * @type {!Long}
+ * @inner
+ */
+ var MIN_VALUE = fromBits(0, 0x80000000|0, false);
+
+ /**
+ * Minimum signed value.
+ * @type {!Long}
+ */
+ Long.MIN_VALUE = MIN_VALUE;
+
+ /**
+ * @alias Long.prototype
+ * @inner
+ */
+ var LongPrototype = Long.prototype;
+
+ /**
+ * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer.
+ * @returns {number}
+ */
+ LongPrototype.toInt = function toInt() {
+ return this.unsigned ? this.low >>> 0 : this.low;
+ };
+
+ /**
+ * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa).
+ * @returns {number}
+ */
+ LongPrototype.toNumber = function toNumber() {
+ if (this.unsigned)
+ return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
+ return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
+ };
+
+ /**
+ * Converts the Long to a string written in the specified radix.
+ * @param {number=} radix Radix (2-36), defaults to 10
+ * @returns {string}
+ * @override
+ * @throws {RangeError} If `radix` is out of range
+ */
+ LongPrototype.toString = function toString(radix) {
+ radix = radix || 10;
+ if (radix < 2 || 36 < radix)
+ throw RangeError('radix');
+ if (this.isZero())
+ return '0';
+ if (this.isNegative()) { // Unsigned Longs are never negative
+ if (this.eq(MIN_VALUE)) {
+ // We need to change the Long value before it can be negated, so we remove
+ // the bottom-most digit in this base and then recurse to do the rest.
+ var radixLong = fromNumber(radix),
+ div = this.div(radixLong),
+ rem1 = div.mul(radixLong).sub(this);
+ return div.toString(radix) + rem1.toInt().toString(radix);
+ } else
+ return '-' + this.neg().toString(radix);
+ }
+
+ // Do several (6) digits each time through the loop, so as to
+ // minimize the calls to the very expensive emulated div.
+ var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
+ rem = this;
+ var result = '';
+ while (true) {
+ var remDiv = rem.div(radixToPower),
+ intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
+ digits = intval.toString(radix);
+ rem = remDiv;
+ if (rem.isZero())
+ return digits + result;
+ else {
+ while (digits.length < 6)
+ digits = '0' + digits;
+ result = '' + digits + result;
+ }
+ }
+ };
+
+ /**
+ * Gets the high 32 bits as a signed integer.
+ * @returns {number} Signed high bits
+ */
+ LongPrototype.getHighBits = function getHighBits() {
+ return this.high;
+ };
+
+ /**
+ * Gets the high 32 bits as an unsigned integer.
+ * @returns {number} Unsigned high bits
+ */
+ LongPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() {
+ return this.high >>> 0;
+ };
+
+ /**
+ * Gets the low 32 bits as a signed integer.
+ * @returns {number} Signed low bits
+ */
+ LongPrototype.getLowBits = function getLowBits() {
+ return this.low;
+ };
+
+ /**
+ * Gets the low 32 bits as an unsigned integer.
+ * @returns {number} Unsigned low bits
+ */
+ LongPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() {
+ return this.low >>> 0;
+ };
+
+ /**
+ * Gets the number of bits needed to represent the absolute value of this Long.
+ * @returns {number}
+ */
+ LongPrototype.getNumBitsAbs = function getNumBitsAbs() {
+ if (this.isNegative()) // Unsigned Longs are never negative
+ return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs();
+ var val = this.high != 0 ? this.high : this.low;
+ for (var bit = 31; bit > 0; bit--)
+ if ((val & (1 << bit)) != 0)
+ break;
+ return this.high != 0 ? bit + 33 : bit + 1;
+ };
+
+ /**
+ * Tests if this Long's value equals zero.
+ * @returns {boolean}
+ */
+ LongPrototype.isZero = function isZero() {
+ return this.high === 0 && this.low === 0;
+ };
+
+ /**
+ * Tests if this Long's value is negative.
+ * @returns {boolean}
+ */
+ LongPrototype.isNegative = function isNegative() {
+ return !this.unsigned && this.high < 0;
+ };
+
+ /**
+ * Tests if this Long's value is positive.
+ * @returns {boolean}
+ */
+ LongPrototype.isPositive = function isPositive() {
+ return this.unsigned || this.high >= 0;
+ };
+
+ /**
+ * Tests if this Long's value is odd.
+ * @returns {boolean}
+ */
+ LongPrototype.isOdd = function isOdd() {
+ return (this.low & 1) === 1;
+ };
+
+ /**
+ * Tests if this Long's value is even.
+ * @returns {boolean}
+ */
+ LongPrototype.isEven = function isEven() {
+ return (this.low & 1) === 0;
+ };
+
+ /**
+ * Tests if this Long's value equals the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.equals = function equals(other) {
+ if (!isLong(other))
+ other = fromValue(other);
+ if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
+ return false;
+ return this.high === other.high && this.low === other.low;
+ };
+
+ /**
+ * Tests if this Long's value equals the specified's. This is an alias of {@link Long#equals}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.eq = LongPrototype.equals;
+
+ /**
+ * Tests if this Long's value differs from the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.notEquals = function notEquals(other) {
+ return !this.eq(/* validates */ other);
+ };
+
+ /**
+ * Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.neq = LongPrototype.notEquals;
+
+ /**
+ * Tests if this Long's value is less than the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.lessThan = function lessThan(other) {
+ return this.comp(/* validates */ other) < 0;
+ };
+
+ /**
+ * Tests if this Long's value is less than the specified's. This is an alias of {@link Long#lessThan}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.lt = LongPrototype.lessThan;
+
+ /**
+ * Tests if this Long's value is less than or equal the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.lessThanOrEqual = function lessThanOrEqual(other) {
+ return this.comp(/* validates */ other) <= 0;
+ };
+
+ /**
+ * Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.lte = LongPrototype.lessThanOrEqual;
+
+ /**
+ * Tests if this Long's value is greater than the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.greaterThan = function greaterThan(other) {
+ return this.comp(/* validates */ other) > 0;
+ };
+
+ /**
+ * Tests if this Long's value is greater than the specified's. This is an alias of {@link Long#greaterThan}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.gt = LongPrototype.greaterThan;
+
+ /**
+ * Tests if this Long's value is greater than or equal the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) {
+ return this.comp(/* validates */ other) >= 0;
+ };
+
+ /**
+ * Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {boolean}
+ */
+ LongPrototype.gte = LongPrototype.greaterThanOrEqual;
+
+ /**
+ * Compares this Long's value with the specified's.
+ * @param {!Long|number|string} other Other value
+ * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+ * if the given one is greater
+ */
+ LongPrototype.compare = function compare(other) {
+ if (!isLong(other))
+ other = fromValue(other);
+ if (this.eq(other))
+ return 0;
+ var thisNeg = this.isNegative(),
+ otherNeg = other.isNegative();
+ if (thisNeg && !otherNeg)
+ return -1;
+ if (!thisNeg && otherNeg)
+ return 1;
+ // At this point the sign bits are the same
+ if (!this.unsigned)
+ return this.sub(other).isNegative() ? -1 : 1;
+ // Both are positive if at least one is unsigned
+ return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
+ };
+
+ /**
+ * Compares this Long's value with the specified's. This is an alias of {@link Long#compare}.
+ * @function
+ * @param {!Long|number|string} other Other value
+ * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+ * if the given one is greater
+ */
+ LongPrototype.comp = LongPrototype.compare;
+
+ /**
+ * Negates this Long's value.
+ * @returns {!Long} Negated Long
+ */
+ LongPrototype.negate = function negate() {
+ if (!this.unsigned && this.eq(MIN_VALUE))
+ return MIN_VALUE;
+ return this.not().add(ONE);
+ };
+
+ /**
+ * Negates this Long's value. This is an alias of {@link Long#negate}.
+ * @function
+ * @returns {!Long} Negated Long
+ */
+ LongPrototype.neg = LongPrototype.negate;
+
+ /**
+ * Returns the sum of this and the specified Long.
+ * @param {!Long|number|string} addend Addend
+ * @returns {!Long} Sum
+ */
+ LongPrototype.add = function add(addend) {
+ if (!isLong(addend))
+ addend = fromValue(addend);
+
+ // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
+
+ var a48 = this.high >>> 16;
+ var a32 = this.high & 0xFFFF;
+ var a16 = this.low >>> 16;
+ var a00 = this.low & 0xFFFF;
+
+ var b48 = addend.high >>> 16;
+ var b32 = addend.high & 0xFFFF;
+ var b16 = addend.low >>> 16;
+ var b00 = addend.low & 0xFFFF;
+
+ var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+ c00 += a00 + b00;
+ c16 += c00 >>> 16;
+ c00 &= 0xFFFF;
+ c16 += a16 + b16;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c32 += a32 + b32;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c48 += a48 + b48;
+ c48 &= 0xFFFF;
+ return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
+ };
+
+ /**
+ * Returns the difference of this and the specified Long.
+ * @param {!Long|number|string} subtrahend Subtrahend
+ * @returns {!Long} Difference
+ */
+ LongPrototype.subtract = function subtract(subtrahend) {
+ if (!isLong(subtrahend))
+ subtrahend = fromValue(subtrahend);
+ return this.add(subtrahend.neg());
+ };
+
+ /**
+ * Returns the difference of this and the specified Long. This is an alias of {@link Long#subtract}.
+ * @function
+ * @param {!Long|number|string} subtrahend Subtrahend
+ * @returns {!Long} Difference
+ */
+ LongPrototype.sub = LongPrototype.subtract;
+
+ /**
+ * Returns the product of this and the specified Long.
+ * @param {!Long|number|string} multiplier Multiplier
+ * @returns {!Long} Product
+ */
+ LongPrototype.multiply = function multiply(multiplier) {
+ if (this.isZero())
+ return ZERO;
+ if (!isLong(multiplier))
+ multiplier = fromValue(multiplier);
+ if (multiplier.isZero())
+ return ZERO;
+ if (this.eq(MIN_VALUE))
+ return multiplier.isOdd() ? MIN_VALUE : ZERO;
+ if (multiplier.eq(MIN_VALUE))
+ return this.isOdd() ? MIN_VALUE : ZERO;
+
+ if (this.isNegative()) {
+ if (multiplier.isNegative())
+ return this.neg().mul(multiplier.neg());
+ else
+ return this.neg().mul(multiplier).neg();
+ } else if (multiplier.isNegative())
+ return this.mul(multiplier.neg()).neg();
+
+ // If both longs are small, use float multiplication
+ if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24))
+ return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
+
+ // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+ // We can skip products that would overflow.
+
+ var a48 = this.high >>> 16;
+ var a32 = this.high & 0xFFFF;
+ var a16 = this.low >>> 16;
+ var a00 = this.low & 0xFFFF;
+
+ var b48 = multiplier.high >>> 16;
+ var b32 = multiplier.high & 0xFFFF;
+ var b16 = multiplier.low >>> 16;
+ var b00 = multiplier.low & 0xFFFF;
+
+ var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+ c00 += a00 * b00;
+ c16 += c00 >>> 16;
+ c00 &= 0xFFFF;
+ c16 += a16 * b00;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c16 += a00 * b16;
+ c32 += c16 >>> 16;
+ c16 &= 0xFFFF;
+ c32 += a32 * b00;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c32 += a16 * b16;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c32 += a00 * b32;
+ c48 += c32 >>> 16;
+ c32 &= 0xFFFF;
+ c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
+ c48 &= 0xFFFF;
+ return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned);
+ };
+
+ /**
+ * Returns the product of this and the specified Long. This is an alias of {@link Long#multiply}.
+ * @function
+ * @param {!Long|number|string} multiplier Multiplier
+ * @returns {!Long} Product
+ */
+ LongPrototype.mul = LongPrototype.multiply;
+
+ /**
+ * Returns this Long divided by the specified. The result is signed if this Long is signed or
+ * unsigned if this Long is unsigned.
+ * @param {!Long|number|string} divisor Divisor
+ * @returns {!Long} Quotient
+ */
+ LongPrototype.divide = function divide(divisor) {
+ if (!isLong(divisor))
+ divisor = fromValue(divisor);
+ if (divisor.isZero())
+ throw Error('division by zero');
+ if (this.isZero())
+ return this.unsigned ? UZERO : ZERO;
+ var approx, rem, res;
+ if (!this.unsigned) {
+ // This section is only relevant for signed longs and is derived from the
+ // closure library as a whole.
+ if (this.eq(MIN_VALUE)) {
+ if (divisor.eq(ONE) || divisor.eq(NEG_ONE))
+ return MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
+ else if (divisor.eq(MIN_VALUE))
+ return ONE;
+ else {
+ // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
+ var halfThis = this.shr(1);
+ approx = halfThis.div(divisor).shl(1);
+ if (approx.eq(ZERO)) {
+ return divisor.isNegative() ? ONE : NEG_ONE;
+ } else {
+ rem = this.sub(divisor.mul(approx));
+ res = approx.add(rem.div(divisor));
+ return res;
+ }
+ }
+ } else if (divisor.eq(MIN_VALUE))
+ return this.unsigned ? UZERO : ZERO;
+ if (this.isNegative()) {
+ if (divisor.isNegative())
+ return this.neg().div(divisor.neg());
+ return this.neg().div(divisor).neg();
+ } else if (divisor.isNegative())
+ return this.div(divisor.neg()).neg();
+ res = ZERO;
+ } else {
+ // The algorithm below has not been made for unsigned longs. It's therefore
+ // required to take special care of the MSB prior to running it.
+ if (!divisor.unsigned)
+ divisor = divisor.toUnsigned();
+ if (divisor.gt(this))
+ return UZERO;
+ if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
+ return UONE;
+ res = UZERO;
+ }
+
+ // Repeat the following until the remainder is less than other: find a
+ // floating-point that approximates remainder / other *from below*, add this
+ // into the result, and subtract it from the remainder. It is critical that
+ // the approximate value is less than or equal to the real value so that the
+ // remainder never becomes negative.
+ rem = this;
+ while (rem.gte(divisor)) {
+ // Approximate the result of division. This may be a little greater or
+ // smaller than the actual value.
+ approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
+
+ // We will tweak the approximate result by changing it in the 48-th digit or
+ // the smallest non-fractional digit, whichever is larger.
+ var log2 = Math.ceil(Math.log(approx) / Math.LN2),
+ delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
+
+ // Decrease the approximation until it is smaller than the remainder. Note
+ // that if it is too large, the product overflows and is negative.
+ approxRes = fromNumber(approx),
+ approxRem = approxRes.mul(divisor);
+ while (approxRem.isNegative() || approxRem.gt(rem)) {
+ approx -= delta;
+ approxRes = fromNumber(approx, this.unsigned);
+ approxRem = approxRes.mul(divisor);
+ }
+
+ // We know the answer can't be zero... and actually, zero would cause
+ // infinite recursion since we would make no progress.
+ if (approxRes.isZero())
+ approxRes = ONE;
+
+ res = res.add(approxRes);
+ rem = rem.sub(approxRem);
+ }
+ return res;
+ };
+
+ /**
+ * Returns this Long divided by the specified. This is an alias of {@link Long#divide}.
+ * @function
+ * @param {!Long|number|string} divisor Divisor
+ * @returns {!Long} Quotient
+ */
+ LongPrototype.div = LongPrototype.divide;
+
+ /**
+ * Returns this Long modulo the specified.
+ * @param {!Long|number|string} divisor Divisor
+ * @returns {!Long} Remainder
+ */
+ LongPrototype.modulo = function modulo(divisor) {
+ if (!isLong(divisor))
+ divisor = fromValue(divisor);
+ return this.sub(this.div(divisor).mul(divisor));
+ };
+
+ /**
+ * Returns this Long modulo the specified. This is an alias of {@link Long#modulo}.
+ * @function
+ * @param {!Long|number|string} divisor Divisor
+ * @returns {!Long} Remainder
+ */
+ LongPrototype.mod = LongPrototype.modulo;
+
+ /**
+ * Returns the bitwise NOT of this Long.
+ * @returns {!Long}
+ */
+ LongPrototype.not = function not() {
+ return fromBits(~this.low, ~this.high, this.unsigned);
+ };
+
+ /**
+ * Returns the bitwise AND of this Long and the specified.
+ * @param {!Long|number|string} other Other Long
+ * @returns {!Long}
+ */
+ LongPrototype.and = function and(other) {
+ if (!isLong(other))
+ other = fromValue(other);
+ return fromBits(this.low & other.low, this.high & other.high, this.unsigned);
+ };
+
+ /**
+ * Returns the bitwise OR of this Long and the specified.
+ * @param {!Long|number|string} other Other Long
+ * @returns {!Long}
+ */
+ LongPrototype.or = function or(other) {
+ if (!isLong(other))
+ other = fromValue(other);
+ return fromBits(this.low | other.low, this.high | other.high, this.unsigned);
+ };
+
+ /**
+ * Returns the bitwise XOR of this Long and the given one.
+ * @param {!Long|number|string} other Other Long
+ * @returns {!Long}
+ */
+ LongPrototype.xor = function xor(other) {
+ if (!isLong(other))
+ other = fromValue(other);
+ return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned);
+ };
+
+ /**
+ * Returns this Long with bits shifted to the left by the given amount.
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ */
+ LongPrototype.shiftLeft = function shiftLeft(numBits) {
+ if (isLong(numBits))
+ numBits = numBits.toInt();
+ if ((numBits &= 63) === 0)
+ return this;
+ else if (numBits < 32)
+ return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned);
+ else
+ return fromBits(0, this.low << (numBits - 32), this.unsigned);
+ };
+
+ /**
+ * Returns this Long with bits shifted to the left by the given amount. This is an alias of {@link Long#shiftLeft}.
+ * @function
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ */
+ LongPrototype.shl = LongPrototype.shiftLeft;
+
+ /**
+ * Returns this Long with bits arithmetically shifted to the right by the given amount.
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ */
+ LongPrototype.shiftRight = function shiftRight(numBits) {
+ if (isLong(numBits))
+ numBits = numBits.toInt();
+ if ((numBits &= 63) === 0)
+ return this;
+ else if (numBits < 32)
+ return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned);
+ else
+ return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned);
+ };
+
+ /**
+ * Returns this Long with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Long#shiftRight}.
+ * @function
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ */
+ LongPrototype.shr = LongPrototype.shiftRight;
+
+ /**
+ * Returns this Long with bits logically shifted to the right by the given amount.
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ */
+ LongPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) {
+ if (isLong(numBits))
+ numBits = numBits.toInt();
+ numBits &= 63;
+ if (numBits === 0)
+ return this;
+ else {
+ var high = this.high;
+ if (numBits < 32) {
+ var low = this.low;
+ return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned);
+ } else if (numBits === 32)
+ return fromBits(high, 0, this.unsigned);
+ else
+ return fromBits(high >>> (numBits - 32), 0, this.unsigned);
+ }
+ };
+
+ /**
+ * Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}.
+ * @function
+ * @param {number|!Long} numBits Number of bits
+ * @returns {!Long} Shifted Long
+ */
+ LongPrototype.shru = LongPrototype.shiftRightUnsigned;
+
+ /**
+ * Converts this Long to signed.
+ * @returns {!Long} Signed long
+ */
+ LongPrototype.toSigned = function toSigned() {
+ if (!this.unsigned)
+ return this;
+ return fromBits(this.low, this.high, false);
+ };
+
+ /**
+ * Converts this Long to unsigned.
+ * @returns {!Long} Unsigned long
+ */
+ LongPrototype.toUnsigned = function toUnsigned() {
+ if (this.unsigned)
+ return this;
+ return fromBits(this.low, this.high, true);
+ };
+
+ /**
+ * Converts this Long to its byte representation.
+ * @param {boolean=} le Whether little or big endian, defaults to big endian
+ * @returns {!Array.<number>} Byte representation
+ */
+ LongPrototype.toBytes = function(le) {
+ return le ? this.toBytesLE() : this.toBytesBE();
+ }
+
+ /**
+ * Converts this Long to its little endian byte representation.
+ * @returns {!Array.<number>} Little endian byte representation
+ */
+ LongPrototype.toBytesLE = function() {
+ var hi = this.high,
+ lo = this.low;
+ return [
+ lo & 0xff,
+ (lo >>> 8) & 0xff,
+ (lo >>> 16) & 0xff,
+ (lo >>> 24) & 0xff,
+ hi & 0xff,
+ (hi >>> 8) & 0xff,
+ (hi >>> 16) & 0xff,
+ (hi >>> 24) & 0xff
+ ];
+ }
+
+ /**
+ * Converts this Long to its big endian byte representation.
+ * @returns {!Array.<number>} Big endian byte representation
+ */
+ LongPrototype.toBytesBE = function() {
+ var hi = this.high,
+ lo = this.low;
+ return [
+ (hi >>> 24) & 0xff,
+ (hi >>> 16) & 0xff,
+ (hi >>> 8) & 0xff,
+ hi & 0xff,
+ (lo >>> 24) & 0xff,
+ (lo >>> 16) & 0xff,
+ (lo >>> 8) & 0xff,
+ lo & 0xff
+ ];
+ }
+
+ return Long;
+ });
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(12)(module)))
+
+/***/ },
+/* 31 */
+/***/ function(module, exports) {
+
+ /* (ignored) */
+
+/***/ },
+/* 32 */
+/***/ function(module, exports) {
+
+ /* (ignored) */
+
+/***/ },
+/* 33 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ var _default = "\n//start\n// pdu_def.proto\n\n// syntax = \"proto3\";\n\noption optimize_for = LITE_RUNTIME;\nenum RCPduPriority_E {\n DP_TOP = 0;\n DP_HIGH = 1;\n DP_MEDIUM = 2;\n DP_LOW = 3;\n}\n\nenum RCPduSegment_E {\n SEG_BEGIN = 0;\n SEG_END = 1;\n SEG_ONCE = 2;\n}\n\nenum RCPduTokenStatus_E {\n TS_NOT_IN_USE = 0;\n TS_SELF_GRABBED = 1;\n TS_OTHER_GRABBED = 2;\n TS_SELF_INHIBITED = 3;\n TS_OTHER_INHIBITED = 4;\n TS_SELF_RECIPIENT = 5;\n TS_SELF_GIVING = 6;\n TS_OTHER_GIVING = 7;\n}\n\nenum RCPduType_E {\n// GCC PDU\n RCPDU_CONNECT_PROVIDER_REQUEST = 0;\n RCPDU_CONNECT_PROVIDER_RESPONSE = 1;\n RCPDU_CONFERENCE_JOIN_REQUEST = 2;\n RCPDU_CONFERENCE_JOIN_RESPONSE = 3;\n RCPDU_CONFERENCE_INVITE_REQUEST = 10;\n RCPDU_CONFERENCE_INVITE_RESPONSE = 11;\n RCPDU_CONFERENCE_LOCK_REQUEST = 20;\n RCPDU_CONFERENCE_LOCK_RESPONSE = 21;\n RCPDU_CONFERENCE_LOCK_INDICATION = 22;\n RCPDU_CONFERENCE_UNLOCK_REQUEST = 30;\n RCPDU_CONFERENCE_UNLOCK_RESPONSE = 31;\n RCPDU_CONFERENCE_UNLOCK_INDICATION = 32;\n RCPDU_CONFERENCE_LEAVE_REQUEST = 39;\n RCPDU_CONFERENCE_TERMINATE_REQUEST = 40;\n RCPDU_CONFERENCE_TERMINATE_RESPONSE = 41;\n RCPDU_CONFERENCE_TERMINATE_INDICATION = 42;\n RCPDU_CONFERENCE_EJECT_USER_REQUEST = 50;\n RCPDU_CONFERENCE_EJECT_USER_RESPONSE = 51;\n RCPDU_CONFERENCE_EJECT_USER_INDICATION = 52;\n RCPDU_ROSTER_UPDATE_INDICATION = 60;\n RCPDU_REGISTRY_UPDATE_REQUEST = 70; // INCLUDE ALL OBJS OPERATION\n RCPDU_REGISTRY_UPDATE_RESPONSE = 71;\n RCPDU_REGISTRY_UPDATE_INDICATION = 72;\n RCPDU_FUNCTION_NOT_SUPPORTED_RESPONSE = 80;\n\n // MCS PDU\n RCPDU_SESSION_JOIN_REQUEST = 90;\n RCPDU_SESSION_JOIN_RESPONSE = 91;\n RCPDU_CHANNEL_GRAB_REQUEST = 100;\n RCPDU_CHANNEL_GRAB_RESPONSE = 101;\n RCPDU_CHANNEL_GRAB_INDICATION = 102;\n RCPDU_CHANNEL_JOIN_REQUEST = 103;\n RCPDU_CHANNEL_JOIN_RESPONSE = 104;\n RCPDU_CHANNEL_LEAVE_REQUEST = 105;\n RCPDU_CHANNEL_RELEASE_REQUEST = 106;\n RCPDU_CHANNEL_RELEASE_INDICATION = 107;\n RCPDU_SEND_DATA_REQUEST = 120;\n RCPDU_SEND_DATA_INDICATION = 121;\n RCPDU_UNIFORM_SEND_DATA_REQUEST = 125;\n RCPDU_UNIFORM_SEND_DATA_INDICATION = 126;\n RCPDU_TOKEN_GRAB_REQUEST = 130;\n RCPDU_TOKEN_GRAB_CONFIRM = 131;\n RCPDU_TOKEN_INHIBIT_REQUEST = 132;\n RCPDU_TOKEN_INHIBIT_CONFIRM = 133;\n RCPDU_TOKEN_GIVE_REQUEST = 134;\n RCPDU_TOKEN_GIVE_INDICATION = 135;\n RCPDU_TOKEN_GIVE_RESPONSE = 136;\n RCPDU_TOKEN_GIVE_CONFIRM = 137;\n RCPDU_TOKEN_PLEASE_REQUEST = 138;\n RCPDU_TOKEN_PLEASE_INDICATION = 139;\n RCPDU_TOKEN_RELEASE_REQUEST = 140;\n RCPDU_TOKEN_RELEASE_CONFIRM = 141;\n RCPDU_TOKEN_TEST_REQUEST = 142;\n RCPDU_TOKEN_TEST_CONFIRM = 143;\n\n // Registry PDU\n RCPDU_REG_REGISTER_KEY = 200;\n RCPDU_REG_UNREGISTER_KEY = 201;\n RCPDU_REG_REGISTER_ROSTER = 202;\n RCPDU_REG_REGISTER_TOKEN = 203;\n RCPDU_REG_REGISTER_PARAMETER = 204;\n RCPDU_REG_REGISTER_COUNTER = 205;\n RCPDU_REG_REGISTER_TABLE = 206;\n RCPDU_REG_REGISTER_CACHE = 207;\n RCPDU_REG_REGISTER_OBJ = 208;\n RCPDU_REG_UNREGISTER_OBJ = 209;\n RCPDU_REG_UPDATE_OBJ = 210;\n RCPDU_REG_ADAPTER = 211;\n RCPDU_REG_CLEANUP_NODE = 212;\n RCPDU_REG_REGISTER_QUEUE = 213;\n\n // Registry Obj update PDU\n RCPDU_REG_TABLE_INSERT_PDU = 230;\n RCPDU_REG_TABLE_DELETE_PDU = 231;\n RCPDU_REG_TABLE_UPDATE_PDU = 232;\n RCPDU_REG_ROSTER_INSERT_PDU = 240;\n RCPDU_REG_ROSTER_DELETE_PDU = 241;\n RCPDU_REG_ROSTER_UPDATE_PDU = 242;\n RCPDU_REG_PARAMETER_UPDATE_PDU = 250;\n RCPDU_REG_QUEUE_INSERT_PDU = 255;\n RCPDU_REG_QUEUE_DELETE_PDU = 256;\n RCPDU_REG_QUEUE_UPDATE_PDU = 257;\n\n // data\n RCPDU_CONFERENCE_SEND_DATA_REQUEST = 259;\n RCPDU_VIDEO_SEND_DATA_REQUEST = 260;\n RCPDU_AUDIO_SEND_DATA_REQUEST = 261;\n RCPDU_GIFT_SEND_DATA_REQUEST = 262;\n RCPDU_CHAT_SEND_DATA_REQUEST = 263;\n RCPDU_VOTING_POLL_RECORD = 265;\n RCPDU_CONFERENCE_RECORD_REQUEST = 270;\n\n // Registry resource request or response PDU\n RCPDU_REG_REQUEST_OBJ = 290;\n RCPDU_REG_RESPONSE_OBJ = 291;\n RCPDU_REG_COUNTER_REQUEST_PDU = 292;\n RCPDU_REG_COUNTER_RESPONSE_PDU = 293;\n\n // Index exchange\n RCPDU_INDEX_ADAPTER = 300;\n RCPDU_INDEX_SERVER_USERS = 301;\n RCPDU_INDEX_CONFERENCE_USER_JOINED = 302;\n RCPDU_INDEX_CONFERENCE_USER_EXITED = 303;\n RCPDU_INDEX_CONFERENCE_USERS = 304;\n\n\n\n\n //new data\n RCPDU_SEND_CONFERENCE_DATA_REQUEST =500;\n RCPDU_SEND_VIDEO_DATA_REQUEST = 501;\n RCPDU_SEND_AUDIO_DATA_REQUEST = 502;\n RCPDU_SEND_GIFT_DATA_REQUEST = 503;\n RCPDU_SEND_CHAT_DATA_REQUEST = 504;\n\n}\n\nenum RCPduNodeType_E {\n NT_TERMINAL = 0;\n NT_MULTIPORT_TERMINAL = 1;\n NT_MCU = 2;\n}\n\nenum RCPduReason_E {\n RSN_USERINITIATED = 0;\n RSN_DISCONNECTED = 1;\n RSN_SUPER_LEFT = 2;\n}\n\nenum RCPduResult_E {\n RET_SUCCESS = 0;\n RET_USER_REJECTED = 1;\n RET_INVALID_CONFERENCE = 2;\n RET_INVALID_PASSWORD = 3;\n RET_INVALID_CONVENER_PASSWORD = 4;\n RET_CHALLENGE_RESPONSE_REQUIRED = 5;\n RET_INVALID_CHALLENGE_RESPONSE = 6;\n RET_NO_CONNECTION = 7;\n RET_FULL_CAPACITY = 8;\n}\n\nenum RCPduNodeCategory_E {\n NC_CONVENTIONAL = 0;\n NC_COUNTED = 1;\n NC_ANONYMOUS = 2;\n}\n\nmessage RCConferenceDescriptorPdu {\n required uint32 id = 1;\n required string name = 2;\n optional bytes description = 3;\n optional uint32 mode = 4;\n optional string password = 5;\n optional uint32 capacity = 6;\n optional bytes user_data = 7;\n}\n\nmessage RCNodeRecordPdu {\n required uint32 id = 1;\n optional uint32 superior_node = 2;\n required RCPduNodeType_E type = 3;\n required string name = 4;\n required uint32 capability = 5;\n optional string net_address = 6;\n optional RCPduNodeCategory_E category = 7;\n}\n\nmessage RCApplicationRecordPdu {\n required uint32 id = 1; // session id\n required string name = 2;\n required string tag = 3;\n repeated uint32 channel_ids = 4 [packed = true];\n optional uint32 capability = 5;\n}\n\n//reg.proto\n\noption optimize_for = LITE_RUNTIME;\nmessage RCRegistryRegisterKeyPdu {\n required RCPduType_E type = 1 [default = RCPDU_REG_REGISTER_KEY];\n required uint32 id = 2;\n required string name = 3;\n required string tag = 4;\n optional bytes user_data = 5;\n}\n\nmessage RCRegistryUnregisterKeyPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_UNREGISTER_KEY];\n required uint32 key_id = 2;\n}\n\nmessage RCRegistryRegisterObjPdu {\n optional RCPduType_E type = 1;\n required uint32 obj_id = 2;\n required string name = 3;\n required string tag = 4;\n optional uint32 owner = 5;\n optional bytes user_data = 6;\n}\n\nmessage RCRegistryUnregisterObjPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_UNREGISTER_OBJ];\n required uint32 obj_id = 2;\n}\n\nmessage RCRegistryUpdateObjPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_UPDATE_OBJ];\n required RCPduType_E sub_type = 2;\n required uint32 obj_id = 3;\n required bytes user_data = 4;\n}\n\nmessage RCAdapterItemPdu {\n required RCPduType_E type = 1;\n required bytes item_data = 2;\n}\n\n// adapter pdu that used to package a list of pdu.\nmessage RCAdapterPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_ADAPTER];\n repeated RCAdapterItemPdu item = 2;\n}\n\n// table operation pdu\nmessage RCRegistryTableItemPdu {\n required uint32 item_idx = 1;\n required uint32 owner = 2;\n required bytes item_data = 3;\n optional uint32 register_obj_id=4;\n}\n\nmessage RCRegistryTableInsertItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_INSERT_PDU];\n repeated RCRegistryTableItemPdu items = 2;\n}\n\nmessage RCRegistryTableDeleteItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_DELETE_PDU];\n repeated uint32 item_idx = 2;\n}\n\nmessage RCRegistryTableUpdateItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];\n repeated RCRegistryTableItemPdu items = 2;\n}\n\n// roster operation pdu\nmessage RCRegistryRosterItemPdu {\n required uint32 node_id = 1;\n required bytes node_data = 2;\n}\nmessage RCRegistryWBItemPdu {\n required uint32 node_id = 1;\n required bytes node_data = 2;\n}\nmessage RCRegistryRosterInsertItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_ROSTER_INSERT_PDU];\n repeated RCRegistryRosterItemPdu items = 2;\n}\n\nmessage RCRegistryRosterDeleteItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_ROSTER_DELETE_PDU];\n required uint32 node_id = 2;\n}\n\nmessage RCRegistryRosterUpdateItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_ROSTER_UPDATE_PDU];\n repeated RCRegistryRosterItemPdu items = 2;\n}\n\n//message RCCleanupNodePdu\n//{\n// optional RCPduType_E type = 1 [default = RCPDU_REG_CLEANUP_NODE];\n// required uint32 node_id = 2;\n//}\n\n// parameter operation pdu\nmessage RCRegistryParameterUpdatePdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_PARAMETER_UPDATE_PDU];\n required uint32 value = 2 [default = 0];\n optional uint32 begin_bit = 3 [default = 31];\n optional uint32 end_bit = 4;\n}\n\n// queue operation pdu\nmessage RCRegistryQueueItemPdu {\n required uint32 owner = 1;\n required uint32 item_id = 2;\n optional bytes item_data = 3;\n optional uint32 item_idx = 4;\n}\n\nmessage RCRegstryQueueInsertItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_QUEUE_INSERT_PDU];\n repeated RCRegistryQueueItemPdu items = 2;\n}\n\nmessage RCRegistryQueueDeleteItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_QUEUE_DELETE_PDU];\n required uint32 item_id = 2;\n}\n\nmessage RCRegistryQueueUpdateItemPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_QUEUE_UPDATE_PDU];\n repeated RCRegistryQueueItemPdu items = 2;\n}\n\nmessage RCRegistryRequestObjPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_REQUEST_OBJ];\n required RCPduType_E sub_type = 2;\n required uint32 obj_id = 3;\n required bytes user_data = 4;\n}\n\nmessage RCRegistryResponseObjPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_RESPONSE_OBJ];\n required RCPduType_E sub_type = 2;\n required uint32 obj_id = 3;\n required bytes user_data = 4;\n}\n\nmessage RCRegistryCounterRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_COUNTER_REQUEST_PDU];\n required uint32 count = 2;\n}\n\nmessage RCRegistryCounterResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_REG_COUNTER_RESPONSE_PDU];\n required uint32 start = 2;\n required uint32 end = 3;\n}\n\n// mcs\noption optimize_for = LITE_RUNTIME;\n\n// Session management\nmessage RCSessionJoinRequestPdu {\n required RCPduType_E type = 1 [default = RCPDU_SESSION_JOIN_REQUEST];\n required uint32 id = 2;\n required string name = 3;\n required string tag = 4;\n optional bytes session_data = 5; //\u805A\u5408\u5728\u4E00\u8D77\u7684registry\u4FE1\u606F\n}\n\nmessage RCSessionJoinResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_SESSION_JOIN_RESPONSE];\n required uint32 id = 2;\n optional bytes response_data = 3;\n}\n\n// Channel management\nmessage RCChannelGrabRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CHANNEL_GRAB_REQUEST];\n required uint32 initiator = 2;\n required uint32 channel_id = 3;\n}\n\nmessage RCChannelGrabResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_CHANNEL_GRAB_RESPONSE];\n required uint32 initiator = 2;\n required uint32 requested_channel_id = 3;\n required RCPduResult_E result = 4;\n optional uint32 channel_id = 5;\n}\n\nmessage RCChannelGrabIndicationPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CHANNEL_GRAB_INDICATION];\n required uint32 initiator = 2;\n optional uint32 channel_id = 3;\n}\n\nmessage RCChannelJoinRequestPdu {\n required RCPduType_E type = 1 [default = RCPDU_CHANNEL_JOIN_REQUEST];\n required uint32 initiator = 2;\n required uint32 channel_id = 3;\n}\n\nmessage RCChannelJoinResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_CHANNEL_JOIN_RESPONSE];\n required uint32 initiator = 2;\n required uint32 requested_channel_id = 3;\n required RCPduResult_E result = 4;\n}\n\nmessage RCChannelLeaveRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CHANNEL_LEAVE_REQUEST];\n required uint32 initiator = 2;\n repeated uint32 channel_ids = 3 [packed = true];\n}\n\nmessage RCChannelReleaseRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CHANNEL_RELEASE_REQUEST];\n required uint32 initiator = 2;\n required uint32 channel_id = 3;\n}\n\nmessage RCChannelReleaseIndicationPdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CHANNEL_RELEASE_INDICATION];\n required uint32 initiator = 2;\n required uint32 channel_id = 3;\n}\n\n// Data transfer\nmessage RCSendDataPdu {\n required RCPduType_E type = 1 [default = RCPDU_SEND_DATA_REQUEST];\n required RCPduType_E sub_type = 2;\n required uint32 initiator = 3;\n required uint32 conf_id = 4;\n required uint32 session_id = 5;\n required uint32 channel_id = 6;\n required bool upward = 7;\n required bool reliability = 8;\n required RCPduPriority_E priority = 9;\n required bytes data = 10;\n optional uint32 peer = 11;\n optional RCPduSegment_E seg = 12;\n optional uint32 total_size = 13;\n optional uint32 site_id = 14;\n optional string user_id = 15;\n optional string user_name = 16;\n optional string user_role = 17;\n optional string device_type = 18;\n optional string site = 19;\n}\n\n// Token management\nmessage RCTokenGrabRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_GRAB_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n}\n\nmessage RCTokenGrabConfirmPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_GRAB_CONFIRM];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n required RCPduResult_E result = 4;\n required RCPduTokenStatus_E status = 5;\n}\n\nmessage RCTokenInhibitRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_INHIBIT_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n}\n\nmessage RCTokenInhibitConfirmPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_INHIBIT_CONFIRM];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n required RCPduResult_E result = 4;\n required RCPduTokenStatus_E status = 5;\n}\n\nmessage RCTokenGiveRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_GIVE_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n required uint64 recipient = 4;\n}\n\nmessage RCTokenGiveIndicationPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_GIVE_INDICATION];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n required uint64 recipient = 4;\n}\n\nmessage RCTokenGiveResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_GIVE_RESPONSE];\n required uint32 token_id = 2;\n required uint64 recipient = 3;\n required RCPduResult_E result = 4;\n}\n\nmessage RCTokenGiveConfirmPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_GIVE_CONFIRM];\n required uint32 token_id = 2;\n required uint64 recipient = 3;\n required RCPduResult_E result = 4;\n required RCPduTokenStatus_E status = 5;\n}\n\nmessage RCTokenPleaseRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_PLEASE_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n}\n\nmessage RCTokenPleaseIndicationPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_PLEASE_INDICATION];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n}\n\nmessage RCTokenReleaseRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_RELEASE_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n}\n\nmessage RCTokenReleaseConfirmPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_TEST_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n required RCPduResult_E result = 4;\n required RCPduTokenStatus_E status = 5;\n}\n\nmessage RCTokenTestRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_TEST_REQUEST];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n}\n\nmessage RCTokenTestConfirmPdu {\n optional RCPduType_E type = 1 [default = RCPDU_TOKEN_TEST_CONFIRM];\n required uint32 initiator = 2;\n required uint32 token_id = 3;\n required RCPduTokenStatus_E status = 4;\n}\n\n//gcc.proto\n\noption optimize_for = LITE_RUNTIME;\nmessage RCConferenceJoinRequestPdu {\n required RCPduType_E type = 1 [default = RCPDU_CONFERENCE_JOIN_REQUEST];\n required uint32 initiator = 2;\n required RCPduNodeType_E node_type = 3;\n required RCConferenceDescriptorPdu class_description = 4;//conf_desc\n}\n\nmessage RCConferenceJoinResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_CONFERENCE_JOIN_RESPONSE];\n required uint32 conf_id = 2;\n required RCPduResult_E result = 3;\n optional RCConferenceDescriptorPdu class_description = 4;\n}\n\nmessage RCConferenceInviteRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CONFERENCE_INVITE_REQUEST];\n required uint32 initiator = 2;\n required RCConferenceDescriptorPdu class_description = 3;\n}\n\nmessage RCConferenceInviteResponsePdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_INVITE_RESPONSE];\n required RCPduResult_E result = 2;\n optional bytes user_data = 3;\n}\n\nmessage RCConferenceLockRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CONFERENCE_LOCK_REQUEST];\n}\n\nmessage RCConferenceLockResponsePdu {\n optional RCPduType_E type = 1 [default = RCPDU_CONFERENCE_LOCK_RESPONSE];\n required RCPduResult_E result = 2;\n}\n\nmessage RCConferenceLockIndicationPdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_LOCK_INDICATION];\n}\n\nmessage RCConferenceUnlockRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CONFERENCE_UNLOCK_REQUEST];\n}\n\nmessage RCConferenceUnlockResponsePdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_UNLOCK_RESPONSE];\n required RCPduResult_E result = 2;\n}\n\nmessage RCConferenceUnlockIndicationPdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_UNLOCK_INDICATION];\n}\n\nmessage RCConferenceLeaveRequestPdu {\n optional RCPduType_E type = 1 [default = RCPDU_CONFERENCE_LEAVE_REQUEST];\n required RCPduReason_E reason = 2;\n}\n\nmessage RCConferenceTerminateRequestPdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_TERMINATE_REQUEST];\n required RCPduReason_E reason = 2;\n}\n\nmessage RCConferenceTerminateResponsePdu {\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_TERMINATE_RESPONSE];\n required RCPduResult_E result = 2;\n}\n\nmessage RCConferenceTerminateIndicationPdu { // MCS_Uniform_Send_Data on GCC_Broadcast_Channel\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_TERMINATE_INDICATION];\n required RCPduReason_E reason = 2;\n}\n\nmessage RCConferenceEjectUserRequestPdu { // MCS_Send_Data on Node ID Channel of Top GCC\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_EJECT_USER_REQUEST];\n required uint32 ejected_node_id = 2;\n required RCPduReason_E reason = 3;\n}\n\nmessage RCConferenceEjectUserResponsePdu { // MCS_Send_Data on Node ID Channel of requester\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_EJECT_USER_RESPONSE];\n required uint32 ejected_node_id = 2;\n required RCPduResult_E result = 3;\n}\n\nmessage RCConferenceEjectUserIndicationPdu { // MCS_Uniform_Send_Data on GCC_Broadcast_Channel\n optional RCPduType_E type = 1\n [default = RCPDU_CONFERENCE_EJECT_USER_INDICATION];\n required uint32 ejected_node_id = 2;\n required RCPduReason_E reason = 3;\n}\n\nmessage RCRosterUpdateIndicationPdu { // MCS_Send_Data on Node ID Channel or\n// MCS_Uniform_Send_Data on GCC_Broadcast_Channel\n optional RCPduType_E type = 1 [default = RCPDU_ROSTER_UPDATE_INDICATION];\n required bool full_refresh = 2; // Conference Roster and all\n repeated RCNodeRecordPdu node_record = 3;\n repeated RCApplicationRecordPdu app_record = 4;\n}\n\nmessage RCRegistryUpdateRequestPdu { // MCS_Send_Data on Node ID Channel of Top GCC\n optional RCPduType_E type = 1 [default = RCPDU_REGISTRY_UPDATE_REQUEST];\n required uint32 key_id = 2;\n required uint32 obj_id = 3;\n required bytes user_data = 4;\n}\n\nmessage RCRegistryUpdateIndicationPdu { // MCS_Send_Data on Node ID Channel of Top GCC\n optional RCPduType_E type = 1 [default = RCPDU_REGISTRY_UPDATE_RESPONSE];\n required uint32 key_id = 2;\n required uint32 obj_id = 3;\n required bytes user_data = 4;\n}\n\nmessage RCRegistryUpdateResponsePdu { // MCS_Send_Data on Node ID Channel of requester\n optional RCPduType_E type = 1 [default = RCPDU_REGISTRY_UPDATE_INDICATION];\n required uint32 key_id = 2;\n required uint32 obj_id = 3;\n required RCPduResult_E result = 4;\n}\n\nmessage RCFunctionNotSupportedResponsePdu {\n optional RCPduType_E type = 1\n [default = RCPDU_FUNCTION_NOT_SUPPORTED_RESPONSE];\n required uint32 request_pdu_id = 2;\n}\n\n//ape.proto\n\noption optimize_for = LITE_RUNTIME;\nmessage RCConferenceSendDataRequestPdu {\n optional uint32 initiator = 1;\n optional uint32 peer = 2;\n required bool is_public = 3;\n required bytes user_data = 4;\n optional uint32 action_type = 5;//\u6D88\u606F\u7684\u6307\u4EE4\u7C7B\u578B\n}\n\nmessage RCChatSendDataRequestPdu {\n optional uint32 initiator = 1;\n optional uint32 peer = 2;\n required bool is_public = 3;\n required bytes user_data = 4;\n required string from_role = 5;\n required bytes from_name = 6;\n}\n\nmessage RCDocSendDataModelPdu {\n required uint32 item_idx=1;//\u552F\u4E00\u6807\u8BC6\n required uint32 owner=2;\n optional uint32 from=3;\n optional uint32 cur_page_no=4;\n optional uint32 page_num =5;\n optional string file_type=6;\n optional string creat_user_id=7;//\u521B\u5EFA\u6587\u6863userid\n optional string relative_url=8;//\u6587\u6863\u76F8\u5BF9\u5730\u5740\n optional string url =9;//\u6587\u6863\u5730\u5740\n optional uint32 cur_V=10;\n optional uint32 cur_H=11;\n optional uint32 scale=12;\n optional bool visible=13;\n optional uint32 action=14;//0\uFF0C\u65E0\u64CD\u4F5C\uFF0C 1\u7FFB\u9875\u30012.\u663E\u793A/\u9690\u85CF\n optional string doc_id=15;//\u6587\u6863\u5728\u670D\u52A1\u5668\u6570\u636E\u5E93\u4E2D\u7684\u552F\u4E00id\n optional string file_name=16;//\u6587\u6863\u7684\u540D\u5B57\n optional string dynamic_TS=17;//\"dynamicTransferStatic\": \"0\"\n optional string md5=18;//md5\n\n}\nmessage RCGiftSendDataRequestPdu {\n optional uint32 initiator = 1;\n required uint32 peer = 2;\n required uint32 index = 3;\n required uint32 num = 4;\n optional bytes user_data = 5;\n}\n\nmessage RCAudioSendDataRequestPdu1 {\n optional uint32 initiator = 1;\n required bytes user_data = 2;\n}\nmessage RCAudioSendDataRequestPdu {\n required uint32 from_node_id = 1;//\u53D1\u8D77\u4EBA\n optional uint32 to_node_id = 2;//\u63A5\u6536\u4EBA\uFF0C\u5982\u679C\u662F0\u5C31\u662F\u6240\u6709\u4EBA\u90FD\u63A5\u6536\n optional uint32 actionType = 3;//\u6D88\u606F\u6307\u4EE4\u7C7B\u578B;\n optional bytes data = 4;//\u5176\u4ED6\u6570\u636E\uFF0C\u8FD9\u4E2A\u6839\u636EactionType\u6765\u786E\u5B9A\u6570\u636E\u7684\u7ED3\u6784\n}\n\nmessage RCVideoSendDataRequestPdu {\n required uint32 from_node_id = 1;//\u53D1\u8D77\u4EBA\n optional uint32 to_node_id = 2;//\u63A5\u6536\u4EBA\uFF0C\u5982\u679C\u662F0\u5C31\u662F\u6240\u6709\u4EBA\u90FD\u63A5\u6536\n optional uint32 actionType = 3;//\u6D88\u606F\u6307\u4EE4\u7C7B\u578B;\n optional bytes data = 4;//\u5176\u4ED6\u6570\u636E\uFF0C\u8FD9\u4E2A\u6839\u636EactionType\u6765\u786E\u5B9A\u6570\u636E\u7684\u7ED3\u6784\n}\n\nmessage RCAudioChannelInfoRecordPdu {\n required uint32 status = 1;\n required uint32 device_id = 2;\n required uint32 framerate = 3;\n required uint32 bitrate = 4;\n required uint32 codec = 5;\n}\nmessage RCAudioChannelInfoPdu {\n optional uint32 status = 1;//\u5F00\u542F\u7684\u72B6\u6001\n optional uint32 channel_id = 2;//\u552F\u4E00\u7684\u9891\u9053id\n optional uint32 timestamp = 3;//\u66F4\u65B0\u7684\u65F6\u95F4\u6233\n optional uint32 from_node_id = 4;//\u53D1\u8D77\u8005\u7684id\n optional uint32 to_node_id = 5;//\u63A5\u6536\u8005\u7684id\uFF0C(\u5982\u679C\u662F0\uFF0C\u6240\u6709\u4EBA\u90FD\u63A5\u6536)\n optional uint32 media_type = 6;//\u5A92\u4F53\u7C7B\u578B\uFF1A\u89C6\u9891(\u5305\u542B\u97F3\u9891)\u6216\u97F3\u9891\n optional uint32 class_id = 7;//\u8BFE\u5802\u53F7\n optional string site_id = 8;//\u7AD9\u70B9\u53F7\n optional string user_id = 9;//\u7528\u6237\u7684userId\n optional string stream_id = 10;//\u6D41\u540D\u79F0\n}\n\nmessage RCVideoChannelInfoPdu {\n optional uint32 status = 1;//\u5F00\u542F\u7684\u72B6\u6001\n optional uint32 channel_id = 2;//\u552F\u4E00\u7684\u9891\u9053id\n optional uint32 timestamp = 3;//\u66F4\u65B0\u7684\u65F6\u95F4\u6233\n optional uint32 from_node_id = 4;//\u53D1\u8D77\u8005\u7684id\n optional uint32 to_node_id = 5;//\u63A5\u6536\u8005\u7684id\uFF0C(\u5982\u679C\u662F0\uFF0C\u6240\u6709\u4EBA\u90FD\u63A5\u6536)\n optional uint32 media_type = 6;//\u5A92\u4F53\u7C7B\u578B\uFF1A\u89C6\u9891(\u5305\u542B\u97F3\u9891)\u6216\u97F3\u9891\n optional uint32 class_id = 7;//\u8BFE\u5802\u53F7\n optional string site_id = 8;//\u7AD9\u70B9\u53F7\n optional string user_id = 9;//\u7528\u6237\u7684userId\n optional string stream_id = 10;//\u6D41\u540D\u79F0\n}\n\nmessage RCVideoChannelInfoRecordPdu {\n optional uint32 status = 1;\n optional uint32 device_id = 2;\n optional uint32 width = 3;\n optional uint32 height = 4;\n optional uint32 framerate = 5;\n optional uint32 bitrate = 6;\n optional uint32 codec = 7;\n optional string peer_id = 8;\n optional string url = 9;\n optional uint32 type = 10;\n optional string shamlive = 11;\n optional uint32 livetype = 12;\n optional uint32 releaseGrab = 13;\n optional string curTime = 14;\n}\n\nmessage RCAudioDeviceInfoRecordPdu {\n required uint32 device_id = 1;\n required string device_name = 2;\n}\n\nmessage RCVideoDeviceInfoRecordPdu {\n required uint32 device_id = 1;\n required string device_name = 2;\n}\n\nmessage RCNodeInfoRecordPdu {\n required uint32 node_id = 1;\n required string name = 2;\n required uint32 role = 3;\n required uint32 level = 4;\n repeated RCAudioDeviceInfoRecordPdu audio_records = 5;\n repeated RCVideoDeviceInfoRecordPdu video_records = 6;\n optional uint32 status = 7;\n optional bytes user_data = 8;\n optional string user_id = 9;\n optional uint32 handUpTime = 10;\n optional uint32 deviceType = 11;\n optional uint32 mobileDirection = 12;\n}\n\nmessage RCVotingPollSettingsPdu {\n required bool timer = 1;\n optional uint32 time_limit = 2;\n optional uint32 total_score = 3;\n}\n\nmessage RCVotingPollResultPdu {\n required string title = 1;\n required string content = 2;\n optional uint32 score = 3;\n}\n\nmessage RCVotingPollQuestionPdu {\n required uint32 index = 1;\n required uint32 type = 2;\n required string title = 3;\n repeated string options = 4;\n optional uint32 score = 5;\n optional uint32 time_limit = 6;\n optional string restrict_input = 7;\n optional uint32 char_limit = 8;\n optional string answer = 9;\n repeated uint32 selections = 10;\n repeated string responses = 11;\n}\n\nmessage RCVotingPollRecordPdu {\n required RCVotingPollSettingsPdu settings = 1;\n required string title = 2;\n repeated RCVotingPollResultPdu results = 3;\n repeated RCVotingPollQuestionPdu questions = 4;\n}\n\nmessage RCNodeInfoUserDataPdu {\n optional string device = 1;//\u8BBE\u5907\u540D\u79F0\n optional bool has_camera = 2;//\u662F\u5426\u6709\u6444\u50CF\u5934\u53EF\u7528\n optional bool has_microphone = 3;//\u9EA6\u514B\u98CE\u662F\u5426\u53EF\u7528\n optional string browser = 4;//\u6D4F\u89C8\u5668\n optional string qq = 5;//qq\n optional string skype = 6;//skype\n}\n\nmessage RCTabUpdateDataRequestPdu {\n optional uint32 id = 1;\n optional bytes action = 2;\n optional uint32 uncomprLen =3;\n}\n\nmessage RCWhiteBoardDataModelPdu {\n required uint32 type= 1;//\u767D\u677F\u7C7B\u578B\n required uint32 itemIdx= 2;//itemIdx \u6BCF\u4E00\u6B21\u7ED8\u5236\u7684\u552F\u4E00\u6807\u8BC6\n required uint32 initiator=3; //\u7ED8\u5236\u6765\u81EA\u8C01\n required uint32 parentId=4; //\u7236\u7EA7\u7684id\n required uint32 cur_page_no= 5;//\u9875\u7801\n optional string pointGroup=6; //\u5750\u6807\u70B9\u96C6\u6570\u7EC4\u7684JSON\u5B57\u7B26\u4E32\n optional string color=7 [default = \"#000000\"]; //\u989C\u8272\n optional uint32 thickness= 8 ;//\u7EBF\u6761\u7C97\u7EC6\n optional uint32 radius= 9;//\u56ED\u7684\u534A\u5F84\n optional uint32 fontSize= 10;//\u5B57\u4F53\u5927\u5C0F\n optional string fontName= 11;//\u5B57\u4F53\u540D\u79F0\n optional string text= 12;//\u6587\u672C\u5185\u5BB9\n optional bytes data = 13;//\u6682\u65F6\u9884\u7559\u7684\u53C2\u6570\n}\nmessage RCClassSendDataModelPdu {\n optional uint32 item_idx=1;\n optional uint32 from=2;\n optional uint32 owner=3;\n optional uint32 action_type=4;//\u72B6\u6001\u6539\u53D8\u7684\u7C7B\u578B\n optional RCClassStatusInfoPdu class_status_info=5;//\u5F53\u524D\u8BFE\u5802\u72B6\u6001\u7684\u4FE1\u606F\n}\nmessage RCClassStatusInfoPdu {\n optional uint32 node_id=1;//mcu\u4E2D\u7684\u552F\u4E00ID\n optional string user_id=2;\n optional string user_name=3;\n optional string site_id=4;//\u7AD9\u70B9\u53F7\n optional uint32 class_id=5;\n optional string class_name=6;\n required uint32 class_type=7;//\u8BFE\u5802\u7C7B\u578B\n required uint32 class_status=9;//\u8BFE\u5802\u7684\u72B6\u6001\n optional string class_startTime=10;//\u8BFE\u5802\u70B9\u51FB\u5F00\u59CB\u65F6\u95F4\n optional string class_stopTime=11;//\u6700\u540E\u4E00\u6B21\u505C\u6B62\u7684\u65F6\u95F4(\u70B9\u6682\u505C\u6216\u7ED3\u675F)\uFF0C\u6BCF\u6B21\u53D1\u9001\u6570\u636E\u90FD\u83B7\u53D6\u5F53\u524D\u65F6\u95F4\u6233\n optional uint32 class_timestamp=12;//\u76F8\u5BF9\u4E8E\u70B9\u5F00\u59CB\u8BFE\u5802\u7684\u65F6\u95F4\u6233\n optional string class_beginTime=13;//\u8BFE\u5802\u521B\u5EFA\u7684\u65F6\u95F4,\u8FD9\u4E2A\u662FSass\u8FD4\u56DE\u7684\n optional string class_endTime=14;//\u8BFE\u5802\u7ED3\u675F\u7684\u65F6\u95F4\uFF0C\u8FD9\u4E2A\u662FSass\u8FD4\u56DE\u7684\n optional bool record_status=15;//\u5F53\u524D\u5F55\u5236\u72B6\u6001\n optional uint32 record_timestamp=16;//\u76F8\u5BF9\u4E8E\u9996\u6B21\u5F00\u59CB\u5F55\u5236\u7684\u65F6\u95F4\u6233\n optional string record_fileName=17;//\u5F55\u5236\u7684\u6587\u4EF6\u540D\n optional string record_downloadUrl=18;//\u4E0B\u8F7D\u5730\u5740\n optional uint32 server_timestamp=19;//\u5F53\u524D\u7684\u7CFB\u7EDF\u65F6\u95F4\u6233\n optional uint32 active_doc_id=20;//\u5F53\u524D\u6FC0\u6D3B\u7684\u6587\u6863id\n optional uint32 active_doc_cur_page=21;//\u5F53\u524D\u6FC0\u6D3B\u7684\u6587\u6863\u7684\u5F53\u524D\u9875\n}\n\nmessage RCConferenceRecordRequestPdu {\n \toptional uint32 initiator = 1;\t// \u53D1\u8D77\u5F55\u50CF\u6307\u4EE4\u7684node id\n\t\toptional bool record = 2;\t\t// \u5F55\u50CF\u6307\u4EE4 true\uFF1A\u5F00\u59CB\u5F55\u50CF\uFF0C false\uFF1A\u505C\u6B62\u5F55\u50CF\n \toptional uint32 class_time = 3;\t// \u8BFE\u5802\u8FDB\u884C\u65F6\u95F4\uFF08\u79D2\uFF09\n\t\toptional string filename = 4;\t// \u5F55\u50CF\u6587\u4EF6\u540D\u79F0,filename\u4E2D\u589E\u52A0\u76EE\u5F55\u90E8\u5206\n}\n\n//end\n";
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(_default, "default", "D:/work/McuClient/src/pdus/pro.js");
+ }();
+
+ ;
+
+/***/ },
+/* 34 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ exports.default = RCPduPackage;
+ function RCPduPackage(targe_type_id) {};
+
+ RCPduPackage.RCPDU_CONNECT_PROVIDER_REQUEST = 0; //加入MCU会议的请求
+ RCPduPackage.RCPDU_CONNECT_PROVIDER_RESPONSE = 1; //返回MCU会议请求结果
+
+ //下面两个是在入会成功之后,创建pdu包时设置的type值
+ RCPduPackage.RCPDU_UNIFORM_SEND_DATA_REQUEST = 125; //发送uniform_pdu
+ RCPduPackage.RCPDU_SEND_DATA_REQUEST = 120; //入会成功之后,客户端接收消息都通过这个,发送私聊的消息也用这个
+
+
+ RCPduPackage.RCPDU_CONFERENCE_JOIN_REQUEST = 2;
+ RCPduPackage.RCPDU_CONFERENCE_JOIN_RESPONSE = 3;
+ RCPduPackage.RCPDU_CONFERENCE_INVITE_REQUEST = 10;
+ RCPduPackage.RCPDU_CONFERENCE_INVITE_RESPONSE = 11;
+ RCPduPackage.RCPDU_CONFERENCE_LOCK_REQUEST = 20;
+ RCPduPackage.RCPDU_CONFERENCE_LOCK_RESPONSE = 21;
+ RCPduPackage.RCPDU_CONFERENCE_LOCK_INDICATION = 22;
+ RCPduPackage.RCPDU_CONFERENCE_UNLOCK_REQUEST = 30;
+ RCPduPackage.RCPDU_CONFERENCE_UNLOCK_RESPONSE = 31;
+ RCPduPackage.RCPDU_CONFERENCE_UNLOCK_INDICATION = 32;
+ RCPduPackage.RCPDU_CONFERENCE_LEAVE_REQUEST = 39;
+ RCPduPackage.RCPDU_CONFERENCE_TERMINATE_REQUEST = 40;
+ RCPduPackage.RCPDU_CONFERENCE_TERMINATE_RESPONSE = 41;
+ RCPduPackage.RCPDU_CONFERENCE_TERMINATE_INDICATION = 42;
+ RCPduPackage.RCPDU_CONFERENCE_EJECT_USER_REQUEST = 50;
+ RCPduPackage.RCPDU_CONFERENCE_EJECT_USER_RESPONSE = 51;
+ RCPduPackage.RCPDU_CONFERENCE_EJECT_USER_INDICATION = 52;
+ RCPduPackage.RCPDU_ROSTER_UPDATE_INDICATION = 60;
+ RCPduPackage.RCPDU_REGISTRY_UPDATE_REQUEST = 70;
+ RCPduPackage.RCPDU_REGISTRY_UPDATE_RESPONSE = 71;
+ RCPduPackage.RCPDU_REGISTRY_UPDATE_INDICATION = 72;
+ RCPduPackage.RCPDU_FUNCTION_NOT_SUPPORTED_RESPONSE = 80;
+ RCPduPackage.RCPDU_SESSION_JOIN_REQUEST = 90;
+ RCPduPackage.RCPDU_SESSION_JOIN_RESPONSE = 91;
+ RCPduPackage.RCPDU_CHANNEL_GRAB_REQUEST = 100;
+ RCPduPackage.RCPDU_CHANNEL_GRAB_RESPONSE = 101;
+ RCPduPackage.RCPDU_CHANNEL_GRAB_INDICATION = 102;
+ RCPduPackage.RCPDU_CHANNEL_JOIN_REQUEST = 103;
+ RCPduPackage.RCPDU_CHANNEL_JOIN_RESPONSE = 104;
+ RCPduPackage.RCPDU_CHANNEL_LEAVE_REQUEST = 105;
+ RCPduPackage.RCPDU_CHANNEL_RELEASE_REQUEST = 106;
+ RCPduPackage.RCPDU_CHANNEL_RELEASE_INDICATION = 107;
+
+ RCPduPackage.RCPDU_SEND_DATA_INDICATION = 121;
+
+ RCPduPackage.RCPDU_UNIFORM_SEND_DATA_INDICATION = 126;
+ RCPduPackage.RCPDU_TOKEN_GRAB_REQUEST = 130;
+ RCPduPackage.RCPDU_TOKEN_GRAB_CONFIRM = 131;
+ RCPduPackage.RCPDU_TOKEN_INHIBIT_REQUEST = 132;
+ RCPduPackage.RCPDU_TOKEN_INHIBIT_CONFIRM = 133;
+ RCPduPackage.RCPDU_TOKEN_GIVE_REQUEST = 134;
+ RCPduPackage.RCPDU_TOKEN_GIVE_INDICATION = 135;
+ RCPduPackage.RCPDU_TOKEN_GIVE_RESPONSE = 136;
+ RCPduPackage.RCPDU_TOKEN_GIVE_CONFIRM = 137;
+ RCPduPackage.RCPDU_TOKEN_PLEASE_REQUEST = 138;
+ RCPduPackage.RCPDU_TOKEN_PLEASE_INDICATION = 139;
+ RCPduPackage.RCPDU_TOKEN_RELEASE_REQUEST = 140;
+ RCPduPackage.RCPDU_TOKEN_RELEASE_CONFIRM = 141;
+ RCPduPackage.RCPDU_TOKEN_TEST_REQUEST = 142;
+ RCPduPackage.RCPDU_TOKEN_TEST_CONFIRM = 143;
+ RCPduPackage.RCPDU_REG_REGISTER_KEY = 200;
+ RCPduPackage.RCPDU_REG_UNREGISTER_KEY = 201;
+ RCPduPackage.RCPDU_REG_REGISTER_ROSTER = 202;
+ RCPduPackage.RCPDU_REG_REGISTER_TOKEN = 203;
+ RCPduPackage.RCPDU_REG_REGISTER_PARAMETER = 204;
+ RCPduPackage.RCPDU_REG_REGISTER_COUNTER = 205;
+ RCPduPackage.RCPDU_REG_REGISTER_TABLE = 206;
+ RCPduPackage.RCPDU_REG_REGISTER_CACHE = 207;
+ RCPduPackage.RCPDU_REG_REGISTER_OBJ = 208;
+ RCPduPackage.RCPDU_REG_UNREGISTER_OBJ = 209;
+ RCPduPackage.RCPDU_REG_UPDATE_OBJ = 210;
+ RCPduPackage.RCPDU_REG_ADAPTER = 211;
+ RCPduPackage.RCPDU_REG_CLEANUP_NODE = 212;
+ RCPduPackage.RCPDU_REG_REGISTER_QUEUE = 213;
+ RCPduPackage.RCPDU_REG_TABLE_INSERT_PDU = 230;
+ RCPduPackage.RCPDU_REG_TABLE_DELETE_PDU = 231;
+ RCPduPackage.RCPDU_REG_TABLE_UPDATE_PDU = 232;
+ RCPduPackage.RCPDU_REG_ROSTER_INSERT_PDU = 240;
+ RCPduPackage.RCPDU_REG_ROSTER_DELETE_PDU = 241;
+ RCPduPackage.RCPDU_REG_ROSTER_UPDATE_PDU = 242;
+ RCPduPackage.RCPDU_REG_PARAMETER_UPDATE_PDU = 250;
+ RCPduPackage.RCPDU_REG_QUEUE_INSERT_PDU = 255;
+ RCPduPackage.RCPDU_REG_QUEUE_DELETE_PDU = 256;
+ RCPduPackage.RCPDU_REG_QUEUE_UPDATE_PDU = 257;
+ RCPduPackage.RCPDU_CONFERENCE_SEND_DATA_REQUEST = 259;
+ RCPduPackage.RCPDU_VIDEO_SEND_DATA_REQUEST = 260;
+ RCPduPackage.RCPDU_AUDIO_SEND_DATA_REQUEST = 261;
+ RCPduPackage.RCPDU_GIFT_SEND_DATA_REQUEST = 262;
+ RCPduPackage.RCPDU_CHAT_SEND_DATA_REQUEST = 263;
+ RCPduPackage.RCPDU_VOTING_POLL_RECORD = 265;
+ RCPduPackage.RCPDU_CONFERENCE_RECORD_REQUEST = 270; //录制和停止录制的协议号
+
+ RCPduPackage.RCPDU_REG_REQUEST_OBJ = 290;
+ RCPduPackage.RCPDU_REG_RESPONSE_OBJ = 291;
+ RCPduPackage.RCPDU_REG_COUNTER_REQUEST_PDU = 292;
+ RCPduPackage.RCPDU_REG_COUNTER_RESPONSE_PDU = 293;
+ RCPduPackage.RCPDU_INDEX_ADAPTER = 300;
+ RCPduPackage.RCPDU_INDEX_SERVER_USERS = 301;
+ RCPduPackage.RCPDU_INDEX_CONFERENCE_USER_JOINED = 302;
+ RCPduPackage.RCPDU_INDEX_CONFERENCE_USER_EXITED = 303;
+ RCPduPackage.RCPDU_INDEX_CONFERENCE_USERS = 304;
+
+ RCPduPackage.RCPDU_SEND_CONFERENCE_DATA_REQUEST = 500;
+ RCPduPackage.RCPDU_SEND_VIDEO_DATA_REQUEST = 501;
+ RCPduPackage.RCPDU_SEND_AUDIO_DATA_REQUEST = 502;
+ RCPduPackage.RCPDU_SEND_GIFT_DATA_REQUEST = 503;
+ RCPduPackage.RCPDU_SEND_CHAT_DATA_REQUEST = 504;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(RCPduPackage, "RCPduPackage", "D:/work/McuClient/src/pdus/PduType.js");
+ }();
+
+ ;
+
+/***/ },
+/* 35 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+ exports.default = PduConsts;
+ function PduConsts() {}
+
+ //nodeType ,目前在加入课堂的时候用到 NT_TERMINAL,其他两个还没用到
+ PduConsts.NT_TERMINAL = 0; //终端适配器
+ PduConsts.NT_MULTIPORT_TERMINAL = 1; //多端口ERMINAL
+ PduConsts.NT_MCU = 2;
+
+ // PduPriority 发送pdu包的 优先级
+ PduConsts.DP_TOP = 0;
+ PduConsts.DP_HIGH = 1;
+ PduConsts.DP_MEDIUM = 2;
+ PduConsts.DP_LOW = 3;
+
+ // PduSegment
+ PduConsts.SEG_BEGIN = 0;
+ PduConsts.SEG_END = 1;
+ PduConsts.SEG_ONCE = 2; //目前发送消息封包的时候都用的这个
+
+
+ // PduReturnType
+ PduConsts.RET_SUCCESS = 0;
+ PduConsts.RET_USER_REJECTED = 1;
+ PduConsts.RET_INVALID_CONFERENCE = 2;
+ PduConsts.RET_INVALID_PASSWORD = 3;
+ PduConsts.RET_INVALID_CONVENER_PASSWORD = 4;
+ PduConsts.RET_CHALLENGE_RESPONSE_REQUIRED = 5;
+ PduConsts.RET_INVALID_CHALLENGE_RESPONSE = 6;
+ PduConsts.RET_NO_CONNECTION = 7;
+ PduConsts.RET_FULL_CAPACITY = 8;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(PduConsts, "PduConsts", "D:/work/McuClient/src/pdus/PduConsts.js");
+ }();
+
+ ;
+
+/***/ },
+/* 36 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Ape2 = __webpack_require__(37);
+
+ var _Ape3 = _interopRequireDefault(_Ape2);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _zlib = __webpack_require__(39);
+
+ var _utf = __webpack_require__(11);
+
+ var _utf2 = _interopRequireDefault(_utf);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ var _TimerCounter = __webpack_require__(40);
+
+ var _TimerCounter2 = _interopRequireDefault(_TimerCounter);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //会议控制APE
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('ConferApe');
+ var itemIdx = 0; //table插入新数据的计数id,目前用时间戳
+
+ var ConferApe = function (_Ape) {
+ _inherits(ConferApe, _Ape);
+
+ function ConferApe() {
+ _classCallCheck(this, ConferApe);
+
+ /*
+ // Attribures
+ this.hostNodeId = -1;//主持人的nodeId
+ // 用户的身份,5种类型:
+ // host(主持人/老师)
+ // presenter(主讲人)
+ // assistant(助教)
+ // normal(普通角色/学生)
+ // record(暂时没用.
+ // 默认值: normal
+ this.hostUserId = '';//主持人的 第三方userId
+ */
+
+ var _this = _possibleConstructorReturn(this, (ConferApe.__proto__ || Object.getPrototypeOf(ConferApe)).call(this, _ApeConsts2.default.CONFERENCE_SESSION_ID, _ApeConsts2.default.CONFERENCE_SESSION_NAME, _ApeConsts2.default.CONFERENCE_SESSION_TAG));
+
+ _this.rosters = {}; //用户列表
+ _this.timerCounter = new _TimerCounter2.default(); //计时器
+
+ // Ape Models
+ _this.registerKey(_this._session_id, _this._session_name, _this._session_tag, new ArrayBuffer());
+
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_ROSTER, _ApeConsts2.default.CONFERENCE_OBJ_ROSTER_ID, _ApeConsts2.default.CONFERENCE_OBJ_ROSTER_NAME, _ApeConsts2.default.CONFERENCE_OBJ_ROSTER_TAG, 0, new ArrayBuffer());
+
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_QUEUE, _ApeConsts2.default.CONFERENCE_OBJ_QUEUE_ID, _ApeConsts2.default.CONFERENCE_OBJ_QUEUE_NAME, _ApeConsts2.default.CONFERENCE_OBJ_QUEUE_TAG, 0, new ArrayBuffer());
+
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_TABLE, _ApeConsts2.default.CONFERENCE_OBJ_TABLE_ID, _ApeConsts2.default.CONFERENCE_OBJ_TABLE_NAME, _ApeConsts2.default.CONFERENCE_OBJ_TABLE_TAG, 0, new ArrayBuffer());
+
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_COUNTER, _ApeConsts2.default.CONFERENCE_OBJ_COUNTER_ID, _ApeConsts2.default.CONFERENCE_OBJ_COUNTER_NAME, _ApeConsts2.default.CONFERENCE_OBJ_COUNTER_TAG, 0, new ArrayBuffer());
+
+ _this.on(_pdus2.default.RCPDU_SESSION_JOIN_RESPONSE, _this._joinSessionHandler.bind(_this));
+
+ _this.on(_pdus2.default.RCPDU_SEND_CONFERENCE_DATA_REQUEST, _this.conferMsgComingHandler.bind(_this)); //这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
+ _this.on(_pdus2.default.RCPDU_CONFERENCE_RECORD_REQUEST, _this.onSendConferRecordRequestHandler.bind(_this)); //发送录制和停止录制消息
+ return _this;
+ }
+
+ //加入会议
+
+
+ _createClass(ConferApe, [{
+ key: '_joinSessionHandler',
+ value: function _joinSessionHandler(_data) {
+ var nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
+ loger.log("_joinSessionHandler nodeInfoRecordPdu=");
+ console.log(nodeInfoRecordPdu);
+ var userDataPdu = new _pdus2.default['RCNodeInfoUserDataPdu']();
+ userDataPdu.qq = '';
+ userDataPdu.skype = '';
+
+ nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
+ nodeInfoRecordPdu.deviceType = _GlobalConfig2.default.deviceType; //设备类型
+
+ var item = new _pdus2.default['RCRegistryRosterItemPdu']();
+ item.nodeId = nodeInfoRecordPdu.nodeId;
+ item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
+
+ var rosterUpdateItem = new _pdus2.default['RCRegistryRosterUpdateItemPdu']();
+ rosterUpdateItem.type = _pdus2.default.RCPDU_REG_ROSTER_UPDATE_PDU;
+ rosterUpdateItem.items.push(item);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.CONFERENCE_OBJ_ROSTER_ID;
+ updateObjPdu.subType = rosterUpdateItem.type;
+ updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+ this.sendUniform(adapterPdu, true);
+ }
+ }, {
+ key: 'sendConferMsg',
+ value: function sendConferMsg(_messageInfo) {
+ if (this._classInfo == null || _EngineUtils2.default.isEmptyObject(this._classInfo)) {
+ loger.log('不能发送会议消息.McuClient还未初始化数据!');
+ if (_GlobalConfig2.default.getCurrentStatus().code == 0 || _GlobalConfig2.default.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return;
+ }
+ return;
+ }
+
+ // to, message
+ loger.log('发送会议消息.', _messageInfo);
+
+ /* message RCConferenceSendDataRequestPdu {
+ optional uint32 initiator = 1;
+ optional uint32 peer = 2;
+ required bool is_public = 3;
+ required bytes user_data = 4;
+ }
+ */
+
+ var conferSendPdu = new _pdus2.default['RCConferenceSendDataRequestPdu']();
+ conferSendPdu.type = _pdus2.default.RCPDU_SEND_CONFERENCE_DATA_REQUEST;
+ conferSendPdu.initiator = this._classInfo.nodeId; //发起人
+ conferSendPdu.peer = parseInt(_messageInfo.to); //发送给谁,公聊的时候是0,私聊的时候是指定的用户id
+
+ conferSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
+ //conferSendPdu.userData =UTF8.setBytesFromString(_messageInfo.message);
+ conferSendPdu.isPublic = true;
+ conferSendPdu.actionType = _messageInfo.actionType;
+ // if (!(conferSendPdu.isPublic || 0 === conferSendPdu.peer)) {
+ if (!conferSendPdu.isPublic && 0 != conferSendPdu.peer) {
+ //发送给制定的人
+ loger.log('发送私聊会议消息.');
+ this.send(conferSendPdu);
+ } else {
+ //发送给所有人
+ loger.log('发送公聊会议消息.');
+ this.sendChatUniform(conferSendPdu);
+ }
+ }
+
+ //发送录制或停止录制的消息,{"recordStatus":true};true为开始录制,false为停止录制
+
+ }, {
+ key: 'sendConferRecordMsg',
+ value: function sendConferRecordMsg(_param) {
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+ // to, message
+ loger.log('发送录制消息.', _param);
+
+ if (_param == null) {
+ loger.warn("控制录制状的消息发送失败,参数错误", _param);
+ return;
+ }
+
+ /* message RCConferenceRecordRequestPdu {
+ optional uint32 initiator = 1; // 发起录像指令的node id
+ optional bool record = 2; // 录像指令 true:开始录像, false:停止录像
+ optional uint32 class_time = 3; // 课堂进行时间(秒)
+ optional string filename = 4; // 录像文件名称,filename中增加目录部分
+ }*/
+
+ //保存当前的录制状态
+ _GlobalConfig2.default.recordStatus = _param.recordStatus || false;
+
+ var conferRecordSendPdu = new _pdus2.default['RCConferenceRecordRequestPdu']();
+ conferRecordSendPdu.type = _pdus2.default.RCPDU_CONFERENCE_RECORD_REQUEST;
+ conferRecordSendPdu.peer = 0; //channel 为0
+ conferRecordSendPdu.isPublic = true;
+
+ conferRecordSendPdu.initiator = this._classInfo.nodeId; //发起人
+ conferRecordSendPdu.record = _GlobalConfig2.default.recordStatus;
+ conferRecordSendPdu.classTime = _GlobalConfig2.default.classTimestamp;
+ conferRecordSendPdu.filename = _GlobalConfig2.default.recordFileName || _GlobalConfig2.default.classId + "_" + _EngineUtils2.default.creatTimestampYMD() + ".rec";
+ this.sendChatUniform(conferRecordSendPdu);
+ }
+
+ //开启录制
+
+ }, {
+ key: 'startRecord',
+ value: function startRecord() {
+ loger.log('startRecord', "isHost", _GlobalConfig2.default.isHost, "recordStatus", _GlobalConfig2.default.recordStatus);
+ //如果是host
+ if (_GlobalConfig2.default.isHost) {
+ _GlobalConfig2.default.classStopTime = _EngineUtils2.default.creatTimestampStr();
+ this.sendConferRecordMsg({ "recordStatus": true });
+ this._emit(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE);
+ this._emit(_MessageTypes2.default.CLASS_RECORD_START); //会议开始录制
+ }
+ }
+
+ //停止录制
+
+ }, {
+ key: 'stopRecord',
+ value: function stopRecord() {
+ loger.log('stopRecord', "isHost", _GlobalConfig2.default.isHost, "recordStatus", _GlobalConfig2.default.recordStatus);
+ //如果是host,并且当前正在录制中
+ if (_GlobalConfig2.default.isHost && _GlobalConfig2.default.recordStatus) {
+ _GlobalConfig2.default.classStopTime = _EngineUtils2.default.creatTimestampStr();
+ this.sendConferRecordMsg({ "recordStatus": false });
+ this._emit(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE);
+ }
+ }
+
+ //主动离开会议,发送通知到服务器
+
+ }, {
+ key: 'leaveClass',
+ value: function leaveClass() {
+ var nodeInfoRecordPdu = this.mcu.mcuClassInfo.self;
+ var userDataPdu = new _pdus2.default['RCNodeInfoUserDataPdu']();
+ userDataPdu.qq = '';
+ userDataPdu.skype = '';
+
+ nodeInfoRecordPdu.userData = userDataPdu.toArrayBuffer();
+ nodeInfoRecordPdu.deviceType = _GlobalConfig2.default.deviceType;
+
+ var item = new _pdus2.default['RCRegistryRosterItemPdu']();
+ item.nodeId = nodeInfoRecordPdu.nodeId;
+ item.nodeData = nodeInfoRecordPdu.toArrayBuffer();
+
+ var rosterUpdateItem = new _pdus2.default['RCRegistryRosterDeleteItemPdu']();
+ rosterUpdateItem.type = _pdus2.default.RCPDU_REG_ROSTER_DELETE_PDU;
+ rosterUpdateItem.nodeId = _GlobalConfig2.default.nodeId;
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.CONFERENCE_OBJ_ROSTER_ID;
+ updateObjPdu.subType = rosterUpdateItem.type;
+ updateObjPdu.userData = rosterUpdateItem.toArrayBuffer();
+
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ this.sendUniform(adapterPdu, true);
+ }
+
+ //还原课堂状态
+
+ }, {
+ key: 'restorClass',
+ value: function restorClass() {
+ _GlobalConfig2.default.classTimestamp = 0;
+ _GlobalConfig2.default.classStatus = _ApeConsts2.default.CLASS_STATUS_WAIT;
+ _GlobalConfig2.default.classStopTime = _EngineUtils2.default.creatTimestampStr();
+ this.stopRecord();
+ this._emit(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE);
+ this.sendUpdaterClassStatusInfo({ "actionType": 0 });
+ loger.log('restorClass');
+ }
+
+ //开始上课
+
+ }, {
+ key: 'startClass',
+ value: function startClass(_param) {
+ if (_GlobalConfig2.default.isHost) {
+
+ var timestamp = _EngineUtils2.default.creatTimestampStr();
+ _GlobalConfig2.default.classStopTime = timestamp;
+
+ //如果录制的文件名不存在,需要创建一个名字
+ var timestampYMD = _EngineUtils2.default.creatTimestampYMD();
+ _GlobalConfig2.default.recordFileName = _GlobalConfig2.default.recordFileName || _GlobalConfig2.default.siteId + "/" + timestampYMD + "/" + _GlobalConfig2.default.classId + "_" + timestampYMD + ".rec"; //4、文件名称 $RECORD_HOME/`site id`/`日期`/`filename` 例:/data/record/su/20161216/`filename`
+
+ if (_GlobalConfig2.default.classStatus == _ApeConsts2.default.CLASS_STATUS_WAIT) {
+ //之前是为开始状态,第一次点开始
+ _GlobalConfig2.default.classStartTime = timestamp;
+ }
+
+ _GlobalConfig2.default.classStatus = _ApeConsts2.default.CLASS_STATUS_STARTED;
+ //开始录制
+ this.startRecord();
+ //会议状态改变
+ this._emit(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE);
+ //同步会议状态
+ this.sendUpdaterClassStatusInfo({ "actionType": 1 });
+
+ //开始计时
+ this.startTimerCounter();
+ } else {
+ loger.warn('没有权限');
+ }
+ }
+
+ //暂停上课
+
+ }, {
+ key: 'pauseClass',
+ value: function pauseClass(_param) {
+ if (_GlobalConfig2.default.classStatus == _ApeConsts2.default.CLASS_STATUS_WAIT) {
+ loger.warn('还没有开始,不能点暂停');
+ return;
+ }
+
+ _GlobalConfig2.default.classStatus = _ApeConsts2.default.CLASS_STATUS_PAUSE;
+ _GlobalConfig2.default.classStopTime = _EngineUtils2.default.creatTimestampStr();
+
+ this.stopRecord();
+ this._emit(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE);
+ this.sendUpdaterClassStatusInfo({ "actionType": 2 });
+ this.stopTimerCounter();
+ }
+
+ //关闭课堂
+
+ }, {
+ key: 'closeClass',
+ value: function closeClass(_param) {
+ if (_GlobalConfig2.default.classStatus == _ApeConsts2.default.CLASS_STATUS_WAIT) {
+ loger.warn('还没有开始,不能点关闭');
+ return;
+ }
+
+ this.stopTimerCounter();
+ this.restorClass();
+ //把所有人都踢出课堂
+ this.sendConferMsg({ "to": 0, "message": "所有人退出会议", "actionType": _ApeConsts2.default.CLASS_ACTION_CLOSE_ALL });
+ }
+
+ //更新会议信息
+
+ }, {
+ key: 'sendUpdaterClassStatusInfo',
+ value: function sendUpdaterClassStatusInfo(_param) {
+ loger.log('sendUpdaterClassStatusInfo');
+ if (_param == null || _EngineUtils2.default.isEmptyObject(_param)) {
+ loger.log('sendUpdaterClassStatusInfo,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ itemIdx = _ApeConsts2.default.CONFERENCE_OBJ_TABLE_ID; // itemIdx=_param.itemIdx;
+ var modelPdu = this.packPdu(_param, itemIdx);
+ //loger.log('sendUpdaterClassStatusInfo----2------');
+ console.log(modelPdu);
+
+ if (modelPdu == null) {
+ loger.log('sendUpdaterClassStatusInfo,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = itemIdx;
+ tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
+ tableItemPdu.registerObjId = _ApeConsts2.default.CONFERENCE_OBJ_TABLE_ID;
+ tableItemPdu.itemData = modelPdu.toArrayBuffer();
+
+ //updater
+ var tableUpdateItem = new _pdus2.default['RCRegistryTableUpdateItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
+ //repeated RCRegistryTableItemPdu items = 2;
+ tableUpdateItem.type = _pdus2.default.RCPDU_REG_TABLE_UPDATE_PDU; //
+ tableUpdateItem.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.CONFERENCE_OBJ_TABLE_ID;
+ updateObjPdu.subType = tableUpdateItem.type;
+ updateObjPdu.userData = tableUpdateItem.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ console.log("会议发送更新数据============");
+ this.sendUniform(adapterPdu, true);
+ }
+
+ /////收到消息处理/////////////////////////////////////////////////////////////////////////////////
+ //加入channel成功
+
+ }, {
+ key: 'onJoinChannelHandlerSuccess',
+ value: function onJoinChannelHandlerSuccess() {
+ loger.log('ConferApe.onJoinChannelHandlerSuccess', _GlobalConfig2.default.classStatus);
+ this.timerCounter.addTimerCallBack(this.timerCounterUptate.bind(this), 1);
+ //如果当前会议正在进行中,开启计时器
+ if (_GlobalConfig2.default.classStatus == _ApeConsts2.default.CLASS_STATUS_STARTED) {
+ //开始计时
+ this.startTimerCounter();
+
+ //如果是host ,开始录制
+ this.startRecord();
+ }
+ }
+
+ //开启计时器
+
+ }, {
+ key: 'startTimerCounter',
+ value: function startTimerCounter() {
+ this.timerCounter.startTimer();
+ }
+
+ //停止计时器
+
+ }, {
+ key: 'stopTimerCounter',
+ value: function stopTimerCounter() {
+ this.timerCounter.stopTimer();
+ }
+ }, {
+ key: 'timerCounterUptate',
+ value: function timerCounterUptate() {
+ if (!this.mcu.connected) {
+ loger.warn('MCU 连接已经断开');
+ this.stopTimerCounter();
+ }
+ //如果还没开始或已经暂停、关闭,不做计时处理
+ if (_GlobalConfig2.default.classStatus != _ApeConsts2.default.CLASS_STATUS_STARTED) {
+ loger.warn('当前课堂已经暂停或者未开始,不计时', "classStatus-->", _GlobalConfig2.default.classStatus);
+ return;
+ }
+ _GlobalConfig2.default.classTimestamp = _GlobalConfig2.default.classTimestamp + 1; //计时
+ //loger.log('课堂进行时间',GlobalConfig.classTimestamp);
+ this._emit(_MessageTypes2.default.CLASS_UPDATE_TIMER, { "classTimestamp": _GlobalConfig2.default.classTimestamp });
+
+ if (_GlobalConfig2.default.classTimestamp % _GlobalConfig2.default.updateClassInfoDelay == 0) {
+ //如果是host身份,需要同步时间给其他人,同时把当前的状态上传到服务器
+ if (_GlobalConfig2.default.isHost) {
+ //保存数据到Sass
+ this._emit(_MessageTypes2.default.CLASS_STATUS_INFO_CHANGE);
+
+ //同步消息给其他人
+ this.sendUpdaterClassStatusInfo({ "actionType": 1 });
+ }
+ }
+ }
+ }, {
+ key: 'tableUpdateHandler',
+ value: function tableUpdateHandler(owner, itemIdx, itemData) {
+ try {
+ var model = this.unPackPdu(owner, itemIdx, itemData);
+ loger.log('tableUpdateHandler');
+ console.log(model);
+
+ //处理会议更新的信息
+ if (model && model.classStatusInfo) {
+ _GlobalConfig2.default.setClassStatusInfo(model.classStatusInfo);
+ }
+ //通知应用层更新会议状态
+ this._emit(_MessageTypes2.default.CLASS_UPTATE_STATUS, _GlobalConfig2.default.classStatusInfo);
+
+ //如果MCU已经断开连接,停止计时器
+ if (!this.mcu.connected) {
+ //停止计时
+ this.stopTimerCounter();
+ return;
+ }
+
+ if (_GlobalConfig2.default.classStatus == _ApeConsts2.default.CLASS_STATUS_STARTED) {
+ //如果会议在进行中,开始计时器
+ this.startTimerCounter();
+ } else {
+ //停止计时
+ this.stopTimerCounter();
+ }
+ } catch (e) {
+ loger.warn('ConferApe table update got exception. itemIdx', itemIdx);
+ }
+ }
+ }, {
+ key: 'conferMsgComingHandler',
+ value: function conferMsgComingHandler(_data) {
+ //flash RCConferenceSendDataRequestPdu
+ //loger.warn('conferMsgComingHandler needs to be handled.');
+ //const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);
+ //loger.log("conferMsgComingHandler",recordInfo);
+
+ var chatReceivePdu = _pdus2.default['RCConferenceSendDataRequestPdu'].decode(_data);
+
+ var chatMsg = {};
+ chatMsg.fromNodeID = chatReceivePdu.initiator;
+ chatMsg.toNodeID = chatReceivePdu.peer;
+ chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
+ chatMsg.actionType = chatReceivePdu.actionType;
+ loger.log("conferMsgComingHandler", chatMsg);
+ switch (chatMsg.actionType) {
+ case _ApeConsts2.default.CLASS_ACTION_CLOSE_ALL:
+ loger.log(chatMsg.message);
+ //收到会议关闭,所有人都退出,执行自己关闭的流程
+ this._emit(_MessageTypes2.default.CLASS_EXIT);
+ break;
+ default:
+ break;
+ }
+ }
+ }, {
+ key: 'onSendConferRecordRequestHandler',
+ value: function onSendConferRecordRequestHandler(_data) {
+ loger.log("onSendConferRecordRequestHandler");
+ try {
+ var conferRecordSendPdu = _pdus2.default['RCConferenceRecordRequestPdu'].decode(_data);
+ console.log(conferRecordSendPdu);
+ } catch (err) {
+ loger.warn("onSendConferRecordRequestHandler err", err.message);
+ }
+ }
+ }, {
+ key: 'rosterInsertHandler',
+ value: function rosterInsertHandler(nodeId, nodeData) {
+ if (_GlobalConfig2.default.nodeId == nodeId) {
+ // loger.log("自己加入 rosterInsertHandler");
+ } else {
+ // loger.log("有人加入 rosterInsertHandler");
+ this.rosterUpdateHandler(nodeId, nodeData);
+ }
+ }
+
+ //更新人员列表数据
+
+ }, {
+ key: 'rosterUpdateHandler',
+ value: function rosterUpdateHandler(nodeId, nodeData) {
+ //如果是自己的信息,不处理跳过
+ if (nodeId == _GlobalConfig2.default.nodeId) {
+ loger.log("自己加入课堂的消息,不需要处理");
+ this.rosters[nodeId] = nodeData;
+ return;
+ }
+
+ loger.log(nodeId, "加入课堂,role-->", nodeData.role, _ApeConsts2.default.userTypes[nodeData.role]);
+
+ //新加入的人员不是自己
+ //1.判断进入的用户身份,如果进入的人身份是host,助教,监课,并且和自己的身份冲突,自己会被踢掉
+ //2.最后进入的人会踢掉之前进入的人,nodeId是按时间戳生成的,最后进入的人nodeId的值比之前进入的人大
+ if (parseInt(nodeId) > _GlobalConfig2.default.nodeId) {
+ if (nodeData.role == _ApeConsts2.default.NR_HOST && _GlobalConfig2.default.isHost) {
+ this.kickOutRoster();
+ return;
+ } else if (nodeData.role == _ApeConsts2.default.NR_PRESENTER && _GlobalConfig2.default.isPresenter) {
+ this.kickOutRoster();
+ return;
+ } else if (nodeData.role == _ApeConsts2.default.NR_ASSISTANT && _GlobalConfig2.default.isAssistant) {
+ this.kickOutRoster();
+ return;
+ } else if (nodeData.role == _ApeConsts2.default.NR_INVISIBLE && _GlobalConfig2.default.isInvisible) {
+ this.kickOutRoster();
+ return;
+ }
+ }
+
+ //处理用户信息
+ var rosterExists = this.rosters[nodeId];
+ this.rosters[nodeId] = nodeData;
+ var userDataObj = null;
+ if (!rosterExists) {
+ try {
+ userDataObj = _pdus2.default['RCNodeInfoUserDataPdu'].decode(nodeData.userData);
+ } catch (err) {
+ loger.log("RCNodeInfoUserDataPdu decode err", err.message);
+ }
+
+ var newNodeData = nodeData;
+ newNodeData.userData = userDataObj;
+
+ //如果是监课,不告诉其他人
+ if (nodeData.role == _ApeConsts2.default.NR_INVISIBLE) {
+ loger.log("NR_INVISIBLE");
+ return;
+ }
+
+ this._emit(_MessageTypes2.default.CLASS_INSERT_ROSTER, { "nodeId": nodeId, "nodeData": newNodeData });
+ this.emitRosterChange();
+ } else {
+ //loger.log("更新人员列表数据,rosterExists已经存在",rosterExists);
+ }
+ }
+
+ //踢出用户
+
+ }, {
+ key: 'kickOutRoster',
+ value: function kickOutRoster() {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_CLASS_KICK_OUT);
+ this._emit(_MessageTypes2.default.CLASS_EXIT);
+ }
+
+ //视频模块发生更新,人员状态需要更新
+
+ }, {
+ key: 'updaterRosterStatus',
+ value: function updaterRosterStatus(_param) {
+ //loger.log("媒体模块发生更新,人员状态需要更新,fromNodeId->",_param.fromNodeId);
+ //如果视频消息中channel的占用人 fromNodeId在人员列表中不存在,需要释放这channel,因为这个有可能是之前没释放成功的
+ if (_param && _param.status == _ApeConsts2.default.CHANNEL_STATUS_OPENING && this.rosters[_param.fromNodeId] == null) {
+ loger.log("媒体模块被占用,占有人已经不存在课堂中,释放Channel,_param->", _param);
+ this._emit(_MessageTypes2.default.CLASS_NONENTITY_ROSTER, { "nodeId": _param.fromNodeId });
+ }
+ }
+
+ //删除用户
+
+ }, {
+ key: 'rosterDelHandler',
+ value: function rosterDelHandler(nodeId) {
+ if (_GlobalConfig2.default.nodeId == nodeId) {
+ loger.log("自己离开课堂");
+ // 自己退出
+ this._emit(_MessageTypes2.default.CLASS_EXIT);
+ } else {
+ loger.log(nodeId, "离开课堂");
+ delete this.rosters[nodeId];
+ this.emitRosterChange();
+ this._emit(_MessageTypes2.default.CLASS_DELETE_ROSTER, { "nodeId": nodeId });
+
+ //当前人员列表中抽一个人来检查离开人员是否占用频道
+ for (var key in this.rosters) {
+ var randNodeId = parseInt(key);
+ if (randNodeId == _GlobalConfig2.default.nodeId) {
+ loger.log(randNodeId, "有权限检查离开的人员是否占用channel");
+ this._emit(_MessageTypes2.default.CLASS_NONENTITY_ROSTER, { "nodeId": nodeId });
+ } else {
+ loger.warn(_GlobalConfig2.default.nodeId, "没有权限检查离开的人员是否占用channel");
+ }
+ return;
+ }
+ }
+ }
+
+ //广播当前的人数
+
+ }, {
+ key: 'emitRosterChange',
+ value: function emitRosterChange() {
+ this._emit(_MessageTypes2.default.CLASS_UPDATE_ROSTER_NUM, Object.keys(this.rosters).length);
+ }
+
+ ///////数据的封包和解包/////////////////////////////////////////
+
+ }, {
+ key: 'packPdu',
+ value: function packPdu(_param, _itemIdx) {
+ loger.log("会议===packPdu ");
+ //验证坐标点集合数组是否合法
+ if (_param == null || _itemIdx == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+ var classStatusInfo = new _pdus2.default['RCClassStatusInfoPdu']();
+ classStatusInfo.nodeId = _GlobalConfig2.default.nodeId; //mcu中的唯一ID
+ classStatusInfo.userId = _GlobalConfig2.default.userId;
+ classStatusInfo.userName = _GlobalConfig2.default.userName;
+ classStatusInfo.siteId = _GlobalConfig2.default.siteId; //站点号
+ classStatusInfo.classId = _GlobalConfig2.default.classId;
+ classStatusInfo.className = _GlobalConfig2.default.className;
+ classStatusInfo.classType = _GlobalConfig2.default.classType; //课堂类型
+ classStatusInfo.classStatus = _GlobalConfig2.default.classStatus; //课堂的状态
+ classStatusInfo.classStartTime = _GlobalConfig2.default.classStartTime; //课堂点击开始时间
+ classStatusInfo.classStopTime = _GlobalConfig2.default.classStopTime; //最后一次停止的时间(点暂停或结束),每次发送数据都获取当前时间戳
+ classStatusInfo.classTimestamp = _GlobalConfig2.default.classTimestamp; //相对于点开始课堂的时间戳
+ classStatusInfo.classBeginTime = _GlobalConfig2.default.classBeginTime; //课堂创建的时间,这个是Sass返回的
+ classStatusInfo.classEndTime = _GlobalConfig2.default.classEndTime; //课堂结束的时间,这个是Sass返回的
+ classStatusInfo.recordStatus = _GlobalConfig2.default.recordStatus; //当前录制状态
+ classStatusInfo.recordTimestamp = _GlobalConfig2.default.recordTimestamp; //相对于首次开始录制的时间戳
+ classStatusInfo.recordFileName = _GlobalConfig2.default.recordFileName; //录制的文件名
+ classStatusInfo.recordDownloadUrl = _GlobalConfig2.default.recordDownloadUrl; //下载地址
+ classStatusInfo.serverTimestamp = _GlobalConfig2.default.serverTimestamp; //当前的系统时间戳
+ classStatusInfo.activeDocId = _GlobalConfig2.default.activeDocId; //当前激活的文档id
+ classStatusInfo.activeDocCurPage = _GlobalConfig2.default.activeDocCurPage; //当前激活的文档的当前页
+
+ loger.log("classStatusInfo-------------", classStatusInfo);
+
+ /*
+ optional uint32 item_idx=1;
+ optional uint32 from=2;
+ optional uint32 owner=3;
+ optional uint32 action_type=4;//状态改变的类型
+ optional RCClassStatusInfoPdu class_status_info=5;//当前课堂状态的信息
+ */
+ //判断type类型,根据type设置不同的参数
+ var modelPdu = new _pdus2.default['RCClassSendDataModelPdu']();
+ modelPdu.itemIdx = _itemIdx;
+ modelPdu.from = _GlobalConfig2.default.nodeId;
+ modelPdu.owner = _GlobalConfig2.default.nodeId;
+ //modelPdu.actionType =_param.actionType;
+ modelPdu.classStatusInfo = classStatusInfo;
+ return modelPdu;
+ }
+ }, {
+ key: 'unPackPdu',
+ value: function unPackPdu(owner, itemIdx, itemData) {
+ loger.log("会议===unPackPdu ");
+ if (owner == null || itemIdx == null || itemData == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+
+ try {
+ var modelPdu = _pdus2.default['RCClassSendDataModelPdu'].decode(itemData);
+ return modelPdu;
+ } catch (err) {
+ loger.log("会议收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
+ }
+ return null;
+ }
+ }]);
+
+ return ConferApe;
+ }(_Ape3.default);
+
+ var _default = ConferApe;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/ConferApe.js');
+
+ __REACT_HOT_LOADER__.register(itemIdx, 'itemIdx', 'D:/work/McuClient/src/apes/ConferApe.js');
+
+ __REACT_HOT_LOADER__.register(ConferApe, 'ConferApe', 'D:/work/McuClient/src/apes/ConferApe.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/ConferApe.js');
+ }();
+
+ ;
+
+/***/ },
+/* 37 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _Emiter2 = __webpack_require__(3);
+
+ var _Emiter3 = _interopRequireDefault(_Emiter2);
+
+ var _mcu = __webpack_require__(23);
+
+ var _mcu2 = _interopRequireDefault(_mcu);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _ArrayBufferUtil = __webpack_require__(38);
+
+ var _ArrayBufferUtil2 = _interopRequireDefault(_ArrayBufferUtil);
+
+ var _PduConsts = __webpack_require__(35);
+
+ var _PduConsts2 = _interopRequireDefault(_PduConsts);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //
+ // Copyright (C) 2016-present All Rights Reserved.
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Github Home: https://github.com/AlexWang1987
+ // Author: AlexWang
+ // Date: 2016-08-26 11:19:56
+ // QQ Email: 1669499355@qq.com
+ // Last Modified time: 2017-01-04 14:38:20
+ // Description: LiveClass-Ape
+ //
+ // //////////////////////////////////////////////////////////////////////////////
+
+ // 日志对象
+ var loger = _Loger2.default.getLoger('Ape');
+
+ var Ape = function (_Emiter) {
+ _inherits(Ape, _Emiter);
+
+ function Ape(session_id, session_name, session_tag) {
+ _classCallCheck(this, Ape);
+
+ var _this = _possibleConstructorReturn(this, (Ape.__proto__ || Object.getPrototypeOf(Ape)).call(this));
+
+ _this._session_id = session_id;
+ _this._channel_id = session_id; // session_id === channel_id
+ _this._session_name = session_name;
+ _this._session_tag = session_tag;
+ _this._session_channels = {};
+ _this._adapter_pdu = new _pdus2.default['RCAdapterPdu']();
+ _this._classInfo = null;
+ _this._rCArrayBufferUtil = _ArrayBufferUtil2.default;
+ _this._apeDelayed = false;
+ _this._apeDelayedMsgs = [];
+ _this._apeDelayedTimer = 0;
+
+ //Ape 通用消息处理
+ _this.on(_pdus2.default.RCPDU_SESSION_JOIN_RESPONSE, _this._joinSessionHandler.bind(_this));
+ _this.on(_pdus2.default.RCPDU_CHANNEL_JOIN_RESPONSE, _this._joinChannelHandler.bind(_this));
+ _this.on(_pdus2.default.RCPDU_REG_ADAPTER, _this._pduMessageHandler.bind(_this));
+
+ //先收到onJoinSessionHandlerSuccess 后收到 onJoinChannelHandlerSuccess
+
+ // 监听底层MCU会议
+ _this.mcu = _mcu2.default;
+ _this.mcu.on(_MessageTypes2.default.CLASS_JOIN_MCU_SUCCESS, _this._mcuConferenceJoinSuccessHandler.bind(_this));
+ _this.mcu.registerApe(_this);
+ return _this;
+ }
+
+ _createClass(Ape, [{
+ key: 'regResponsePduHandler',
+ value: function regResponsePduHandler() {}
+
+ // 消息处理
+
+ }, {
+ key: '_pduMessageHandler',
+ value: function _pduMessageHandler(regBuffer) {
+ var _this2 = this;
+
+ //loger.log("RCPDU_REG_ADAPTER==============================");
+ if (this._apeDelayed) {
+ // this._apeDelayedMsgs.push(regBuffer);
+ // this._apeDelayedStart();
+ setTimeout(function () {
+ _this2._pduRegAdapterHandler(regBuffer);
+ }, _GlobalConfig2.default.mcuDelay || 2000);
+ return;
+ }
+ this._pduRegAdapterHandler(regBuffer);
+ }
+
+ // _apeDelayedStart() {
+ // if (this._apeDelayed && !this._apeDelayedTimer) {
+ // this._apeDelayedTimer = setInterval(this._delayedMsgHandler.bind(this), this._classInfo['mcuDelay'] || 10000);
+ // }
+ // }
+
+ // _apeDelayedStop() {
+ // clearInterval(this._apeDelayedTimer);
+ // this._apeDelayedTimer = 0;
+ // }
+
+ // // 延迟消息处理
+ // _delayedMsgHandler() {
+ // if (this._apeDelayedMsgs.length) {
+ // this._pduRegAdapterHandler(this._apeDelayedMsgs.pop());
+ // if (!this._apeDelayedMsgs.length) this._apeDelayedStop();
+ // }
+ // }
+
+ // 数据同步处理
+
+ }, {
+ key: '_pduRegAdapterHandler',
+ value: function _pduRegAdapterHandler(regBuffer) {
+ var regPdu = _pdus2.default['RCAdapterPdu'].decode(regBuffer);
+ var regItems = regPdu.item;
+ var regItemSize = regItems.length;
+ //loger.log(this._session_name + '数据同步消息');
+ loger.log(this._session_name + '数据同步消息.同步条数', regItemSize);
+ //console.log(regPdu);
+
+ for (var i = 0; i < regItemSize; ++i) {
+ var regItem = regItems[i];
+ var regItemType = regItem.type;
+ var regItemData = regItem.itemData;
+
+ //根据数据包中的type处理数据是否同步
+
+ if (_pdus2.default.RCPDU_REG_UPDATE_OBJ !== regItemType) {
+ if (_pdus2.default.RCPDU_REG_RESPONSE_OBJ == regItemType) {
+ var regResponsePdu = _pdus2.default['RCRegistryResponseObjPdu'].decode(regItemData);
+ this.regResponsePduHandler(regResponsePdu);
+ }
+ // 只处理两种类型
+ continue;
+ }
+
+ //具体的数据包
+ var regUpdatedItem = _pdus2.default['RCRegistryUpdateObjPdu'].decode(regItemData);
+ var sub_type = regUpdatedItem.subType;
+ var object_id = regUpdatedItem.objId;
+ var user_data = regUpdatedItem.userData;
+
+ loger.log('REG OBJECT EVENT ->', _pdus2.default.id2type(sub_type));
+ switch (sub_type) {
+ case _pdus2.default.RCPDU_REG_ROSTER_INSERT_PDU:
+ var rosterInsertData = _pdus2.default['RCRegstryRosterInsertItemPdu'].decode(user_data);
+ var rosterInsertItems = rosterInsertData.items;
+ var rosterInsertItemsLen = rosterInsertItems.length;
+ for (var _i = 0; _i < rosterInsertItemsLen; ++_i) {
+ var record = rosterInsertItems[_i];
+ var recordId = record.item_id;
+ var recordData = _pdus2.default['RCNodeInfoRecordPdu'].decode(record.item_data);
+ this.rosterInsertHandler(recordId, recordData);
+ }
+ break;
+ case _pdus2.default.RCPDU_REG_ROSTER_DELETE_PDU:
+ var rosterDelData = _pdus2.default['RCRegistryRosterDeleteItemPdu'].decode(user_data);
+ this.rosterDelHandler(rosterDelData.nodeId);
+ break;
+ case _pdus2.default.RCPDU_REG_ROSTER_UPDATE_PDU:
+ var rosterUpdateData = _pdus2.default['RCRegistryRosterUpdateItemPdu'].decode(user_data);
+ var rosterUpdateItems = rosterUpdateData.items;
+ var rosterUpdateItemsLen = rosterUpdateItems.length;
+ for (var _i2 = 0; _i2 < rosterUpdateItemsLen; ++_i2) {
+ var node = rosterUpdateItems[_i2];
+ var nodeId = node.nodeId;
+ var nodeData = _pdus2.default['RCNodeInfoRecordPdu'].decode(node.nodeData);
+ this.rosterUpdateHandler(nodeId, nodeData);
+ }
+ break;
+ case _pdus2.default.RCPDU_REG_TABLE_INSERT_PDU:
+ var tableInsertData = _pdus2.default['RCRegistryTableInsertItemPdu'].decode(user_data);
+ var tableInsertItems = tableInsertData.items;
+ var tableInsertItemsLen = tableInsertItems.length;
+ for (var _i3 = 0; _i3 < tableInsertItemsLen; ++_i3) {
+ var insertItem = tableInsertItems[_i3];
+ //loger.log("insertItem",insertItem);
+ this.tableInsertHandler(insertItem.owner, insertItem.itemIdx, insertItem.itemData);
+ }
+ break;
+ case _pdus2.default.RCPDU_REG_TABLE_DELETE_PDU:
+ var tableDeleteData = _pdus2.default['RCRegistryTableDeleteItemPdu'].decode(user_data);
+ //console.log("tableDeleteData",object_id,tableDeleteData);
+ this.tableDeleteHandler(object_id, tableDeleteData);
+ break;
+ case _pdus2.default.RCPDU_REG_TABLE_UPDATE_PDU:
+ var tableUpdateData = _pdus2.default['RCRegistryTableUpdateItemPdu'].decode(user_data);
+ var tableUpdateItems = tableUpdateData.items;
+ var tableUpdateItemsLen = tableUpdateItems.length;
+ loger.log("RCRegistryTableUpdateItemPdu " + tableUpdateItemsLen);
+ console.log(tableUpdateData);
+
+ for (var _i4 = 0; _i4 < tableUpdateItemsLen; ++_i4) {
+ var tableItem = tableUpdateItems[_i4];
+ this.tableUpdateHandler(tableItem.owner, tableItem.itemIdx, tableItem.itemData);
+ }
+ break;
+ case _pdus2.default.RCPDU_REG_QUEUE_UPDATE_PDU:
+ case _pdus2.default.RCPDU_REG_QUEUE_DELETE_PDU:
+ case _pdus2.default.RCPDU_REG_QUEUE_INSERT_PDU:
+ loger.warn('REG QUEUE ARE IGNORED');
+ break;
+
+ }
+ }
+ }
+ }, {
+ key: 'rosterInsertHandler',
+ value: function rosterInsertHandler(recordId, recordData) {
+ loger.warn(this._session_name + ' rosterInsertHandler 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'rosterUpdateHandler',
+ value: function rosterUpdateHandler(nodeId, nodeData) {
+ loger.warn(this._session_name + ' rosterUpdateHandler 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'rosterDelHandler',
+ value: function rosterDelHandler(recordData) {
+ loger.warn(this._session_name + ' rosterDelHandler 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'tableInsertHandler',
+ value: function tableInsertHandler(tableId, record) {
+ loger.warn(this._session_name + ' tableInsertHandler 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'tableUpdateHandler',
+ value: function tableUpdateHandler(ownerId, recordId, recordData) {
+ loger.warn(this._session_name + ' tableUpdateHandler 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'tableDeleteHandler',
+ value: function tableDeleteHandler(tableId, record) {
+ loger.warn(this._session_name + ' tableDelHandler 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'onJoinChannelHandlerSuccess',
+ value: function onJoinChannelHandlerSuccess() {
+ loger.warn(this._session_name + ' onJoinChannelHandlerSuccess 应有子类具体覆盖处理.');
+ }
+ }, {
+ key: 'onJoinSessionHandlerSuccess',
+ value: function onJoinSessionHandlerSuccess() {
+ loger.warn(this._session_name + ' onJoinSessionHandlerSuccess 应有子类具体覆盖处理.');
+ }
+ // 加入Session处理
+
+ }, {
+ key: '_joinSessionHandler',
+ value: function _joinSessionHandler(data) {
+ loger.log(this._session_name, ' -> 加入Session');
+ this.onJoinSessionHandlerSuccess();
+ }
+
+ // 加入Channel处理
+
+ }, {
+ key: '_joinChannelHandler',
+ value: function _joinChannelHandler(data) {
+ var joinedChannel = _pdus2.default['RCChannelJoinResponsePdu'].decode(data);
+ if (joinedChannel.result === _pdus2.default.RET_SUCCESS) {
+ loger.log(this._session_name, ' -> 加入Channel成功. ChannelId', joinedChannel.requestedChannelId);
+ this._session_channels[joinedChannel.requestedChannelId] = _ApeConsts2.default.CJS_JOINNED;
+ this.onJoinChannelHandlerSuccess();
+ } else {
+ loger.log(this._session_name, ' -> 加入Channel失败.', joinedChannel);
+ }
+ }
+
+ // 依赖的会议创建完毕 - 发起Ape加入
+
+ }, {
+ key: '_mcuConferenceJoinSuccessHandler',
+ value: function _mcuConferenceJoinSuccessHandler(_data) {
+ loger.log('创建Ape->', 'SessionId', this._session_id, 'SessionName', this._session_name, 'SessionTag', this._session_tag);
+
+ // 会议依赖底层会议信息
+ //this._classInfo = classInfo;
+ this._classInfo = _GlobalConfig2.default.getClassInfo();
+
+ var joinSessionPdu = new _pdus2.default['RCSessionJoinRequestPdu']();
+ joinSessionPdu.id = this._session_id;
+ joinSessionPdu.name = this._session_name;
+ joinSessionPdu.tag = this._session_tag;
+ joinSessionPdu.sessionData = this._adapter_pdu.toArrayBuffer();
+ this.sendUniform(joinSessionPdu, true);
+
+ var joinChannelPdu = new _pdus2.default['RCChannelJoinRequestPdu']();
+ joinChannelPdu.initiator = this.mcu.classInfo.nodeId;
+ joinChannelPdu.channelId = this._session_id;
+ this.send(joinChannelPdu);
+ }
+
+ // 注册Key对象
+
+ }, {
+ key: 'registerKey',
+ value: function registerKey(id, name, tag, user_data) {
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_REGISTER_KEY;
+
+ // pack register key pdus
+ var registerKeyPdu = new _pdus2.default['RCRegistryRegisterKeyPdu']();
+ registerKeyPdu.id = id;
+ registerKeyPdu.name = name;
+ registerKeyPdu.tag = tag;
+ if (user_data.length) {
+ registerKeyPdu.userData = user_data;
+ }
+
+ adapterItemPdu.itemData = registerKeyPdu.toArrayBuffer();
+ this._adapter_pdu.item.push(adapterItemPdu);
+ }
+
+ // 注册Object对象 等同于flash中的 RCRegistryOperator
+
+ }, {
+ key: 'registerObj',
+ value: function registerObj(type, id, name, tag, owner, user_data) {
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_REGISTER_OBJ;
+
+ var registerObjPdu = new _pdus2.default['RCRegistryRegisterObjPdu']();
+ registerObjPdu.type = type;
+ registerObjPdu.objId = id;
+ registerObjPdu.name = name;
+ registerObjPdu.tag = tag;
+ if (owner) {
+ registerObjPdu.owner = owner;
+ }
+ if (user_data.length) {
+ registerObjPdu.userData = user_data;
+ }
+
+ adapterItemPdu.itemData = registerObjPdu.toArrayBuffer();
+ this._adapter_pdu.item.push(adapterItemPdu);
+ }
+ }, {
+ key: 'send',
+ value: function send(appPdu) {
+ loger.log('Ape发送数据NORMAL PDU');
+ console.log(appPdu);
+ //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
+ if (_GlobalConfig2.default.getCurrentStatus().code == 0 || _GlobalConfig2.default.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return;
+ }
+ var normalPdu = _pdus2.default.create_normal_pdu(appPdu.type, this._classInfo.nodeId, this._classInfo.classId, this._session_id, this._channel_id, true, true, _PduConsts2.default.DP_TOP, this._classInfo.topNodeID, _PduConsts2.default.SEG_ONCE);
+ normalPdu.data = appPdu.toArrayBuffer();
+ // Mcu发送
+ this.mcu.send(normalPdu);
+ }
+
+ // 发送当前APE(session uniform包)
+
+ }, {
+ key: 'sendUniform',
+ value: function sendUniform(appPdu, top) {
+ loger.log('Ape发送数据UNIFORM PDU');
+ console.log(appPdu);
+ //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
+ if (_GlobalConfig2.default.getCurrentStatus().code == 0 || _GlobalConfig2.default.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return;
+ }
+
+ var uniformPdu = _pdus2.default.create_uniform_pdu(appPdu.type, this._classInfo.nodeId, this._classInfo.classId, this._session_id, top ? _ApeConsts2.default.BROADCAST_CHANNEL_ID : this._channel_id, true, _PduConsts2.default.DP_TOP, top ? this._classInfo.topNodeID : appPdu.peer || 0, _PduConsts2.default.SEG_ONCE);
+ uniformPdu.data = appPdu.toArrayBuffer();
+ // Mcu发送
+ this.mcu.send(uniformPdu);
+ }
+ }, {
+ key: 'sendChatUniform',
+ value: function sendChatUniform(appPdu, top) {
+ loger.log('Ape发送数据UNIFORM PDU');
+ console.log(appPdu);
+ //loger.log('当前的状态============',GlobalConfig.getCurrentStatus().code);
+ if (_GlobalConfig2.default.getCurrentStatus().code == 0 || _GlobalConfig2.default.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return;
+ }
+
+ var uniformPdu = _pdus2.default.create_uniform_pdu(appPdu.type, this._classInfo.nodeId, this._classInfo.classId, this._session_id, top ? _ApeConsts2.default.BROADCAST_CHANNEL_ID : this._channel_id, true, _PduConsts2.default.DP_TOP, 0, //flash中这个值设置为0
+ _PduConsts2.default.SEG_ONCE);
+ uniformPdu.data = appPdu.toArrayBuffer();
+ // Mcu发送
+ this.mcu.send(uniformPdu);
+ }
+ }]);
+
+ return Ape;
+ }(_Emiter3.default);
+
+ var _default = Ape;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/Ape.js');
+
+ __REACT_HOT_LOADER__.register(Ape, 'Ape', 'D:/work/McuClient/src/apes/Ape.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/Ape.js');
+ }();
+
+ ;
+
+/***/ },
+/* 38 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ var ArrayBufferUtil = function () {
+ function ArrayBufferUtil() {
+ _classCallCheck(this, ArrayBufferUtil);
+ }
+
+ _createClass(ArrayBufferUtil, null, [{
+ key: "ab2str",
+ value: function ab2str(buf) {
+ return String.fromCharCode.apply(null, new Uint16Array(buf));
+ }
+ }, {
+ key: "str2ab",
+ value: function str2ab(str) {
+ var buf = new ArrayBuffer(str.length * 2); // one char use 2 byte
+ var bufView = new Uint16Array(buf);
+ for (var i = 0, strLen = str.length; i < strLen; i++) {
+ bufView[i] = str.charCodeAt(i);
+ }
+ return buf;
+ }
+ }, {
+ key: "strToUint8Array",
+ value: function strToUint8Array(str) {
+ var out = void 0,
+ i = void 0,
+ len = void 0,
+ c = void 0;
+ out = "";
+ len = str.length;
+ var uintArray = [];
+ for (i = 0; i < len; i++) {
+ c = str.charCodeAt(i);
+ if (c >= 0x0001 && c <= 0x007F) {
+ uintArray.push(c);
+ } else if (c > 0x07FF) {
+ uintArray.push(0xE0 | c >> 12 & 0x0F);
+ uintArray.push(0x80 | c >> 6 & 0x3F);
+ uintArray.push(0x80 | c >> 0 & 0x3F);
+ //out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
+ //out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
+ //out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
+ } else {
+ uintArray.push(0xC0 | c >> 6 & 0x1F);
+ uintArray.push(0x80 | c >> 0 & 0x3F);
+ //out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
+ //out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
+ }
+ }
+ return new Uint8Array(uintArray);
+ }
+ }, {
+ key: "uint8ArrayToStr",
+ value: function uint8ArrayToStr(uint8, index) {
+ var out = void 0,
+ i = void 0,
+ len = void 0,
+ c = void 0;
+ var char2 = void 0,
+ char3 = void 0;
+ out = "";
+ len = uint8.buffer.byteLength;
+ i = uint8.offset + index; //pzm update 前两个字符乱码
+ while (i < uint8.limit) {
+ c = uint8.view[i++];
+ switch (c >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ // 0xxxxxxx
+ out += String.fromCharCode(uint8.view[i - 1]);
+ break;
+ case 12:
+ case 13:
+ // 110x xxxx 10xx xxxx
+ char2 = uint8.view[i++];
+ out += String.fromCharCode((c & 0x1F) << 6 | char2 & 0x3F);
+ break;
+ case 14:
+ // 1110 xxxx 10xx xxxx 10xx xxxx
+ char2 = uint8.view[i++];
+ char3 = uint8.view[i++];
+ out += String.fromCharCode((c & 0x0F) << 12 | (char2 & 0x3F) << 6 | (char3 & 0x3F) << 0);
+ break;
+ }
+ }
+ return out;
+ }
+ }]);
+
+ return ArrayBufferUtil;
+ }();
+
+ var _default = ArrayBufferUtil;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(ArrayBufferUtil, "ArrayBufferUtil", "D:/work/McuClient/src/libs/ArrayBufferUtil.js");
+
+ __REACT_HOT_LOADER__.register(_default, "default", "D:/work/McuClient/src/libs/ArrayBufferUtil.js");
+ }();
+
+ ;
+
+/***/ },
+/* 39 */
+/***/ function(module, exports) {
+
+ /** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function l(d){throw d;}var v=void 0,x=!0,aa=this;function D(d,a){var c=d.split("."),e=aa;!(c[0]in e)&&e.execScript&&e.execScript("var "+c[0]);for(var b;c.length&&(b=c.shift());)!c.length&&a!==v?e[b]=a:e=e[b]?e[b]:e[b]={}};var F="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function H(d,a){this.index="number"===typeof a?a:0;this.i=0;this.buffer=d instanceof(F?Uint8Array:Array)?d:new (F?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&l(Error("invalid index"));this.buffer.length<=this.index&&this.f()}H.prototype.f=function(){var d=this.buffer,a,c=d.length,e=new (F?Uint8Array:Array)(c<<1);if(F)e.set(d);else for(a=0;a<c;++a)e[a]=d[a];return this.buffer=e};
+ H.prototype.d=function(d,a,c){var e=this.buffer,b=this.index,f=this.i,g=e[b],h;c&&1<a&&(d=8<a?(N[d&255]<<24|N[d>>>8&255]<<16|N[d>>>16&255]<<8|N[d>>>24&255])>>32-a:N[d]>>8-a);if(8>a+f)g=g<<a|d,f+=a;else for(h=0;h<a;++h)g=g<<1|d>>a-h-1&1,8===++f&&(f=0,e[b++]=N[g],g=0,b===e.length&&(e=this.f()));e[b]=g;this.buffer=e;this.i=f;this.index=b};H.prototype.finish=function(){var d=this.buffer,a=this.index,c;0<this.i&&(d[a]<<=8-this.i,d[a]=N[d[a]],a++);F?c=d.subarray(0,a):(d.length=a,c=d);return c};
+ var fa=new (F?Uint8Array:Array)(256),O;for(O=0;256>O;++O){for(var P=O,Q=P,ga=7,P=P>>>1;P;P>>>=1)Q<<=1,Q|=P&1,--ga;fa[O]=(Q<<ga&255)>>>0}var N=fa;function ha(d){this.buffer=new (F?Uint16Array:Array)(2*d);this.length=0}ha.prototype.getParent=function(d){return 2*((d-2)/4|0)};ha.prototype.push=function(d,a){var c,e,b=this.buffer,f;c=this.length;b[this.length++]=a;for(b[this.length++]=d;0<c;)if(e=this.getParent(c),b[c]>b[e])f=b[c],b[c]=b[e],b[e]=f,f=b[c+1],b[c+1]=b[e+1],b[e+1]=f,c=e;else break;return this.length};
+ ha.prototype.pop=function(){var d,a,c=this.buffer,e,b,f;a=c[0];d=c[1];this.length-=2;c[0]=c[this.length];c[1]=c[this.length+1];for(f=0;;){b=2*f+2;if(b>=this.length)break;b+2<this.length&&c[b+2]>c[b]&&(b+=2);if(c[b]>c[f])e=c[f],c[f]=c[b],c[b]=e,e=c[f+1],c[f+1]=c[b+1],c[b+1]=e;else break;f=b}return{index:d,value:a,length:this.length}};function R(d){var a=d.length,c=0,e=Number.POSITIVE_INFINITY,b,f,g,h,k,n,q,r,p,m;for(r=0;r<a;++r)d[r]>c&&(c=d[r]),d[r]<e&&(e=d[r]);b=1<<c;f=new (F?Uint32Array:Array)(b);g=1;h=0;for(k=2;g<=c;){for(r=0;r<a;++r)if(d[r]===g){n=0;q=h;for(p=0;p<g;++p)n=n<<1|q&1,q>>=1;m=g<<16|r;for(p=n;p<b;p+=k)f[p]=m;++h}++g;h<<=1;k<<=1}return[f,c,e]};function ia(d,a){this.h=ma;this.w=0;this.input=F&&d instanceof Array?new Uint8Array(d):d;this.b=0;a&&(a.lazy&&(this.w=a.lazy),"number"===typeof a.compressionType&&(this.h=a.compressionType),a.outputBuffer&&(this.a=F&&a.outputBuffer instanceof Array?new Uint8Array(a.outputBuffer):a.outputBuffer),"number"===typeof a.outputIndex&&(this.b=a.outputIndex));this.a||(this.a=new (F?Uint8Array:Array)(32768))}var ma=2,na={NONE:0,r:1,k:ma,O:3},oa=[],S;
+ for(S=0;288>S;S++)switch(x){case 143>=S:oa.push([S+48,8]);break;case 255>=S:oa.push([S-144+400,9]);break;case 279>=S:oa.push([S-256+0,7]);break;case 287>=S:oa.push([S-280+192,8]);break;default:l("invalid literal: "+S)}
+ ia.prototype.j=function(){var d,a,c,e,b=this.input;switch(this.h){case 0:c=0;for(e=b.length;c<e;){a=F?b.subarray(c,c+65535):b.slice(c,c+65535);c+=a.length;var f=a,g=c===e,h=v,k=v,n=v,q=v,r=v,p=this.a,m=this.b;if(F){for(p=new Uint8Array(this.a.buffer);p.length<=m+f.length+5;)p=new Uint8Array(p.length<<1);p.set(this.a)}h=g?1:0;p[m++]=h|0;k=f.length;n=~k+65536&65535;p[m++]=k&255;p[m++]=k>>>8&255;p[m++]=n&255;p[m++]=n>>>8&255;if(F)p.set(f,m),m+=f.length,p=p.subarray(0,m);else{q=0;for(r=f.length;q<r;++q)p[m++]=
+ f[q];p.length=m}this.b=m;this.a=p}break;case 1:var s=new H(F?new Uint8Array(this.a.buffer):this.a,this.b);s.d(1,1,x);s.d(1,2,x);var w=pa(this,b),y,ja,A;y=0;for(ja=w.length;y<ja;y++)if(A=w[y],H.prototype.d.apply(s,oa[A]),256<A)s.d(w[++y],w[++y],x),s.d(w[++y],5),s.d(w[++y],w[++y],x);else if(256===A)break;this.a=s.finish();this.b=this.a.length;break;case ma:var C=new H(F?new Uint8Array(this.a.buffer):this.a,this.b),Ea,M,U,V,W,gb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],ba,Fa,ca,Ga,ka,ra=Array(19),
+ Ha,X,la,z,Ia;Ea=ma;C.d(1,1,x);C.d(Ea,2,x);M=pa(this,b);ba=qa(this.M,15);Fa=sa(ba);ca=qa(this.L,7);Ga=sa(ca);for(U=286;257<U&&0===ba[U-1];U--);for(V=30;1<V&&0===ca[V-1];V--);var Ja=U,Ka=V,I=new (F?Uint32Array:Array)(Ja+Ka),t,J,u,da,G=new (F?Uint32Array:Array)(316),E,B,K=new (F?Uint8Array:Array)(19);for(t=J=0;t<Ja;t++)I[J++]=ba[t];for(t=0;t<Ka;t++)I[J++]=ca[t];if(!F){t=0;for(da=K.length;t<da;++t)K[t]=0}t=E=0;for(da=I.length;t<da;t+=J){for(J=1;t+J<da&&I[t+J]===I[t];++J);u=J;if(0===I[t])if(3>u)for(;0<
+ u--;)G[E++]=0,K[0]++;else for(;0<u;)B=138>u?u:138,B>u-3&&B<u&&(B=u-3),10>=B?(G[E++]=17,G[E++]=B-3,K[17]++):(G[E++]=18,G[E++]=B-11,K[18]++),u-=B;else if(G[E++]=I[t],K[I[t]]++,u--,3>u)for(;0<u--;)G[E++]=I[t],K[I[t]]++;else for(;0<u;)B=6>u?u:6,B>u-3&&B<u&&(B=u-3),G[E++]=16,G[E++]=B-3,K[16]++,u-=B}d=F?G.subarray(0,E):G.slice(0,E);ka=qa(K,7);for(z=0;19>z;z++)ra[z]=ka[gb[z]];for(W=19;4<W&&0===ra[W-1];W--);Ha=sa(ka);C.d(U-257,5,x);C.d(V-1,5,x);C.d(W-4,4,x);for(z=0;z<W;z++)C.d(ra[z],3,x);z=0;for(Ia=d.length;z<
+ Ia;z++)if(X=d[z],C.d(Ha[X],ka[X],x),16<=X){z++;switch(X){case 16:la=2;break;case 17:la=3;break;case 18:la=7;break;default:l("invalid code: "+X)}C.d(d[z],la,x)}var La=[Fa,ba],Ma=[Ga,ca],L,Na,ea,ua,Oa,Pa,Qa,Ra;Oa=La[0];Pa=La[1];Qa=Ma[0];Ra=Ma[1];L=0;for(Na=M.length;L<Na;++L)if(ea=M[L],C.d(Oa[ea],Pa[ea],x),256<ea)C.d(M[++L],M[++L],x),ua=M[++L],C.d(Qa[ua],Ra[ua],x),C.d(M[++L],M[++L],x);else if(256===ea)break;this.a=C.finish();this.b=this.a.length;break;default:l("invalid compression type")}return this.a};
+ function ta(d,a){this.length=d;this.H=a}
+ var va=function(){function d(b){switch(x){case 3===b:return[257,b-3,0];case 4===b:return[258,b-4,0];case 5===b:return[259,b-5,0];case 6===b:return[260,b-6,0];case 7===b:return[261,b-7,0];case 8===b:return[262,b-8,0];case 9===b:return[263,b-9,0];case 10===b:return[264,b-10,0];case 12>=b:return[265,b-11,1];case 14>=b:return[266,b-13,1];case 16>=b:return[267,b-15,1];case 18>=b:return[268,b-17,1];case 22>=b:return[269,b-19,2];case 26>=b:return[270,b-23,2];case 30>=b:return[271,b-27,2];case 34>=b:return[272,
+ b-31,2];case 42>=b:return[273,b-35,3];case 50>=b:return[274,b-43,3];case 58>=b:return[275,b-51,3];case 66>=b:return[276,b-59,3];case 82>=b:return[277,b-67,4];case 98>=b:return[278,b-83,4];case 114>=b:return[279,b-99,4];case 130>=b:return[280,b-115,4];case 162>=b:return[281,b-131,5];case 194>=b:return[282,b-163,5];case 226>=b:return[283,b-195,5];case 257>=b:return[284,b-227,5];case 258===b:return[285,b-258,0];default:l("invalid length: "+b)}}var a=[],c,e;for(c=3;258>=c;c++)e=d(c),a[c]=e[2]<<24|e[1]<<
+ 16|e[0];return a}(),wa=F?new Uint32Array(va):va;
+ function pa(d,a){function c(b,c){var a=b.H,d=[],e=0,f;f=wa[b.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(x){case 1===a:g=[0,a-1,0];break;case 2===a:g=[1,a-2,0];break;case 3===a:g=[2,a-3,0];break;case 4===a:g=[3,a-4,0];break;case 6>=a:g=[4,a-5,1];break;case 8>=a:g=[5,a-7,1];break;case 12>=a:g=[6,a-9,2];break;case 16>=a:g=[7,a-13,2];break;case 24>=a:g=[8,a-17,3];break;case 32>=a:g=[9,a-25,3];break;case 48>=a:g=[10,a-33,4];break;case 64>=a:g=[11,a-49,4];break;case 96>=a:g=[12,a-
+ 65,5];break;case 128>=a:g=[13,a-97,5];break;case 192>=a:g=[14,a-129,6];break;case 256>=a:g=[15,a-193,6];break;case 384>=a:g=[16,a-257,7];break;case 512>=a:g=[17,a-385,7];break;case 768>=a:g=[18,a-513,8];break;case 1024>=a:g=[19,a-769,8];break;case 1536>=a:g=[20,a-1025,9];break;case 2048>=a:g=[21,a-1537,9];break;case 3072>=a:g=[22,a-2049,10];break;case 4096>=a:g=[23,a-3073,10];break;case 6144>=a:g=[24,a-4097,11];break;case 8192>=a:g=[25,a-6145,11];break;case 12288>=a:g=[26,a-8193,12];break;case 16384>=
+ a:g=[27,a-12289,12];break;case 24576>=a:g=[28,a-16385,13];break;case 32768>=a:g=[29,a-24577,13];break;default:l("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,k;h=0;for(k=d.length;h<k;++h)p[m++]=d[h];w[d[0]]++;y[d[3]]++;s=b.length+c-1;r=null}var e,b,f,g,h,k={},n,q,r,p=F?new Uint16Array(2*a.length):[],m=0,s=0,w=new (F?Uint32Array:Array)(286),y=new (F?Uint32Array:Array)(30),ja=d.w,A;if(!F){for(f=0;285>=f;)w[f++]=0;for(f=0;29>=f;)y[f++]=0}w[256]=1;e=0;for(b=a.length;e<b;++e){f=h=0;
+ for(g=3;f<g&&e+f!==b;++f)h=h<<8|a[e+f];k[h]===v&&(k[h]=[]);n=k[h];if(!(0<s--)){for(;0<n.length&&32768<e-n[0];)n.shift();if(e+3>=b){r&&c(r,-1);f=0;for(g=b-e;f<g;++f)A=a[e+f],p[m++]=A,++w[A];break}0<n.length?(q=xa(a,e,n),r?r.length<q.length?(A=a[e-1],p[m++]=A,++w[A],c(q,0)):c(r,-1):q.length<ja?r=q:c(q,0)):r?c(r,-1):(A=a[e],p[m++]=A,++w[A])}n.push(e)}p[m++]=256;w[256]++;d.M=w;d.L=y;return F?p.subarray(0,m):p}
+ function xa(d,a,c){var e,b,f=0,g,h,k,n,q=d.length;h=0;n=c.length;a:for(;h<n;h++){e=c[n-h-1];g=3;if(3<f){for(k=f;3<k;k--)if(d[e+k-1]!==d[a+k-1])continue a;g=f}for(;258>g&&a+g<q&&d[e+g]===d[a+g];)++g;g>f&&(b=e,f=g);if(258===g)break}return new ta(f,a-b)}
+ function qa(d,a){var c=d.length,e=new ha(572),b=new (F?Uint8Array:Array)(c),f,g,h,k,n;if(!F)for(k=0;k<c;k++)b[k]=0;for(k=0;k<c;++k)0<d[k]&&e.push(k,d[k]);f=Array(e.length/2);g=new (F?Uint32Array:Array)(e.length/2);if(1===f.length)return b[e.pop().index]=1,b;k=0;for(n=e.length/2;k<n;++k)f[k]=e.pop(),g[k]=f[k].value;h=ya(g,g.length,a);k=0;for(n=f.length;k<n;++k)b[f[k].index]=h[k];return b}
+ function ya(d,a,c){function e(b){var c=k[b][n[b]];c===a?(e(b+1),e(b+1)):--g[c];++n[b]}var b=new (F?Uint16Array:Array)(c),f=new (F?Uint8Array:Array)(c),g=new (F?Uint8Array:Array)(a),h=Array(c),k=Array(c),n=Array(c),q=(1<<c)-a,r=1<<c-1,p,m,s,w,y;b[c-1]=a;for(m=0;m<c;++m)q<r?f[m]=0:(f[m]=1,q-=r),q<<=1,b[c-2-m]=(b[c-1-m]/2|0)+a;b[0]=f[0];h[0]=Array(b[0]);k[0]=Array(b[0]);for(m=1;m<c;++m)b[m]>2*b[m-1]+f[m]&&(b[m]=2*b[m-1]+f[m]),h[m]=Array(b[m]),k[m]=Array(b[m]);for(p=0;p<a;++p)g[p]=c;for(s=0;s<b[c-1];++s)h[c-
+ 1][s]=d[s],k[c-1][s]=s;for(p=0;p<c;++p)n[p]=0;1===f[c-1]&&(--g[0],++n[c-1]);for(m=c-2;0<=m;--m){w=p=0;y=n[m+1];for(s=0;s<b[m];s++)w=h[m+1][y]+h[m+1][y+1],w>d[p]?(h[m][s]=w,k[m][s]=a,y+=2):(h[m][s]=d[p],k[m][s]=p,++p);n[m]=0;1===f[m]&&e(m)}return g}
+ function sa(d){var a=new (F?Uint16Array:Array)(d.length),c=[],e=[],b=0,f,g,h,k;f=0;for(g=d.length;f<g;f++)c[d[f]]=(c[d[f]]|0)+1;f=1;for(g=16;f<=g;f++)e[f]=b,b+=c[f]|0,b<<=1;f=0;for(g=d.length;f<g;f++){b=e[d[f]];e[d[f]]+=1;h=a[f]=0;for(k=d[f];h<k;h++)a[f]=a[f]<<1|b&1,b>>>=1}return a};function T(d,a){this.l=[];this.m=32768;this.e=this.g=this.c=this.q=0;this.input=F?new Uint8Array(d):d;this.s=!1;this.n=za;this.C=!1;if(a||!(a={}))a.index&&(this.c=a.index),a.bufferSize&&(this.m=a.bufferSize),a.bufferType&&(this.n=a.bufferType),a.resize&&(this.C=a.resize);switch(this.n){case Aa:this.b=32768;this.a=new (F?Uint8Array:Array)(32768+this.m+258);break;case za:this.b=0;this.a=new (F?Uint8Array:Array)(this.m);this.f=this.K;this.t=this.I;this.o=this.J;break;default:l(Error("invalid inflate mode"))}}
+ var Aa=0,za=1,Ba={F:Aa,D:za};
+ T.prototype.p=function(){for(;!this.s;){var d=Y(this,3);d&1&&(this.s=x);d>>>=1;switch(d){case 0:var a=this.input,c=this.c,e=this.a,b=this.b,f=a.length,g=v,h=v,k=e.length,n=v;this.e=this.g=0;c+1>=f&&l(Error("invalid uncompressed block header: LEN"));g=a[c++]|a[c++]<<8;c+1>=f&&l(Error("invalid uncompressed block header: NLEN"));h=a[c++]|a[c++]<<8;g===~h&&l(Error("invalid uncompressed block header: length verify"));c+g>a.length&&l(Error("input buffer is broken"));switch(this.n){case Aa:for(;b+g>e.length;){n=
+ k-b;g-=n;if(F)e.set(a.subarray(c,c+n),b),b+=n,c+=n;else for(;n--;)e[b++]=a[c++];this.b=b;e=this.f();b=this.b}break;case za:for(;b+g>e.length;)e=this.f({v:2});break;default:l(Error("invalid inflate mode"))}if(F)e.set(a.subarray(c,c+g),b),b+=g,c+=g;else for(;g--;)e[b++]=a[c++];this.c=c;this.b=b;this.a=e;break;case 1:this.o(Ca,Da);break;case 2:Sa(this);break;default:l(Error("unknown BTYPE: "+d))}}return this.t()};
+ var Ta=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Ua=F?new Uint16Array(Ta):Ta,Va=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],Wa=F?new Uint16Array(Va):Va,Xa=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],Ya=F?new Uint8Array(Xa):Xa,Za=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],$a=F?new Uint16Array(Za):Za,ab=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,
+ 10,11,11,12,12,13,13],bb=F?new Uint8Array(ab):ab,cb=new (F?Uint8Array:Array)(288),Z,db;Z=0;for(db=cb.length;Z<db;++Z)cb[Z]=143>=Z?8:255>=Z?9:279>=Z?7:8;var Ca=R(cb),eb=new (F?Uint8Array:Array)(30),fb,hb;fb=0;for(hb=eb.length;fb<hb;++fb)eb[fb]=5;var Da=R(eb);function Y(d,a){for(var c=d.g,e=d.e,b=d.input,f=d.c,g=b.length,h;e<a;)f>=g&&l(Error("input buffer is broken")),c|=b[f++]<<e,e+=8;h=c&(1<<a)-1;d.g=c>>>a;d.e=e-a;d.c=f;return h}
+ function ib(d,a){for(var c=d.g,e=d.e,b=d.input,f=d.c,g=b.length,h=a[0],k=a[1],n,q;e<k&&!(f>=g);)c|=b[f++]<<e,e+=8;n=h[c&(1<<k)-1];q=n>>>16;d.g=c>>q;d.e=e-q;d.c=f;return n&65535}
+ function Sa(d){function a(a,b,c){var d,e=this.z,f,g;for(g=0;g<a;)switch(d=ib(this,b),d){case 16:for(f=3+Y(this,2);f--;)c[g++]=e;break;case 17:for(f=3+Y(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+Y(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}this.z=e;return c}var c=Y(d,5)+257,e=Y(d,5)+1,b=Y(d,4)+4,f=new (F?Uint8Array:Array)(Ua.length),g,h,k,n;for(n=0;n<b;++n)f[Ua[n]]=Y(d,3);if(!F){n=b;for(b=f.length;n<b;++n)f[Ua[n]]=0}g=R(f);h=new (F?Uint8Array:Array)(c);k=new (F?Uint8Array:Array)(e);
+ d.z=0;d.o(R(a.call(d,c,g,h)),R(a.call(d,e,g,k)))}T.prototype.o=function(d,a){var c=this.a,e=this.b;this.u=d;for(var b=c.length-258,f,g,h,k;256!==(f=ib(this,d));)if(256>f)e>=b&&(this.b=e,c=this.f(),e=this.b),c[e++]=f;else{g=f-257;k=Wa[g];0<Ya[g]&&(k+=Y(this,Ya[g]));f=ib(this,a);h=$a[f];0<bb[f]&&(h+=Y(this,bb[f]));e>=b&&(this.b=e,c=this.f(),e=this.b);for(;k--;)c[e]=c[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e};
+ T.prototype.J=function(d,a){var c=this.a,e=this.b;this.u=d;for(var b=c.length,f,g,h,k;256!==(f=ib(this,d));)if(256>f)e>=b&&(c=this.f(),b=c.length),c[e++]=f;else{g=f-257;k=Wa[g];0<Ya[g]&&(k+=Y(this,Ya[g]));f=ib(this,a);h=$a[f];0<bb[f]&&(h+=Y(this,bb[f]));e+k>b&&(c=this.f(),b=c.length);for(;k--;)c[e]=c[e++-h]}for(;8<=this.e;)this.e-=8,this.c--;this.b=e};
+ T.prototype.f=function(){var d=new (F?Uint8Array:Array)(this.b-32768),a=this.b-32768,c,e,b=this.a;if(F)d.set(b.subarray(32768,d.length));else{c=0;for(e=d.length;c<e;++c)d[c]=b[c+32768]}this.l.push(d);this.q+=d.length;if(F)b.set(b.subarray(a,a+32768));else for(c=0;32768>c;++c)b[c]=b[a+c];this.b=32768;return b};
+ T.prototype.K=function(d){var a,c=this.input.length/this.c+1|0,e,b,f,g=this.input,h=this.a;d&&("number"===typeof d.v&&(c=d.v),"number"===typeof d.G&&(c+=d.G));2>c?(e=(g.length-this.c)/this.u[2],f=258*(e/2)|0,b=f<h.length?h.length+f:h.length<<1):b=h.length*c;F?(a=new Uint8Array(b),a.set(h)):a=h;return this.a=a};
+ T.prototype.t=function(){var d=0,a=this.a,c=this.l,e,b=new (F?Uint8Array:Array)(this.q+(this.b-32768)),f,g,h,k;if(0===c.length)return F?this.a.subarray(32768,this.b):this.a.slice(32768,this.b);f=0;for(g=c.length;f<g;++f){e=c[f];h=0;for(k=e.length;h<k;++h)b[d++]=e[h]}f=32768;for(g=this.b;f<g;++f)b[d++]=a[f];this.l=[];return this.buffer=b};
+ T.prototype.I=function(){var d,a=this.b;F?this.C?(d=new Uint8Array(a),d.set(this.a.subarray(0,a))):d=this.a.subarray(0,a):(this.a.length>a&&(this.a.length=a),d=this.a);return this.buffer=d};function jb(d){if("string"===typeof d){var a=d.split(""),c,e;c=0;for(e=a.length;c<e;c++)a[c]=(a[c].charCodeAt(0)&255)>>>0;d=a}for(var b=1,f=0,g=d.length,h,k=0;0<g;){h=1024<g?1024:g;g-=h;do b+=d[k++],f+=b;while(--h);b%=65521;f%=65521}return(f<<16|b)>>>0};function kb(d,a){var c,e;this.input=d;this.c=0;if(a||!(a={}))a.index&&(this.c=a.index),a.verify&&(this.N=a.verify);c=d[this.c++];e=d[this.c++];switch(c&15){case lb:this.method=lb;break;default:l(Error("unsupported compression method"))}0!==((c<<8)+e)%31&&l(Error("invalid fcheck flag:"+((c<<8)+e)%31));e&32&&l(Error("fdict flag is not supported"));this.B=new T(d,{index:this.c,bufferSize:a.bufferSize,bufferType:a.bufferType,resize:a.resize})}
+ kb.prototype.p=function(){var d=this.input,a,c;a=this.B.p();this.c=this.B.c;this.N&&(c=(d[this.c++]<<24|d[this.c++]<<16|d[this.c++]<<8|d[this.c++])>>>0,c!==jb(a)&&l(Error("invalid adler-32 checksum")));return a};var lb=8;function mb(d,a){this.input=d;this.a=new (F?Uint8Array:Array)(32768);this.h=$.k;var c={},e;if((a||!(a={}))&&"number"===typeof a.compressionType)this.h=a.compressionType;for(e in a)c[e]=a[e];c.outputBuffer=this.a;this.A=new ia(this.input,c)}var $=na;
+ mb.prototype.j=function(){var d,a,c,e,b,f,g,h=0;g=this.a;d=lb;switch(d){case lb:a=Math.LOG2E*Math.log(32768)-8;break;default:l(Error("invalid compression method"))}c=a<<4|d;g[h++]=c;switch(d){case lb:switch(this.h){case $.NONE:b=0;break;case $.r:b=1;break;case $.k:b=2;break;default:l(Error("unsupported compression type"))}break;default:l(Error("invalid compression method"))}e=b<<6|0;g[h++]=e|31-(256*c+e)%31;f=jb(this.input);this.A.b=h;g=this.A.j();h=g.length;F&&(g=new Uint8Array(g.buffer),g.length<=
+ h+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,h+4));g[h++]=f>>24&255;g[h++]=f>>16&255;g[h++]=f>>8&255;g[h++]=f&255;return g};function nb(d,a){var c,e,b,f;if(Object.keys)c=Object.keys(a);else for(e in c=[],b=0,a)c[b++]=e;b=0;for(f=c.length;b<f;++b)e=c[b],D(d+"."+e,a[e])};D("Zlib.Inflate",kb);D("Zlib.Inflate.prototype.decompress",kb.prototype.p);nb("Zlib.Inflate.BufferType",{ADAPTIVE:Ba.D,BLOCK:Ba.F});D("Zlib.Deflate",mb);D("Zlib.Deflate.compress",function(d,a){return(new mb(d,a)).j()});D("Zlib.Deflate.prototype.compress",mb.prototype.j);nb("Zlib.Deflate.CompressionType",{NONE:$.NONE,FIXED:$.r,DYNAMIC:$.k});}).call(this); //@ sourceMappingURL=zlib.min.js.map
+
+
+/***/ },
+/* 40 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ // //////////////////////////////////////////////////////////////////////////////
+ // 计时器
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var TimerCounter = function () {
+ function TimerCounter() {
+ _classCallCheck(this, TimerCounter);
+
+ this.timer = 0;
+ this.delay = 1000;
+ this.counter = 0;
+ this.callBackDelay = 1; //回调间隔,单位(秒)
+ this.callBackFun = null; //回调函数
+ this.isStart = false;
+ }
+
+ _createClass(TimerCounter, [{
+ key: "addTimerCallBack",
+ value: function addTimerCallBack(_callBackFun, _callBackDelay) {
+ this.callBackFun = _callBackFun;
+ this.callBackDelay = _callBackDelay;
+ }
+ //开计时
+
+ }, {
+ key: "startTimer",
+ value: function startTimer() {
+ var _position = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
+
+ if (this.isStart) return;
+ this.isStart = true;
+ if (_position && parseInt(_position) > 0) {
+ this.counter = _position;
+ } else {
+ this.counter = 0;
+ }
+ console.log("startTimer", this.counter);
+ this.timerClear();
+ this.timerStart();
+ }
+ //停止
+
+ }, {
+ key: "stopTimer",
+ value: function stopTimer() {
+ console.log("stopTimer", this.counter);
+ this.isStart = false;
+ this.timerClear();
+ }
+ //计数
+
+ }, {
+ key: "updateCounter",
+ value: function updateCounter() {
+ this.counter++;
+ //this.counter++;
+ //console.log("TimerCounter",counter);
+ if (this.callBackFun != null && this.counter % this.callBackDelay == 0) {
+ this.callBackFun();
+ }
+ }
+ }, {
+ key: "timerStart",
+ value: function timerStart() {
+ this.timer = setInterval(this.updateCounter.bind(this), this.delay);
+ }
+ }, {
+ key: "timerClear",
+ value: function timerClear() {
+ clearInterval(this.timer);
+ }
+ }]);
+
+ return TimerCounter;
+ }();
+
+ var _default = TimerCounter;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(TimerCounter, "TimerCounter", "D:/work/McuClient/src/TimerCounter.js");
+
+ __REACT_HOT_LOADER__.register(_default, "default", "D:/work/McuClient/src/TimerCounter.js");
+ }();
+
+ ;
+
+/***/ },
+/* 41 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Ape2 = __webpack_require__(37);
+
+ var _Ape3 = _interopRequireDefault(_Ape2);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //
+ // Copyright (C) 2016-present All Rights Reserved.
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Github Home: https://github.com/AlexWang1987
+ // Author: AlexWang
+ // Date: 2016-08-14 15:55:42
+ // QQ Email: 1669499355@qq.com
+ // Last Modified time: 2016-09-06 16:28:14
+ // Description: LiveClass-ChatApe
+ //
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('ChatApe');
+
+ var ChatApe = function (_Ape) {
+ _inherits(ChatApe, _Ape);
+
+ function ChatApe() {
+ _classCallCheck(this, ChatApe);
+
+ //Ape Models
+ var _this = _possibleConstructorReturn(this, (ChatApe.__proto__ || Object.getPrototypeOf(ChatApe)).call(this, _ApeConsts2.default.CHAT_SESSION_ID, _ApeConsts2.default.CHAT_SESSION_NAME, _ApeConsts2.default.CHAT_SESSION_TAG));
+
+ _this.registerKey(_this._session_id, _this._session_name, _this._session_tag, new ArrayBuffer());
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_TABLE, _ApeConsts2.default.CHAT_OBJ_TABLE_ID, _ApeConsts2.default.CHAT_OBJ_TABLE_NAME, _ApeConsts2.default.CHAT_OBJ_TABLE_TAG, 0, new ArrayBuffer());
+
+ // ape listeners
+ //this.on(pdu.RCPDU_CHAT_SEND_DATA_REQUEST, this.chatMsgIncomingHandler.bind(this));
+ _this.on(_pdus2.default.RCPDU_SEND_CHAT_DATA_REQUEST, _this.chatMsgIncomingHandler.bind(_this));
+ return _this;
+ }
+
+ _createClass(ChatApe, [{
+ key: 'sendChatMsg',
+ value: function sendChatMsg(_messageInfo) {
+ if (this._classInfo === null || _EngineUtils2.default.isEmptyObject(this._classInfo)) {
+ loger.log('不能发送聊天消息.McuClient还未初始化数据!');
+ if (GlobalConfig.getCurrentStatus().code == 0 || GlobalConfig.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return;
+ }
+ return;
+ }
+
+ // to, message
+ loger.log('发送聊天消息.', _messageInfo.to, _messageInfo.message);
+
+ var chatSendPdu = new _pdus2.default['RCChatSendDataRequestPdu']();
+ //chatSendPdu.type = pdu.RCPDU_CHAT_SEND_DATA_REQUEST;
+ chatSendPdu.type = _pdus2.default.RCPDU_SEND_CHAT_DATA_REQUEST;
+ chatSendPdu.initiator = this._classInfo.nodeId; //发起人
+ chatSendPdu.peer = parseInt(_messageInfo.to); //发送给谁,公聊的时候是0,私聊的时候是指定的用户id
+
+ chatSendPdu.userData = this._rCArrayBufferUtil.strToUint8Array("h5" + _messageInfo.message);
+ chatSendPdu.fromName = this._rCArrayBufferUtil.strToUint8Array("h5" + this._classInfo.userName);
+ chatSendPdu.fromRole = this._classInfo.userRole; // classRole已经废弃
+ chatSendPdu.isPublic = true;
+ // if (!(chatSendPdu.isPublic || 0 === chatSendPdu.peer)) {
+ if (!chatSendPdu.isPublic && 0 != chatSendPdu.peer) {
+ //发送给制定的人
+ loger.log('发送私聊消息.');
+ this.send(chatSendPdu);
+ } else {
+ //发送给所有人
+ loger.log('发送公聊消息.');
+ //this.sendUniform(chatSendPdu);
+ this.sendChatUniform(chatSendPdu);
+ }
+ }
+ }, {
+ key: 'chatMsgIncomingHandler',
+ value: function chatMsgIncomingHandler(chatBuffer) {
+ var chatReceivePdu = _pdus2.default['RCChatSendDataRequestPdu'].decode(chatBuffer);
+
+ var chatMsg = {};
+ chatMsg.fromNodeId = chatReceivePdu.initiator;
+ chatMsg.toNodeId = chatReceivePdu.peer;
+ chatMsg.message = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.userData, 2);
+ chatMsg.fromName = this._rCArrayBufferUtil.uint8ArrayToStr(chatReceivePdu.fromName, 2);
+ chatMsg.fromRole = chatReceivePdu.fromRole;
+
+ loger.log('接收聊天消息.', chatMsg);
+
+ this._emit(_MessageTypes2.default.CHAT_RECEIVE, chatMsg);
+ }
+ }]);
+
+ return ChatApe;
+ }(_Ape3.default);
+
+ var _default = ChatApe;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/ChatApe.js');
+
+ __REACT_HOT_LOADER__.register(ChatApe, 'ChatApe', 'D:/work/McuClient/src/apes/ChatApe.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/ChatApe.js');
+ }();
+
+ ;
+
+/***/ },
+/* 42 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Ape2 = __webpack_require__(37);
+
+ var _Ape3 = _interopRequireDefault(_Ape2);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ var _MediaModule = __webpack_require__(43);
+
+ var _MediaModule2 = _interopRequireDefault(_MediaModule);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //视频模块
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('VideoApe');
+
+ var VideoApe = function (_Ape) {
+ _inherits(VideoApe, _Ape);
+
+ function VideoApe() {
+ _classCallCheck(this, VideoApe);
+
+ var _this = _possibleConstructorReturn(this, (VideoApe.__proto__ || Object.getPrototypeOf(VideoApe)).call(this, _ApeConsts2.default.VIDEO_SESSION_ID, _ApeConsts2.default.VIDEO_SESSION_NAME, _ApeConsts2.default.VIDEO_SESSION_TAG));
+
+ _this.mediaModule = new _MediaModule2.default();
+ _this.mediaModule.MEDIA_OBJ_TABLE_ID = _ApeConsts2.default.VIDEO_OBJ_TABLE_ID;
+ _this.mediaModule.mediaChannels = {};
+
+ // Ape Models
+ _this.registerKey(_this._session_id, _this._session_name, _this._session_tag, new ArrayBuffer());
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_TABLE, _ApeConsts2.default.VIDEO_OBJ_TABLE_ID, _ApeConsts2.default.VIDEO_OBJ_TABLE_NAME, _ApeConsts2.default.VIDEO_OBJ_TABLE_TAG, 0, new ArrayBuffer());
+
+ // videoApe 监听视频控制消息,用户之间的消息传递
+ _this.on(_pdus2.default.RCPDU_SEND_VIDEO_DATA_REQUEST, _this.receiveVideoCommandHandler.bind(_this));
+ return _this;
+ }
+ //ape加入成功
+
+
+ _createClass(VideoApe, [{
+ key: 'onJoinChannelHandlerSuccess',
+ value: function onJoinChannelHandlerSuccess() {
+ //这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
+ this.mediaModule.maxMediaChannel = _GlobalConfig2.default.maxVideoChannels;
+ }
+
+ /////////////发送数据操作////////////////////////////////////////////
+ //获取播流地址
+
+ }, {
+ key: 'getPlayVideoPath',
+ value: function getPlayVideoPath(_param) {
+ loger.log('getPlayVideoPath');
+ return this.mediaModule.getMediaPlayPath(_param);
+ }
+
+ //获取推流地址
+
+ }, {
+ key: 'getPublishVideoPath',
+ value: function getPublishVideoPath(_param) {
+ loger.log('getPublishVideoPath');
+ return this.mediaModule.getMediaPublishPath(_param);
+ }
+
+ //获取当前所有频道信息
+
+ }, {
+ key: 'getAllChannelInfo',
+ value: function getAllChannelInfo(_param) {
+ loger.log('getAllChannelInfo');
+ return this.mediaModule.getAllMediaChannelInfo();
+ }
+
+ //推流
+
+ }, {
+ key: 'publishVideo',
+ value: function publishVideo(_param) {
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ if (_param == null || _param.publishUrl == null) {
+ loger.warn('publishVideo,参数错误', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "参数错误" };
+ }
+
+ //根据推流的地址获取对应的频道信息
+ var needPublishChannelInfo = this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
+ if (needPublishChannelInfo == null) {
+ loger.warn('publishVideo,推流数据已经无效', _param);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "推流数据已经无效" };
+ }
+
+ /* //20170302 修改频道占用规则,同一个人可以推多路流,暂停下面的限制
+ //同一个nodeId只允许推一个流,如果已经推了就不能再推
+ if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
+ loger.warn("publishVideo,已经存在一个流,不能再推");
+ return {"code": ApeConsts.RETURN_FAILED, "data": "已经存在一个流,不能再推"};
+ }*/
+
+ //判断当前是否还有空闲的channle
+ var freeChannel = this.mediaModule.getFreeMediaChannel();
+ if (freeChannel == 0) {
+ loger.warn("publishVideo,没有空闲的channel ");
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels };
+ }
+
+ //判断当前的频道是否已经占用
+ if (this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)) {
+ loger.warn(needPublishChannelInfo.channelId, "频道已经被占用");
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "频道已经被占用!", "mediaChannels": this.mediaModule.mediaChannels };
+ }
+
+ var channelInfo = this.mediaModule.getDefaultChannelInfo();
+ channelInfo.owner = _GlobalConfig2.default.nodeId;
+ channelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_OPENING;
+ channelInfo.channelId = needPublishChannelInfo.channelId;
+ channelInfo.streamId = needPublishChannelInfo.streamId; //按规则拼接的流名称
+ channelInfo.mediaType = _ApeConsts2.default.MEDIA_TYPE_VIDEO;
+ this.sendTableUpdateHandler(channelInfo);
+
+ return { "code": _ApeConsts2.default.RETURN_SUCCESS, "data": "推流成功!", "mediaId": needPublishChannelInfo.channelId };
+ }
+
+ //停止推流,
+
+ }, {
+ key: 'stopPublishVideo',
+ value: function stopPublishVideo(_param) {
+ loger.log('stopPublishVideo ->_param', _param);
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ //默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
+ var nodeId = _GlobalConfig2.default.nodeId;
+ if (_param && parseInt(_param.nodeId) > 0) {
+ nodeId = parseInt(_param.nodeId);
+ }
+
+ //默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
+ var releaseChannelId = 0;
+ if (_param && parseInt(_param.mediaId) > 0) {
+ releaseChannelId = parseInt(_param.mediaId);
+ }
+
+ //释放channelId 的占用
+ if (releaseChannelId > 0) {
+ //第一种情况,释放nodeId占用的指定mediaId (channelId)
+ this._releaseChannelForNodeId(nodeId, releaseChannelId);
+ } else {
+ //第二种情况,释放nodeId占用的所有channelId
+ this._releaseNodeIdAllChannel(nodeId);
+ }
+ }
+ //释放nodeId占用的指定的channelId频道
+
+ }, {
+ key: '_releaseChannelForNodeId',
+ value: function _releaseChannelForNodeId(nodeId, channelId) {
+ loger.log(nodeId, "_releaseChannelForNodeId-->channelId", channelId);
+ var channelInfo = this.mediaModule.mediaChannels[channelId];
+ if (channelInfo && channelInfo.status == _ApeConsts2.default.CHANNEL_STATUS_OPENING) {
+ if (channelInfo.fromNodeId == nodeId) {
+
+ var _channelInfo2 = this.mediaModule.getDefaultChannelInfo();
+ _channelInfo2.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ _channelInfo2.channelId = channelId;
+
+ this.sendTableUpdateHandler(_channelInfo2);
+ } else {
+ loger.warn(channelId, "不属于nodeId", nodeId, "不能释放", channelInfo);
+ }
+ } else {
+ loger.warn(nodeId, "要释放的channel不存在或者已经释放-->channelId", channelInfo);
+ }
+ }
+ //释放nodeId占用的所有频道
+
+ }, {
+ key: '_releaseNodeIdAllChannel',
+ value: function _releaseNodeIdAllChannel(nodeId) {
+ loger.log(nodeId, "_releaseNodeIdAllChannel", this.mcu.connected);
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ var openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
+ if (openingChannel == 0) {
+ loger.warn(nodeId, "没有占用channel不需要处理");
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "没有占用channel不需要处理" };
+ }
+
+ var channelInfo = this.mediaModule.getDefaultChannelInfo();
+ channelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ channelInfo.channelId = openingChannel;
+
+ this.sendTableUpdateHandler(channelInfo);
+ //递归检查,800毫秒之后执行
+ setTimeout(function () {
+ loger.warn(nodeId, "递归检查频道是否占用");
+ this._releaseNodeIdAllChannel(nodeId);
+ }.bind(this), 800);
+ }
+ }, {
+ key: 'sendVideoBroadcastMsg',
+ value: function sendVideoBroadcastMsg(_param) {
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ if (this._classInfo === null || _EngineUtils2.default.isEmptyObject(this._classInfo)) {
+ loger.log('不能发送Video消息.McuClient还未初始化数据!');
+ if (_GlobalConfig2.default.getCurrentStatus().code == 0 || _GlobalConfig2.default.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return { "code": 1, "data": "不能发送Video消息.McuClient还未初始化数据" };
+ }
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "不能发送Video消息.McuClient还未初始化数据" };
+ }
+ if (_param == null) {
+ loger.warn('sendVideoCommandMsg失败,参数错误', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "sendVideoCommandMsg失败,参数错误" };
+ }
+ // to, message
+ loger.log('发送Video消息.', _param);
+
+ if (_param.actionType != null && _param.actionType == _ApeConsts2.default.MEDIA_ACTION_OPEN_CAMERA) {
+ //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
+ var freeChannel = this.mediaModule.getFreeMediaChannel();
+ if (freeChannel == 0) {
+ loger.warn('sendVideoCommandMsg,不能再打开更多的设备', _param);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels };
+ }
+ }
+
+ var videoSendPdu = new _pdus2.default['RCVideoSendDataRequestPdu']();
+ videoSendPdu.type = _pdus2.default.RCPDU_SEND_VIDEO_DATA_REQUEST;
+ videoSendPdu.isPublic = true;
+
+ videoSendPdu.fromNodeId = _GlobalConfig2.default.nodeId; //发起人
+ videoSendPdu.toNodeId = parseInt(_param.toNodeId) || 0; //接收者,0就是所有人
+ videoSendPdu.actionType = parseInt(_param.actionType) || _ApeConsts2.default.MEDIA_ACTION_DEFAULT;
+
+ videoSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.data); //开头两个字会乱码
+
+ if (!videoSendPdu.isPublic && 0 != videoSendPdu.toNodeId) {
+ //发送给制定的人
+ loger.log('发送私聊Video消息.');
+ this.send(videoSendPdu);
+ } else {
+ //发送给所有人
+ loger.log('发送公聊Video消息.');
+ this.sendChatUniform(videoSendPdu);
+ }
+ return { "code": _ApeConsts2.default.RETURN_SUCCESS, "data": "" };
+ }
+ }, {
+ key: 'sendTableUpdateHandler',
+ value: function sendTableUpdateHandler(_channelInfo) {
+ loger.log("video===sendTableUpdateHandler ");
+ var updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId); //let updateModelPdu=this.packPdu({},ApeConsts.VIDEO_OBJ_TABLE_ID+2);
+
+ if (updateModelPdu == null) {
+ loger.warn("sendTableUpdateHandler error,updateModelPdu=null");
+ return;
+ }
+
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = _channelInfo.channelId; //tableItemPdu.itemIdx=ApeConsts.VIDEO_OBJ_TABLE_ID+2;
+ tableItemPdu.owner = _channelInfo.owner; //0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
+ tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
+
+ //insert
+ var tableInsertItemPdu = new _pdus2.default['RCRegistryTableUpdateItemPdu']();
+ tableInsertItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_UPDATE_PDU; //
+ tableInsertItemPdu.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.VIDEO_OBJ_TABLE_ID; //
+ updateObjPdu.subType = tableInsertItemPdu.type;
+ updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ loger.log("发送更新VIDEO.itemIdx=" + tableItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+
+ /////收到消息处理//////////////////////////////////////////////////
+
+ // 视频消息处理,内部处理,不需要告诉应用层
+
+ }, {
+ key: 'receiveVideoCommandHandler',
+ value: function receiveVideoCommandHandler(_data) {
+ var videoReceivePdu = _pdus2.default['RCVideoSendDataRequestPdu'].decode(_data);
+ if (videoReceivePdu == null) {
+ loger.warn("视频控制消息处理,收到的消息为null,不做处理");
+ return;
+ }
+ videoReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(videoReceivePdu.data, 2); //开头两个字会乱码
+ loger.log('视频控制消息处理 .', videoReceivePdu);
+ console.log(videoReceivePdu);
+
+ //判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
+ if (videoReceivePdu.toNodeId != 0 && videoReceivePdu.toNodeId != _GlobalConfig2.default.nodeId) {
+ loger.log('视频消息不处理 toNodeId=', videoReceivePdu.toNodeId, "my nodeId=", _GlobalConfig2.default.nodeId);
+ } else {
+ this._emit(_MessageTypes2.default.VIDEO_BROADCAST, videoReceivePdu);
+ }
+ }
+ }, {
+ key: 'tableUpdateHandler',
+ value: function tableUpdateHandler(owner, itemIdx, itemData) {
+ // debugger;
+ var unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
+ loger.log("tableUpdateHandler,channel", itemIdx);
+
+ //****很重要********
+ //如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
+ if (owner == 0) {
+ loger.log("释放占用的频道,channel", itemIdx);
+ unpackChannelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ unpackChannelInfo.streamId = "";
+ }
+
+ this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
+
+ if (unpackChannelInfo && unpackChannelInfo.fromNodeId != _GlobalConfig2.default.nodeId) {
+ var receiveChannelInfo = {};
+ receiveChannelInfo.mediaId = unpackChannelInfo.channelId;
+
+ //消息不是自己同步的,需要处理
+ if (unpackChannelInfo.status == _ApeConsts2.default.CHANNEL_STATUS_OPENING) {
+ //正在推流
+ receiveChannelInfo.m3u8Url = "";
+ receiveChannelInfo.rtmpUrl = "";
+ var m3u8Stream = this.mediaModule.getMediaPlayPath({ "type": "m3u8", "streamId": unpackChannelInfo.streamId });
+ var rtmpStream = this.mediaModule.getMediaPlayPath({ "type": "rtmp", "streamId": unpackChannelInfo.streamId });
+
+ if (m3u8Stream.code == 0) {
+ receiveChannelInfo.m3u8Url = m3u8Stream.playUrl;
+ }
+ if (rtmpStream.code == 0) {
+ receiveChannelInfo.rtmpUrl = rtmpStream.playUrl;
+ }
+ loger.log("VIDEO_PLAY", receiveChannelInfo);
+ //广播播放视频的消息
+ this._emit(_MessageTypes2.default.VIDEO_PLAY, receiveChannelInfo);
+ } else {
+ loger.log("VIDEO_STOP", receiveChannelInfo);
+ //流已经停止
+ this._emit(_MessageTypes2.default.VIDEO_STOP, receiveChannelInfo);
+ }
+ } else {
+ loger.warn("视频消息是自己发送的或者是视频消息无效,不需要处理,消息内容如下:");
+ console.log(unpackChannelInfo);
+ }
+
+ this._emit(_MessageTypes2.default.VIDEO_UPDATE, unpackChannelInfo);
+ }
+
+ ///////数据的封包和解包/////////////////////////////////////////
+
+ }, {
+ key: 'packPdu',
+ value: function packPdu(_param, _itemIdx) {
+ loger.log("packPdu ");
+ //验证坐标点集合数组是否合法
+ if (_param == null || _itemIdx == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+
+ //判断type类型,根据type设置不同的参数
+ var packPduModel = new _pdus2.default['RCVideoChannelInfoPdu']();
+ packPduModel.status = _param.status || _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ packPduModel.channelId = _itemIdx;
+ packPduModel.streamId = _param.streamId || "";
+ packPduModel.siteId = _param.siteId || _GlobalConfig2.default.siteId; //GlobalConfig.siteId;
+ packPduModel.classId = parseInt(_param.classId) || parseInt(_GlobalConfig2.default.classId);
+ packPduModel.userId = _param.userId || "0";
+ packPduModel.mediaType = _param.mediaType || _ApeConsts2.default.MEDIA_TYPE_VIDEO;
+ packPduModel.timestamp = _param.timestamp || _EngineUtils2.default.creatTimestamp();
+ packPduModel.fromNodeId = _GlobalConfig2.default.nodeId;
+ packPduModel.toNodeId = 0;
+ console.log(packPduModel);
+ return packPduModel;
+ }
+ }, {
+ key: 'unPackPdu',
+ value: function unPackPdu(owner, itemIdx, itemData) {
+ loger.log("unPackPdu->owner:", owner, "itemIdx->", itemIdx);
+ if (owner == null || itemIdx == null || itemData == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+ try {
+ var videoChannelInfo = _pdus2.default['RCVideoChannelInfoPdu'].decode(itemData);
+ console.log(videoChannelInfo);
+ return videoChannelInfo;
+ } catch (err) {
+ loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
+ }
+ return null;
+ }
+ }]);
+
+ return VideoApe;
+ }(_Ape3.default);
+
+ var _default = VideoApe;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/VideoApe.js');
+
+ __REACT_HOT_LOADER__.register(VideoApe, 'VideoApe', 'D:/work/McuClient/src/apes/VideoApe.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/VideoApe.js');
+ }();
+
+ ;
+
+/***/ },
+/* 43 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); // //////////////////////////////////////////////////////////////////////////////
+ // VideoApe、AudioApe 共用的方法单独提取处理
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ var loger = _Loger2.default.getLoger('MediaModule');
+
+ var MediaModule = function () {
+ function MediaModule() {
+ _classCallCheck(this, MediaModule);
+
+ this.needPublishMediaChannel = {}; //记录准备推流的频道信息
+ this.mediaChannels = {};
+ this.maxMediaChannel = 0;
+ this.MEDIA_OBJ_TABLE_ID = 0;
+ }
+
+ //获取播流地址
+
+
+ _createClass(MediaModule, [{
+ key: 'getMediaPlayPath',
+ value: function getMediaPlayPath(_param) {
+ loger.log('getMediaPlayPath');
+ if (_param == null || _param.streamId == null) {
+ loger.warn('getMediaPlayPath,参数错误', _param);
+ //this._emit(MessageTypes.MCU_ERROR, MessageTypes.ERR_APE_INTERFACE_PARAM_WRONG);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "" };
+ }
+
+ var path = "";
+ var port = "";
+ if (_param.type == "m3u8") {
+ //M3U8
+ //http://123.56.73.119:6001/hls/h5dev_403074980_0_983041_1487663265/index.m3u8
+ port = _GlobalConfig2.default.RSServerPort == "" || _GlobalConfig2.default.RSServerPort == null ? "" : ":" + _GlobalConfig2.default.RSServerPort;
+ path = "http://" + _GlobalConfig2.default.RSServerIP + port + "/live/" + _param.streamId + "/index.m3u8";
+ } else {
+ port = _GlobalConfig2.default.MSServerPort == "" || _GlobalConfig2.default.MSServerPort == null ? "" : ":" + _GlobalConfig2.default.MSServerPort;
+ path = "rtmp://" + _GlobalConfig2.default.MSServerIP + port + "/live/" + _param.streamId;
+ }
+ return { "code": _ApeConsts2.default.RETURN_SUCCESS, "data": "", "playUrl": path };
+ }
+
+ //获取推流地址
+
+ }, {
+ key: 'getMediaPublishPath',
+ value: function getMediaPublishPath(_param) {
+ loger.log('getMediaPublishPath');
+ //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
+ var freeChannel = this.getFreeMediaChannel();
+ if (freeChannel == 0) {
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaChannels };
+ }
+
+ //默认方式推流
+ var pubType = "live";
+ //flash推流
+ if (_param && _param.type == "flash") {
+ pubType = "flash";
+ }
+
+ //端口,有端口就显示 ":xxx",没有端口就是""
+ var port = _GlobalConfig2.default.MSServerPort == "" || _GlobalConfig2.default.MSServerPort == null ? "" : ":" + _GlobalConfig2.default.MSServerPort;
+ //时间戳
+ var timestamp = _EngineUtils2.default.creatTimestamp();
+
+ var streamId = _GlobalConfig2.default.siteId + "_" + _GlobalConfig2.default.classId + "_" + _GlobalConfig2.default.userId + "_" + freeChannel + "_" + timestamp;
+
+ //生成推流地址和推流数据(同步数据的时候用)
+ var publishUrl = "rtmp://" + _GlobalConfig2.default.MSServerIP + port + "/" + pubType + "/" + streamId;
+
+ this.needPublishMediaChannel[publishUrl] = {
+ "channelId": freeChannel,
+ "publishUrl": publishUrl,
+ "streamId": streamId
+ };
+ return { "code": _ApeConsts2.default.RETURN_SUCCESS,
+ "data": "",
+ "publishUrl": publishUrl
+ };
+ }
+
+ //获取当前空闲的channel,返回值为0代表没有空闲的,否则返回的就是空闲的channelId
+
+ }, {
+ key: 'getFreeMediaChannel',
+ value: function getFreeMediaChannel() {
+ var counter = 0;
+ for (var key in this.mediaChannels) {
+ var item = this.mediaChannels[key];
+ if (item && item.status == _ApeConsts2.default.CHANNEL_STATUS_RELEASED) {
+ return item.channelId;
+ }
+ counter++;
+ }
+ loger.log("getFreeMediaChannel", "maxMediaChannel", this.maxMediaChannel, "counter:", counter);
+ console.log(this.mediaChannels);
+ if (counter < this.maxMediaChannel) {
+ return this.MEDIA_OBJ_TABLE_ID + counter;
+ }
+ return 0; //没有空闲的
+ }
+
+ //获取准备推流的频道信息
+
+ }, {
+ key: 'getNeedPublishMediaChannel',
+ value: function getNeedPublishMediaChannel(_publishUrl) {
+ return this.needPublishMediaChannel[_publishUrl];
+ }
+
+ //获取当前属于nodeId的已经打开的的channel,返回值为0代表没有打开的,否则返回的就是打开的channelId
+
+ }, {
+ key: 'getOpeningMediaChannel',
+ value: function getOpeningMediaChannel(_nodeId) {
+ loger.log("getOpeningMediaChannel", "nodeId", _nodeId, "mediaChannels:", this.mediaChannels);
+ if (_nodeId == null || _nodeId == 0) {
+ return 0;
+ }
+ for (var key in this.mediaChannels) {
+ var item = this.mediaChannels[key];
+ if (item && item.status == _ApeConsts2.default.CHANNEL_STATUS_OPENING && item.fromNodeId == _nodeId) {
+ return item.channelId;
+ }
+ }
+ return 0;
+ }
+
+ //检查频道是否已经被占用
+
+ }, {
+ key: 'checkChannelIsOpening',
+ value: function checkChannelIsOpening(_channelId) {
+ if (_channelId == null) {
+ loger.warn("checkChannelIsOpening error,channel=", _channelId);
+ return true;
+ }
+ var channelInfo = this.mediaChannels[_channelId];
+ if (channelInfo == null || channelInfo.status == _ApeConsts2.default.CHANNEL_STATUS_RELEASED) {
+ return false;
+ }
+ return true;
+ }
+
+ //获取当前所有频道的信息
+
+ }, {
+ key: 'getAllMediaChannelInfo',
+ value: function getAllMediaChannelInfo() {
+ var channels = [];
+ for (var key in this.mediaChannels) {
+ var channel = this.mediaChannels[key];
+ if (channel) {
+ channels.push({ "mediaId": channel.channelId, "status": channel.status, "fromNodeId": channel.fromNodeId });
+ }
+ }
+ if (channels.length < this.maxMediaChannel) {
+ for (var i = channels.length; i < this.maxMediaChannel; i++) {
+ var channelId = this.MEDIA_OBJ_TABLE_ID + i;
+ channels.push({ "mediaId": channelId, "status": _ApeConsts2.default.CHANNEL_STATUS_RELEASED, "fromNodeId": 0 });
+ }
+ }
+ return channels;
+ }
+ //获取默认的频道信息
+
+ }, {
+ key: 'getDefaultChannelInfo',
+ value: function getDefaultChannelInfo() {
+ var channelInfo = {};
+ channelInfo.owner = 0; //这个很重要,释放的时候必须设置为0,占用的时候设置为自己的nodeId
+ channelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ channelInfo.fromNodeId = _GlobalConfig2.default.nodeId;
+ channelInfo.channelId = 0;
+ channelInfo.streamId = "";
+ channelInfo.classId = _GlobalConfig2.default.classId;
+ channelInfo.siteId = _GlobalConfig2.default.siteId;
+ channelInfo.toNodeId = 0;
+ channelInfo.userId = _GlobalConfig2.default.userId;
+ channelInfo.mediaType = _ApeConsts2.default.MEDIA_TYPE_DEFAULT;
+ return channelInfo;
+ }
+ }]);
+
+ return MediaModule;
+ }();
+
+ var _default = MediaModule;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/MediaModule.js');
+
+ __REACT_HOT_LOADER__.register(MediaModule, 'MediaModule', 'D:/work/McuClient/src/apes/MediaModule.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/MediaModule.js');
+ }();
+
+ ;
+
+/***/ },
+/* 44 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Ape2 = __webpack_require__(37);
+
+ var _Ape3 = _interopRequireDefault(_Ape2);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ var _MediaModule = __webpack_require__(43);
+
+ var _MediaModule2 = _interopRequireDefault(_MediaModule);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //音频模块
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('AudioApe');
+
+ var AudioApe = function (_Ape) {
+ _inherits(AudioApe, _Ape);
+
+ function AudioApe() {
+ _classCallCheck(this, AudioApe);
+
+ var _this = _possibleConstructorReturn(this, (AudioApe.__proto__ || Object.getPrototypeOf(AudioApe)).call(this, _ApeConsts2.default.AUDIO_SESSION_ID, _ApeConsts2.default.AUDIO_SESSION_NAME, _ApeConsts2.default.AUDIO_SESSION_TAG));
+
+ _this.mediaModule = new _MediaModule2.default();
+ _this.mediaModule.MEDIA_OBJ_TABLE_ID = _ApeConsts2.default.AUDIO_OBJ_TABLE_ID;
+ _this.mediaModule.mediaChannels = {};
+ // Ape Models
+ _this.registerKey(_this._session_id, _this._session_name, _this._session_tag, new ArrayBuffer());
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_TABLE, _ApeConsts2.default.AUDIO_OBJ_TABLE_ID, _ApeConsts2.default.AUDIO_OBJ_TABLE_NAME, _ApeConsts2.default.AUDIO_OBJ_TABLE_TAG, 0, new ArrayBuffer());
+
+ // 广播消息,用户之间的消息传递
+ _this.on(_pdus2.default.RCPDU_SEND_AUDIO_DATA_REQUEST, _this.receiveAudiooCommandHandler.bind(_this));
+ return _this;
+ }
+ //ape加入成功
+
+
+ _createClass(AudioApe, [{
+ key: 'onJoinChannelHandlerSuccess',
+ value: function onJoinChannelHandlerSuccess() {
+ //这个设置很重要,因为只有Sass流程完成之后,APE才能取得GlobalConfig中的数据
+ this.mediaModule.maxMediaChannel = _GlobalConfig2.default.maxAudioChannels;
+ }
+
+ /////////////发送数据操作////////////////////////////////////////////
+ //获取播流地址
+
+ }, {
+ key: 'getAudioPlayPath',
+ value: function getAudioPlayPath(_param) {
+ loger.log('getAudioPlayPath');
+ return this.mediaModule.getMediaPlayPath(_param);
+ }
+
+ //获取推流地址
+
+ }, {
+ key: 'getAudioPublishPath',
+ value: function getAudioPublishPath(_param) {
+ loger.log('getAudioPublishPath');
+ return this.mediaModule.getMediaPublishPath(_param);
+ }
+
+ //获取当前所有频道信息
+
+ }, {
+ key: 'getAllChannelInfo',
+ value: function getAllChannelInfo(_param) {
+ loger.log('getAllChannelInfo');
+ return this.mediaModule.getAllMediaChannelInfo();
+ }
+
+ //推流
+
+ }, {
+ key: 'publishAudio',
+ value: function publishAudio(_param) {
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ if (_param == null || _param.publishUrl == null) {
+ loger.warn('publishAudio,参数错误', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "参数错误" };
+ }
+
+ //根据推流的地址获取对应的频道信息
+ var needPublishChannelInfo = this.mediaModule.getNeedPublishMediaChannel(_param.publishUrl);
+ if (needPublishChannelInfo == null) {
+ loger.warn('publishVideo,推流数据已经无效', _param);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "推流数据已经无效" };
+ }
+
+ /* //20170302 修改频道占用规则,同一个人可以推多路流,暂停下面的限制
+ //同一个nodeId只允许推一个流,如果已经推了就不能再推
+ if(this.mediaModule.getOpeningMediaChannel(GlobalConfig.nodeId)!=0){
+ loger.warn("publishAudio,已经存在一个流,不能再推");
+ return {"code": ApeConsts.RETURN_FAILED, "data": "已经存在一个流,不能再推","mediaChannels":this.mediaModule.mediaChannels};
+ }*/
+
+ //判断当前是否还有空闲的channle
+ var freeChannel = this.mediaModule.getFreeMediaChannel();
+ if (freeChannel == 0) {
+ loger.warn("publishAudio,没有空闲的channel ");
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels };
+ }
+
+ //判断当前的频道是否已经占用
+ if (this.mediaModule.checkChannelIsOpening(needPublishChannelInfo.channelId)) {
+ loger.warn(needPublishChannelInfo.channelId, "频道已经被占用");
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "频道已经被占用!" };
+ }
+
+ var channelInfo = this.mediaModule.getDefaultChannelInfo();
+ channelInfo.owner = _GlobalConfig2.default.nodeId;
+ channelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_OPENING;
+ channelInfo.channelId = needPublishChannelInfo.channelId; //freeChannel
+ channelInfo.streamId = needPublishChannelInfo.streamId; //按规则拼接的流名称
+ channelInfo.timestamp = needPublishChannelInfo.timestamp; //EngineUtils.creatTimestamp();
+ channelInfo.mediaType = _ApeConsts2.default.MEDIA_TYPE_AUDIO;
+ this.sendTableUpdateHandler(channelInfo);
+ return { "code": _ApeConsts2.default.RETURN_SUCCESS, "data": "推流成功!", "mediaId": needPublishChannelInfo.channelId };
+ }
+
+ //停止推流,
+
+ }, {
+ key: 'stopPublishAudio',
+ value: function stopPublishAudio(_param) {
+ loger.log('stopPublishAudio ->_param', _param);
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ //默认为自己的nodeId,_param如果为空,那么默认就是当前自己的nodeId,否则用_param
+ var nodeId = _GlobalConfig2.default.nodeId;
+ if (_param && parseInt(_param.nodeId) > 0) {
+ nodeId = parseInt(_param.nodeId);
+ }
+
+ //默认为0,如果releaseChannelId 存在就释放releaseChannelId通道
+ var releaseChannelId = 0;
+ if (_param && parseInt(_param.mediaId) > 0) {
+ releaseChannelId = parseInt(_param.mediaId);
+ }
+
+ //释放channelId 的占用
+ if (releaseChannelId > 0) {
+ //第一种情况,释放nodeId占用的指定mediaId (channelId)
+ this._releaseChannelForNodeId(nodeId, releaseChannelId);
+ } else {
+ //第二种情况,释放nodeId占用的所有channelId
+ this._releaseNodeIdAllChannel(nodeId);
+ }
+ }
+
+ //释放nodeId占用的指定的channelId频道
+
+ }, {
+ key: '_releaseChannelForNodeId',
+ value: function _releaseChannelForNodeId(nodeId, channelId) {
+ loger.log(nodeId, "_releaseChannelForNodeId-->channelId", channelId);
+ var channelInfo = this.mediaModule.mediaChannels[channelId];
+ if (channelInfo && channelInfo.status == _ApeConsts2.default.CHANNEL_STATUS_OPENING) {
+ if (channelInfo.fromNodeId == nodeId) {
+
+ var _channelInfo2 = this.mediaModule.getDefaultChannelInfo();
+ _channelInfo2.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ _channelInfo2.channelId = channelId;
+
+ this.sendTableUpdateHandler(_channelInfo2);
+ } else {
+ loger.warn(channelId, "不属于nodeId", nodeId, "不能释放", channelInfo);
+ }
+ } else {
+ loger.warn(nodeId, "要释放的channel不存在或者已经释放-->channelId", channelInfo);
+ }
+ }
+ //释放nodeId占用的所有频道
+
+ }, {
+ key: '_releaseNodeIdAllChannel',
+ value: function _releaseNodeIdAllChannel(nodeId) {
+ loger.log(nodeId, "_releaseNodeIdAllChannel", this.mcu.connected);
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+
+ var openingChannel = this.mediaModule.getOpeningMediaChannel(nodeId);
+ if (openingChannel == 0) {
+ loger.warn(nodeId, "没有占用channel不需要处理");
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "没有占用channel不需要处理" };
+ }
+
+ var channelInfo = this.mediaModule.getDefaultChannelInfo();
+ channelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ channelInfo.channelId = openingChannel;
+
+ this.sendTableUpdateHandler(channelInfo);
+ //递归检查,800毫秒之后执行
+ setTimeout(function () {
+ loger.warn(nodeId, "递归检查频道是否占用");
+ this._releaseNodeIdAllChannel(nodeId);
+ }.bind(this), 800);
+ }
+ }, {
+ key: 'sendAudioBroadcastMsg',
+ value: function sendAudioBroadcastMsg(_param) {
+ loger.log('sendAudioBroadcastMsg', _param);
+ if (!this.mcu.connected) {
+ loger.warn(_GlobalConfig2.default.getCurrentStatus());
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "已经断开连接" };
+ }
+ if (this._classInfo === null || _EngineUtils2.default.isEmptyObject(this._classInfo)) {
+ loger.log('sendAudioBroadcastMsg.McuClient还未初始化数据!');
+ if (_GlobalConfig2.default.getCurrentStatus().code == 0 || _GlobalConfig2.default.getCurrentStatus().code == 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_SEND_FAILED_NO_JOIN);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据" };
+ }
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "sendAudioBroadcastMsg.McuClient还未初始化数据" };
+ }
+ if (_param == null) {
+ loger.warn('sendAudioBroadcastMsg,参数错误', _param);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "sendAudioBroadcastMsg,参数错误" };
+ }
+ // to, message
+ loger.log('发送Audio消息.', _param);
+
+ if (_param.actionType != null && _param.actionType == _ApeConsts2.default.MEDIA_ACTION_OPEN_CAMERA) {
+ //判断当前开启的视频数量是否已经是最大值,如果已经是最大值,不能再开启
+ var freeChannel = this.mediaModule.getFreeMediaChannel();
+ if (freeChannel == 0) {
+ loger.warn('sendAudioBroadcastMsg,不能再打开更多的设备', _param);
+ return { "code": _ApeConsts2.default.RETURN_FAILED, "data": "不能再打开更多的设备", "mediaChannels": this.mediaModule.mediaChannels };
+ }
+ }
+
+ var audioSendPdu = new _pdus2.default['RCAudioSendDataRequestPdu']();
+ audioSendPdu.type = _pdus2.default.RCPDU_SEND_AUDIO_DATA_REQUEST;
+ audioSendPdu.isPublic = true;
+
+ audioSendPdu.fromNodeId = _GlobalConfig2.default.nodeId; //发起人
+ audioSendPdu.toNodeId = parseInt(_param.toNodeId) || 0; //接收者,0就是所有人
+ audioSendPdu.actionType = parseInt(_param.actionType) || _ApeConsts2.default.MEDIA_ACTION_DEFAULT;
+
+ audioSendPdu.data = this._rCArrayBufferUtil.strToUint8Array("h5" + _param.data); //开头两个字会乱码
+
+ if (!audioSendPdu.isPublic && 0 != audioSendPdu.toNodeId) {
+ //发送给制定的人
+ loger.log('发送私聊消息.');
+ this.send(audioSendPdu);
+ } else {
+ //发送给所有人
+ loger.log('发送公聊消息.');
+ this.sendChatUniform(audioSendPdu);
+ }
+ return { "code": _ApeConsts2.default.RETURN_SUCCESS, "data": "" };
+ }
+ }, {
+ key: 'sendTableUpdateHandler',
+ value: function sendTableUpdateHandler(_channelInfo) {
+ loger.log("audio,sendTableUpdateHandler ");
+ var updateModelPdu = this.packPdu(_channelInfo, _channelInfo.channelId);
+ if (updateModelPdu == null) {
+ loger.warn("sendTableUpdateHandler error,updateModelPdu=null");
+ return;
+ }
+
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = _channelInfo.channelId;
+ tableItemPdu.owner = _channelInfo.owner; //0收到flash的是这个值,MCU做了了用户掉线处理,30秒之后会清理owner为0
+ tableItemPdu.itemData = updateModelPdu.toArrayBuffer();
+
+ //insert
+ var tableInsertItemPdu = new _pdus2.default['RCRegistryTableUpdateItemPdu']();
+ tableInsertItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_UPDATE_PDU;
+ tableInsertItemPdu.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.AUDIO_OBJ_TABLE_ID; //
+ updateObjPdu.subType = tableInsertItemPdu.type;
+ updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ loger.log("发送更新AUDIO.itemIdx=" + tableItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+
+ /////收到消息处理//////////////////////////////////////////////////
+
+ // 消息处理,内部处理,不需要告诉应用层
+
+ }, {
+ key: 'receiveAudiooCommandHandler',
+ value: function receiveAudiooCommandHandler(_data) {
+ var audioReceivePdu = _pdus2.default['RCAudioSendDataRequestPdu'].decode(_data);
+ if (audioReceivePdu == null) {
+ loger.warn("音频消息处理,收到的消息为null,不做处理");
+ return;
+ }
+ audioReceivePdu.data = this._rCArrayBufferUtil.uint8ArrayToStr(audioReceivePdu.data, 2); //开头两个字会乱码
+ loger.log('音频消息处理 receiveAudiooCommandHandler.', audioReceivePdu);
+
+ //判断接收者的id,如果不是0,并且也不是自己的nodeId,那么消息不做处理
+ if (audioReceivePdu.toNodeId != 0 && audioReceivePdu.toNodeId != _GlobalConfig2.default.nodeId) {
+ loger.log('音频消息不处理 toNodeId=', audioReceivePdu.toNodeId, "my nodeId=", _GlobalConfig2.default.nodeId);
+ } else {
+ this._emit(_MessageTypes2.default.AUDIO_BROADCAST, audioReceivePdu);
+ }
+ }
+ }, {
+ key: 'tableUpdateHandler',
+ value: function tableUpdateHandler(owner, itemIdx, itemData) {
+ var unpackChannelInfo = this.unPackPdu(owner, itemIdx, itemData);
+ loger.log("tableUpdateHandler,channel", itemIdx);
+
+ //****很重要********
+ //如果owner的值为0,代表的是这个歌频道已经被释放了(mcu服务端对于占用channel的掉线用户,就是把owner设置为0)
+ if (owner == 0) {
+ loger.log("释放占用的频道,channel", itemIdx);
+ unpackChannelInfo.status = _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ unpackChannelInfo.streamId = "";
+ }
+
+ this.mediaModule.mediaChannels[itemIdx] = unpackChannelInfo;
+
+ if (unpackChannelInfo && unpackChannelInfo.fromNodeId != _GlobalConfig2.default.nodeId) {
+ var receiveChannelInfo = {};
+ receiveChannelInfo.mediaId = unpackChannelInfo.channelId;
+
+ //消息不是自己同步的,需要处理
+ if (unpackChannelInfo.status == _ApeConsts2.default.CHANNEL_STATUS_OPENING) {
+ //正在推流
+ receiveChannelInfo.m3u8Url = "";
+ receiveChannelInfo.rtmpUrl = "";
+ var m3u8Stream = this.mediaModule.getMediaPlayPath({ "type": "m3u8", "streamId": unpackChannelInfo.streamId });
+ var rtmpStream = this.mediaModule.getMediaPlayPath({ "type": "rtmp", "streamId": unpackChannelInfo.streamId });
+
+ if (m3u8Stream.code == 0) {
+ receiveChannelInfo.m3u8Url = m3u8Stream.playUrl;
+ }
+ if (rtmpStream.code == 0) {
+ receiveChannelInfo.rtmpUrl = rtmpStream.playUrl;
+ }
+ loger.log("AUDIO_PLAY", receiveChannelInfo);
+ //广播播放视频的消息
+ this._emit(_MessageTypes2.default.AUDIO_PLAY, receiveChannelInfo);
+ } else {
+ loger.log("AUDIO_STOP", receiveChannelInfo);
+ //流已经停止
+ this._emit(_MessageTypes2.default.AUDIO_STOP, receiveChannelInfo);
+ }
+ } else {
+ loger.warn("消息是自己发送的或者是消息无效,不需要处理,消息内容如下:");
+ console.log(unpackChannelInfo);
+ }
+ this._emit(_MessageTypes2.default.AUDIO_UPDATE, unpackChannelInfo);
+ }
+
+ ///////数据的封包和解包/////////////////////////////////////////
+
+ }, {
+ key: 'packPdu',
+ value: function packPdu(_param, _itemIdx) {
+ loger.log("packPdu ");
+ //验证坐标点集合数组是否合法
+ if (_param == null || _itemIdx == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+
+ //判断type类型,根据type设置不同的参数
+ var packPduModel = new _pdus2.default['RCAudioChannelInfoPdu']();
+ packPduModel.status = _param.status || _ApeConsts2.default.CHANNEL_STATUS_RELEASED;
+ packPduModel.channelId = _itemIdx;
+ packPduModel.streamId = _param.streamId || "";
+ packPduModel.siteId = _param.siteId || _GlobalConfig2.default.siteId; //GlobalConfig.siteId;
+ packPduModel.classId = parseInt(_param.classId) || parseInt(_GlobalConfig2.default.classId);
+ packPduModel.userId = _param.userId || "0";
+ packPduModel.mediaType = _param.mediaType || _ApeConsts2.default.MEDIA_TYPE_AUDIO;
+ packPduModel.timestamp = _param.timestamp || _EngineUtils2.default.creatTimestamp();
+ packPduModel.fromNodeId = _GlobalConfig2.default.nodeId;
+ packPduModel.toNodeId = 0;
+ console.log("packPdu", packPduModel);
+ return packPduModel;
+ }
+ }, {
+ key: 'unPackPdu',
+ value: function unPackPdu(owner, itemIdx, itemData) {
+ loger.log("unPackPdu ");
+ if (owner == null || itemIdx == null || itemData == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+ try {
+ var packChannelInfo = _pdus2.default['RCAudioChannelInfoPdu'].decode(itemData);
+ console.log(packChannelInfo);
+ return packChannelInfo;
+ } catch (err) {
+ loger.log("unPackPdu error,itemIdx=" + itemIdx + " err:" + err.message);
+ }
+ return null;
+ }
+ }]);
+
+ return AudioApe;
+ }(_Ape3.default);
+
+ var _default = AudioApe;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/AudioApe.js');
+
+ __REACT_HOT_LOADER__.register(AudioApe, 'AudioApe', 'D:/work/McuClient/src/apes/AudioApe.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/AudioApe.js');
+ }();
+
+ ;
+
+/***/ },
+/* 45 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Ape2 = __webpack_require__(37);
+
+ var _Ape3 = _interopRequireDefault(_Ape2);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //
+ // Copyright (C) 2016-present All Rights Reserved.
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Github Home: https://github.com/AlexWang1987
+ // Author: AlexWang
+ // Date: 2016-08-26 17:30:43
+ // QQ Email: 1669499355@qq.com
+ // Last Modified time: 2016-09-21 14:12:25
+ // Description: LiveClass-DocApe
+ //
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('DocApe');
+ var itemIdx = 0; //table插入新数据的计数id,目前用时间戳
+
+ var DocApe = function (_Ape) {
+ _inherits(DocApe, _Ape);
+
+ function DocApe() {
+ _classCallCheck(this, DocApe);
+
+ var _this = _possibleConstructorReturn(this, (DocApe.__proto__ || Object.getPrototypeOf(DocApe)).call(this, _ApeConsts2.default.DOCSHARING_SESSION_ID, _ApeConsts2.default.DOCSHARING_SESSION_NAME, _ApeConsts2.default.DOCSHARING_SESSION_TAG));
+
+ _this.docList = {}; //记录文档的数组this.docList[itemIdx]=itemIdx的数据
+ //this.activeDocItemIdx =0;//当前激活的文档itemIdx
+ //this.activeDocCurPage=1;//当前激活的文档的当前页
+ // 延迟
+ _this._apeDelayed = false;
+
+ // Ape Models
+ _this.registerKey(_this._session_id, _this._session_name, _this._session_tag, new ArrayBuffer());
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_TABLE, _ApeConsts2.default.DOCSHARING_OBJ_TABLE_ID, _ApeConsts2.default.DOCSHARING_OBJ_TABLE_NAME, _ApeConsts2.default.DOCSHARING_OBJ_TABLE_TAG, 0, new ArrayBuffer());
+ //this.registerObj(pdu.RCPDU_REG_REGISTER_TABLE, ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5, ApeConsts.DOCSHARING_OBJ_TABLE_NAME_H5, ApeConsts.DOCSHARING_OBJ_TABLE_TAG_H5, 0, new ArrayBuffer);
+ return _this;
+ }
+
+ /////////////发送数据操作//////////////////////////////////////////////////////
+ //上传文档
+
+
+ _createClass(DocApe, [{
+ key: 'documentUpload',
+ value: function documentUpload(paramInfo) {
+ if (paramInfo == null || _EngineUtils2.default.isEmptyObject(paramInfo)) {
+ loger.log('documentUpload失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ //判断文档是否已经存在,每个文档都有唯一的docId,如果已经同步的文档中存在相同的docId就不需要再同步
+ if (this.checkDocId(paramInfo.docId)) {
+ //文档已经存在相同的docId,不需要同步上传
+ loger.warn('documentUpload 文档的docId不无效或已经存在相同的docId,不需要上传');
+ return;
+ }
+
+ itemIdx = _EngineUtils2.default.creatSoleNumberFromTimestamp();
+ var docDataModelPdu = this.packPdu(paramInfo, itemIdx);
+ if (docDataModelPdu == null) {
+ loger.log('documentUpload失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ //console.log(docDataModelPdu);
+
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = itemIdx; //直接用时间戳作为id
+ tableItemPdu.registerObjId = _ApeConsts2.default.DOCSHARING_OBJ_TABLE_ID; // tableItemPdu.registerObjId=ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5;
+ tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
+ tableItemPdu.itemData = docDataModelPdu.toArrayBuffer();
+
+ //insert
+ var tableInsertItemPdu = new _pdus2.default['RCRegistryTableInsertItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
+ //repeated RCRegistryTableItemPdu items = 2;
+ tableInsertItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_INSERT_PDU; //
+ tableInsertItemPdu.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.DOCSHARING_OBJ_TABLE_ID; // updateObjPdu.objId = ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5;
+ updateObjPdu.subType = tableInsertItemPdu.type;
+ updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ loger.log("文档upload tableItemPdu.itemIdx=" + tableItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+ }, {
+ key: 'updaterDoc',
+ value: function updaterDoc(_docDataModel, _itemIdx) {
+ loger.log("文档===updaterDoc ", _itemIdx);
+ //验证坐标点集合数组是否合法
+ if (_docDataModel == null || _itemIdx == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+ loger.log("文档===updaterDoc ", _docDataModel);
+
+ var docDataModelPdu = this.packPdu(_docDataModel, _itemIdx);
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = _itemIdx; //直接用时间戳作为id
+ //tableItemPdu.registerObjId=ApeConsts.DOCSHARING_OBJ_TABLE_ID;// tableItemPdu.registerObjId=ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5;
+ tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
+ tableItemPdu.itemData = docDataModelPdu.toArrayBuffer();
+
+ //insert
+ var tableInsertItemPdu = new _pdus2.default['RCRegistryTableUpdateItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
+ //repeated RCRegistryTableItemPdu items = 2;
+ tableInsertItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_UPDATE_PDU; //
+ tableInsertItemPdu.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.DOCSHARING_OBJ_TABLE_ID; // updateObjPdu.objId = ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5;
+ updateObjPdu.subType = tableInsertItemPdu.type;
+ updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ loger.log("发送更新文档.itemIdx=" + tableItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+ //获取文档的图片完整地址
+
+ }, {
+ key: 'getDocImageFullPath',
+ value: function getDocImageFullPath(_param) {
+ if (_param == null || _param.relativeUrl == null || _param.relativeUrl == "") {
+ loger.warn('获取文档完整地址,传递的参数不对.', _param);
+ return [];
+ }
+
+ var port = _GlobalConfig2.default.DOCServerPort == "" || _GlobalConfig2.default.DOCServerPort == null ? "" : ":" + _GlobalConfig2.default.DOCServerPort;
+ var fullPath = _GlobalConfig2.default.DOCServerIP + port + _param.relativeUrl;
+ if (fullPath && fullPath.indexOf("http://") < 0) {
+ fullPath = "http://" + fullPath;
+ }
+
+ var fileType = "jpg";
+ switch (_param.type) {
+ case "jpg":
+ fileType = "jpg";
+ fullPath = this.replacePathType(fullPath) + ".jpg";
+ break;
+ case "png":
+ fileType = "png";
+ fullPath = this.replacePathType(fullPath) + ".png";
+ break;
+ default:
+ //不做处理,直接返回拼接的地址
+ break;
+ }
+
+ if (_param.pageNum && parseInt(_param.pageNum) > 1) {
+ //如果是多页的,需要返回序列
+ var lastIndex = fullPath.lastIndexOf("/");
+ if (lastIndex > 0) {
+ var newPath = fullPath.substr(0, lastIndex);
+ var pathArr = [];
+ //页数从1开始
+ for (var i = 1; i <= _param.pageNum; i++) {
+ pathArr.push(newPath + "/" + i + "." + fileType);
+ }
+ return pathArr;
+ } else {
+ return [fullPath];
+ }
+ } else {
+ return [fullPath];
+ }
+ }
+
+ //获取文档的pdf完整地址
+
+ }, {
+ key: 'getDocPDFFullPath',
+ value: function getDocPDFFullPath(_param) {
+ if (_param == null || _param.relativeUrl == null || _param.relativeUrl == "") {
+ loger.warn('获取文档完整地址,传递的参数不对.', _param);
+ return [];
+ }
+ var port = _GlobalConfig2.default.DOCServerPort == "" || _GlobalConfig2.default.DOCServerPort == null ? "" : ":" + _GlobalConfig2.default.DOCServerPort;
+ var fullPath = _GlobalConfig2.default.DOCServerIP + port + _param.relativeUrl;
+ if (fullPath && fullPath.indexOf("http://") < 0) {
+ fullPath = "http://" + fullPath;
+ }
+ fullPath = this.replacePathType(fullPath) + ".pdf";
+ return [fullPath];
+ }
+
+ // 去除文件的后缀格式名称
+
+ }, {
+ key: 'replacePathType',
+ value: function replacePathType(_path) {
+ var path = _path;
+ path = path.replace(/.jpg/g, "");
+ path = path.replace(/.png/g, "");
+ path = path.replace(/.swf/g, "");
+ path = path.replace(/.pdf/g, "");
+ return path;
+ }
+
+ //切换文档
+
+ }, {
+ key: 'documentSwitchDoc',
+ value: function documentSwitchDoc(paramInfo) {
+ loger.log('切换文档,documentSwitchDoc');
+ console.log(paramInfo);
+ if (paramInfo == null || paramInfo.itemIdx == null) {
+ loger.warn('documentSwitch失败,参数错误', paramInfo);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+
+ if (paramInfo.itemIdx == _GlobalConfig2.default.activeDocId && _GlobalConfig2.default.activeDocId != 0) {
+ loger.warn('文档已经显示', paramInfo.itemIdx, _GlobalConfig2.default.activeDocId);
+ return;
+ }
+
+ //更新切换之前的文档的数据,要显示当前切换的文档,上一个文档需要隐藏
+ var oldDocModel = void 0;
+ if (_GlobalConfig2.default.activeDocId != 0) {
+ oldDocModel = this.docList[_GlobalConfig2.default.activeDocId];
+ if (oldDocModel) {
+ oldDocModel.action = _ApeConsts2.default.DOC_ACTION_NORMAL;
+ oldDocModel.visible = false; //设置为不可见
+ }
+ }
+
+ //获取已经存在的数据
+ var docDataModel = this.docList[paramInfo.itemIdx];
+ if (docDataModel == null) {
+ loger.warn('documentSwitch失败,文档不存在', paramInfo);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+
+ //更新当前选择的文档数据的字段
+ docDataModel.action = _ApeConsts2.default.DOC_ACTION_SWITCH_DOC;
+ docDataModel.visible = paramInfo.visible || false; //默认是false
+
+ //loger.log('切换文档,当前文档和上一个显示的文档都需要更新状态');
+ console.log({ "oldDoc": oldDocModel, "nowDoc": docDataModel });
+ //更新当前选择的文档
+ this.updaterDoc(docDataModel, docDataModel.itemIdx);
+
+ //更新上一个文档 隐藏
+ if (oldDocModel) {
+ this.updaterDoc(oldDocModel, oldDocModel.itemIdx);
+ }
+ }
+
+ //文档翻页
+
+ }, {
+ key: 'documentSwitchPage',
+ value: function documentSwitchPage(paramInfo) {
+ loger.log('文档翻页,documentSwitchPage');
+ console.log(paramInfo);
+ //console.log(this.docList);
+ //获取已经存在的数据
+ var docDataModel = this.docList[paramInfo.itemIdx];
+ //console.log(docDataModelPdu);
+ //console.log(docDataModel);
+ if (docDataModel == null) {
+ loger.log('documentCommand失败,文档不存在', paramInfo);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ //更新数据的字段
+ docDataModel.action = _ApeConsts2.default.DOC_ACTION_SWITCH_PAGE;
+ docDataModel.curPageNo = parseInt(paramInfo.curPageNo) || 1;
+ if (docDataModel.curPageNo < 1) {
+ docDataModel.curPageNo = 1; //默认值最小是1
+ }
+ this.updaterDoc(docDataModel, docDataModel.itemIdx);
+ }
+
+ //缩放/滚动
+
+ }, {
+ key: 'documentCommand',
+ value: function documentCommand(paramInfo) {
+ //console.log(this.docList);
+ //获取已经存在的数据
+ var docDataModel = this.docList[paramInfo.itemIdx];
+ //console.log(docDataModelPdu);
+ //console.log(docDataModel);
+ if (docDataModel == null) {
+ loger.log('documentCommand失败,文档不存在', paramInfo);
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ //更新数据的字段
+ docDataModel.action = _ApeConsts2.default.DOC_ACTION_COMMAND;
+ //docDataModel.scale=parseInt(paramInfo.scale)||100;//默认是100(百分比)
+ this.updaterDoc(docDataModel, docDataModel.itemIdx);
+ }
+
+ //删除所有文档
+
+ }, {
+ key: 'documentDeleteAll',
+ value: function documentDeleteAll(_param) {
+ for (var key in this.docList) {
+ //console.log("key:"+key);
+ loger.log("删除文档数据,itemIdx:" + key);
+ this.documentDelete({ "itemIdx": key });
+ }
+ }
+
+ //删除文档
+
+ }, {
+ key: 'documentDelete',
+ value: function documentDelete(paramInfo) {
+ //{"itemIdx":itemIdx}
+ var tableDeleteItemPdu = new _pdus2.default['RCRegistryTableDeleteItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_DELETE_PDU];
+ // repeated uint32 item_idx = 2;
+ tableDeleteItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_DELETE_PDU; //
+ tableDeleteItemPdu.itemIdx = parseInt(paramInfo.itemIdx); //这里需要设置要删除的数据的itemIdx,每条数据的这个id都不一样
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.DOCSHARING_OBJ_TABLE_ID; // updateObjPdu.objId = ApeConsts.DOCSHARING_OBJ_TABLE_ID_H5;
+ updateObjPdu.subType = tableDeleteItemPdu.type;
+ updateObjPdu.userData = tableDeleteItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ loger.log("文档发送删除数据=============" + tableDeleteItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+
+ /////收到消息处理/////////////////////////////////////////////////////////////////////////////////
+
+ }, {
+ key: 'tableInsertHandler',
+ value: function tableInsertHandler(owner, itemIdx, itemData) {
+ //this.tableUpdateHandler(owner, tableId, itemData);
+ //loger.log('tableInsertHandler---',itemData);
+ var itemDataInfo = this.unPackPdu(owner, itemIdx, itemData);
+ this.docList[itemIdx] = itemDataInfo;
+
+ if (itemDataInfo.visible == "true" || itemDataInfo.visible == true) {
+ _GlobalConfig2.default.activeDocId = itemDataInfo.itemIdx; //当前激活的文档ID
+ _GlobalConfig2.default.activeDocCurPage = itemDataInfo.curPageNo; //当前激活的文档的当前页
+ loger.log('tableInsertHandler 设置当前激活的文档id');
+ }
+
+ loger.log('tableInsertHandler 发送给客户端');
+ console.log(itemDataInfo);
+ this._emit(_MessageTypes2.default.DOC_UPDATE, itemDataInfo); //用添加和更新都统一DOC_UPDATE
+ }
+ }, {
+ key: 'tableDeleteHandler',
+ value: function tableDeleteHandler(object_id, tableDeleteData) {
+ /*const re={};
+ re.type=ApeConsts.DOCUMENT_DEL;
+ this._emit(MessageTypes.DOC_DELETE, re);*/
+
+ loger.log('tableDeleteHandler', object_id, tableDeleteData); //["tableDeleteHandler",1179649,{"type":231,"itemIdx":[1486301768]}]
+ if (tableDeleteData && tableDeleteData.itemIdx) {
+ var len = tableDeleteData.itemIdx.length;
+ var itemIdxs = tableDeleteData.itemIdx;
+ for (var i = 0; i < len; i++) {
+ if (this.docList[itemIdxs[i]]) {
+ loger.log("删除文档数据:", itemIdxs[i]);
+ this._emit(_MessageTypes2.default.DOC_DELETE, itemIdxs[i]);
+ var itemDataInfo = this.docList[itemIdxs[i]];
+ if (itemDataInfo && (itemDataInfo.visible == "true" || itemDataInfo.visible == true)) {
+ _GlobalConfig2.default.activeDocId = 0; //当前激活的文档ID
+ _GlobalConfig2.default.activeDocCurPage = 1; //当前激活的文档的当前页
+ loger.log('tableDeleteHandler 设置当前激活的文档id');
+ }
+ delete this.docList[itemIdxs[i]];
+ }
+ }
+ }
+ }
+ }, {
+ key: 'tableUpdateHandler',
+ value: function tableUpdateHandler(owner, itemIdx, itemData) {
+ //let itemDataInfo = pdu['RCDocSendDataRequestPdu'].decode(itemData);
+ var itemDataInfo = this.unPackPdu(owner, itemIdx, itemData);
+ if (itemDataInfo != null) {
+ this.docList[itemIdx] = itemDataInfo;
+
+ /* switch (itemDataInfo.action){
+ case DOC_ACTION_SWITCH_DOC:
+ break;
+ case DOC_ACTION_COMMAND:
+ break;
+ case DOC_ACTION_NORMAL:
+ break;
+ default :
+ break;
+ }*/
+ //GlobalConfig.activeDocId=0;//默认id
+ // GlobalConfig.activeDocCurPage=1;//默认页数
+ if (itemDataInfo && (itemDataInfo.visible == "true" || itemDataInfo.visible == true)) {
+ _GlobalConfig2.default.activeDocId = itemDataInfo.itemIdx; //当前激活的文档ID
+ _GlobalConfig2.default.activeDocCurPage = itemDataInfo.curPageNo; //当前激活的文档的当前页
+ loger.log('tableUpdateHandler 设置当前激活的文档id');
+ }
+ loger.log('tableUpdateHandler 发送给客户端');
+ console.log(itemDataInfo);
+ this._emit(_MessageTypes2.default.DOC_UPDATE, itemDataInfo);
+ } else {
+ loger.log('tableUpdateHandler 数据无效--> itemIdx', itemIdx);
+ }
+
+ /*try {
+ const recordInfo = pdu['RCDocSendDataRequestPdu'].decode(itemData);
+ recordInfo.type = ApeConsts.DOCUMENT_LOAD;
+ recordInfo.ext = recordInfo.name.substr(recordInfo.name.indexOf('.') + 1);
+ recordInfo.wbid = (recordInfo.id << 10) + recordInfo.curPageNo;
+ recordInfo.isPicture = ~['bmp', 'png', 'gif', 'jpg', 'jpeg'].indexOf(recordInfo.ext);
+ if (recordInfo.isPicture) {
+ recordInfo.namePath = recordInfo.uri.substring(0, recordInfo.uri.lastIndexOf('.'));
+ recordInfo.loadURL = recordInfo.namePath + '.' + recordInfo.ext;
+ } else {
+ recordInfo.namePath = recordInfo.uri.substring(0, recordInfo.uri.lastIndexOf('/'));
+ recordInfo.loadURL = `${recordInfo.namePath}/${recordInfo.curPageNo}.jpg`;
+ }
+ this.docList[recordId] = recordInfo;
+ this._emit(MessageTypes.DOC_UPDATE, recordInfo);
+ loger.log('Doc update ->' + itemIdx);
+ } catch (e) {
+ loger.warn('Doc Table Update Decode包异常');
+ }*/
+ }
+ }, {
+ key: 'onJoinChannelHandlerSuccess',
+ value: function onJoinChannelHandlerSuccess() {
+ var _this2 = this;
+
+ loger.log(this._session_name + ' onJoinChannelHandlerSuccess===========================');
+ if (this._apeDelayed) {
+ // this._apeDelayedMsgs.push(regBuffer);
+ // this._apeDelayedStart();
+ setTimeout(function () {
+ _this2._emit(DocApe.DOC_JOIN_CHANNEL_SUCCESS);
+ }, _GlobalConfig2.default.mcuDelay + _GlobalConfig2.default.docDelay || 12000 + _GlobalConfig2.default.docDelay);
+ } else {
+ setTimeout(function () {
+ _this2._emit(DocApe.DOC_JOIN_CHANNEL_SUCCESS);
+ }, _GlobalConfig2.default.docDelay);
+ }
+ }
+
+ //检查文档是否已经存在,如果存在 返回true,否则返回false
+
+ }, {
+ key: 'checkDocId',
+ value: function checkDocId(_docId) {
+ if (_docId == null) {
+ loger.warn('checkDocId _docId参数为null');
+ return true;
+ }
+ //遍历查找
+ for (var key in this.docList) {
+ var item = this.docList[key];
+ loger.log('item.docId==============_docId', item.docId, _docId);
+ if (item && item.docId == _docId) {
+ return true;
+ }
+ }
+
+ //储存的数据中没有查找到
+ return false;
+ }
+
+ ///////数据的封包和解包/////////////////////////////////////////
+
+ }, {
+ key: 'packPdu',
+ value: function packPdu(_param, _itemIdx) {
+ loger.log("文档===packPdu ");
+ //验证坐标点集合数组是否合法
+ if (_param == null || _itemIdx == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+
+ /* message RCDocSendDataModelPdu {
+ required uint32 item_idx=1;//唯一标识
+ required uint32 owner=2;
+ optional uint32 from=3;
+ optional uint32 cur_page_no=4;
+ optional uint32 page_num =5;
+ optional string file_type=6;
+ optional string creat_user_id=7;//创建文档userid
+ optional string relative_url=8;//文档相对地址
+ optional string url =9;//文档地址
+ optional uint32 cur_V=10;
+ optional uint32 cur_H=11;
+ optional uint32 scale=12;
+ optional bool visible=13;
+ optional uint32 action=14;//0,无操作, 1翻页 /缩放/滚动、2.显示/隐藏
+ optional string doc_id=15;//文档在服务器数据库中的唯一id
+ optional string file_name=16;//文档的名字
+ optional string dynamic_TS=17;//"dynamicTransferStatic": "0"
+ optional string md5=18;//md5
+ }*/
+
+ //判断type类型,根据type设置不同的参数
+ var docModelPdu = new _pdus2.default['RCDocSendDataModelPdu']();
+ docModelPdu.itemIdx = _itemIdx;
+ docModelPdu.owner = _GlobalConfig2.default.nodeId;
+ docModelPdu.from = _GlobalConfig2.default.nodeId;
+ docModelPdu.curPageNo = _param.curPageNo || 1;
+ docModelPdu.pageNum = _param.pageNum || 1;
+ docModelPdu.fileType = _param.fileType || "";
+ docModelPdu.creatUserId = _param.creatUserId || "0";
+ docModelPdu.url = _param.url || ""; //"http://101.200.150.192/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg";
+ docModelPdu.relativeUrl = _param.relativeUrl || ""; //"/DocSharing/data/h5test/20170206-171100025/7e9c4178cac1133e0dd9d5b583439122.jpg";
+ docModelPdu.curV = _param.curV || 0;
+ docModelPdu.curH = _param.curH || 0;
+ docModelPdu.scale = _param.scale || 100; //按百分比
+ docModelPdu.visible = _param.visible || false;
+ docModelPdu.action = _param.action || _ApeConsts2.default.DOC_ACTION_NORMAL; //0,无操作, 1翻页、2.显示/隐藏, 3缩放/滚动
+ docModelPdu.docId = _param.docId || ""; //文档在服务器数据库中的唯一id,必须有
+ docModelPdu.md5 = _param.md5 || ""; //MD5
+ docModelPdu.fileName = _param.fileName || "doc_" + _itemIdx; //文档的名字
+ docModelPdu.dynamicTS = _param.dynamicTS || "0"; //文档上传后返回值中的字段dynamicTransferStatic
+ console.log(docModelPdu);
+ return docModelPdu;
+ }
+ }, {
+ key: 'unPackPdu',
+ value: function unPackPdu(owner, itemIdx, itemData) {
+ loger.log("文档===unPackPdu ");
+ if (owner == null || itemIdx == null || itemData == null) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+
+ try {
+ var docModelPdu = _pdus2.default['RCDocSendDataModelPdu'].decode(itemData);
+ loger.log(docModelPdu);
+ return docModelPdu;
+ } catch (err) {
+ loger.log("文档收到数据 unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
+ }
+ return null;
+ }
+ }]);
+
+ return DocApe;
+ }(_Ape3.default);
+
+ DocApe.prototype.DOC_JOIN_CHANNEL_SUCCESS = DocApe.DOC_JOIN_CHANNEL_SUCCESS = 'docServer.join.channel.success';
+ var _default = DocApe;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/DocApe.js');
+
+ __REACT_HOT_LOADER__.register(itemIdx, 'itemIdx', 'D:/work/McuClient/src/apes/DocApe.js');
+
+ __REACT_HOT_LOADER__.register(DocApe, 'DocApe', 'D:/work/McuClient/src/apes/DocApe.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/DocApe.js');
+ }();
+
+ ;
+
+/***/ },
+/* 46 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ Object.defineProperty(exports, "__esModule", {
+ value: true
+ });
+
+ var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
+
+ var _Ape2 = __webpack_require__(37);
+
+ var _Ape3 = _interopRequireDefault(_Ape2);
+
+ var _ApeConsts = __webpack_require__(8);
+
+ var _ApeConsts2 = _interopRequireDefault(_ApeConsts);
+
+ var _pdus = __webpack_require__(25);
+
+ var _pdus2 = _interopRequireDefault(_pdus);
+
+ var _Loger = __webpack_require__(5);
+
+ var _Loger2 = _interopRequireDefault(_Loger);
+
+ var _MessageTypes = __webpack_require__(6);
+
+ var _MessageTypes2 = _interopRequireDefault(_MessageTypes);
+
+ var _zlib = __webpack_require__(39);
+
+ var _utf = __webpack_require__(11);
+
+ var _utf2 = _interopRequireDefault(_utf);
+
+ var _GlobalConfig = __webpack_require__(7);
+
+ var _GlobalConfig2 = _interopRequireDefault(_GlobalConfig);
+
+ var _EngineUtils = __webpack_require__(9);
+
+ var _EngineUtils2 = _interopRequireDefault(_EngineUtils);
+
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+ function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+ function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // //////////////////////////////////////////////////////////////////////////////
+ //
+ // Copyright (C) 2016-present All Rights Reserved.
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Github Home: https://github.com/AlexWang1987
+ // Author: AlexWang
+ // Date: 2016-08-26 17:36:20
+ // QQ Email: 1669499355@qq.com
+ // Last Modified time: 2016-09-21 14:06:12
+ // Description: LiveClass-WhiteBoardApe
+ //
+ // //////////////////////////////////////////////////////////////////////////////
+
+ var loger = _Loger2.default.getLoger('WhiteBoardApe');
+
+ var itemIdx = 0; //table插入新数据的计数id,目前用时间戳
+ var TYPE_BIGHT = 0; //任意线段
+ var TYPE_LINE = 1; //直线
+ var TYPE_RECT = 2; //矩形
+ var TYPE_CIRCLE = 3; //圆形
+ var TYPE_TEXT = 4; //文本
+
+ var WhiteBoardApe = function (_Ape) {
+ _inherits(WhiteBoardApe, _Ape);
+
+ function WhiteBoardApe() {
+ _classCallCheck(this, WhiteBoardApe);
+
+ // properties
+ var _this = _possibleConstructorReturn(this, (WhiteBoardApe.__proto__ || Object.getPrototypeOf(WhiteBoardApe)).call(this, _ApeConsts2.default.WHITEBOARD_SESSION_ID, _ApeConsts2.default.WHITEBOARD_SESSION_NAME, _ApeConsts2.default.WHITEBOARD_SESSION_TAG));
+
+ _this.annoInfos = {}; //储存所有的标注数据
+ _this.insertHistory = []; //添加的白板记录,用于撤回操作
+ // 白板延迟
+ // this._apeDelayed = true;
+
+ //Ape Models
+ _this.registerKey(_this._session_id, _this._session_name, _this._session_tag, new ArrayBuffer());
+ _this.registerObj(_pdus2.default.RCPDU_REG_REGISTER_TABLE, _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_ID, _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_NAME, _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_TAG, 0, new ArrayBuffer());
+
+ // ape listeners
+ _this.on(_pdus2.default.RCPDU_SESSION_JOIN_RESPONSE, _this._joinSessionHandler.bind(_this));
+ //this.on(pdu.RCPDU_CONFERENCE_SEND_DATA_REQUEST, this.whiteboardMsgComingHandler.bind(this));//这个是会议消息类型,flash里在使用这里不再使用,各个模块的消息由模块自己来处理
+ return _this;
+ }
+
+ _createClass(WhiteBoardApe, [{
+ key: '_joinSessionHandler',
+ value: function _joinSessionHandler(_data) {
+ loger.log("RCPDU_SESSION_JOIN_RESPONSE");
+ this.insertHistory = [];
+ }
+
+ /////////////发送数据操作//////////////////////////////////////////////////////
+ // 添加标注,发送信息
+
+ }, {
+ key: 'sendInsetAnnotaion',
+ value: function sendInsetAnnotaion(_param) {
+ if (_param == null || _EngineUtils2.default.isEmptyObject(_param)) {
+ loger.log('sendInsetAnnotaion失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+
+ itemIdx = _EngineUtils2.default.creatSoleNumberFromTimestamp();
+ var whiteBoardModelPdu = this.packPdu(_param, itemIdx);
+ if (whiteBoardModelPdu == null) {
+ loger.log('sendInsetAnnotaion失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ //console.log(whiteBoardModelPdu);
+
+ //储存记录,用于返回上一步操作
+ this.insertHistory.push(whiteBoardModelPdu);
+
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = itemIdx; //直接用时间戳作为id
+ tableItemPdu.registerObjId = _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_ID;
+ tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
+ tableItemPdu.itemData = whiteBoardModelPdu.toArrayBuffer();
+
+ //insert
+ var tableInsertItemPdu = new _pdus2.default['RCRegistryTableInsertItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
+ //repeated RCRegistryTableItemPdu items = 2;
+ tableInsertItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_INSERT_PDU; //
+ tableInsertItemPdu.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_ID;
+ updateObjPdu.subType = tableInsertItemPdu.type;
+ updateObjPdu.userData = tableInsertItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ console.log("添加白板数据=====itemIdx=" + tableItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+ //撤销上一步
+
+ }, {
+ key: 'sendGotoPrev',
+ value: function sendGotoPrev() {
+ loger.log("白板返回上一步");
+ if (this.insertHistory == null || this.insertHistory.length < 1) {
+ loger.warn("无法继续上一步操作,已经没有可以撤销的数据");
+ return;
+ }
+ console.log(this.insertHistory);
+ this.sendDeleteAnnotaion(this.insertHistory.pop());
+ }
+ //删除当前页码的所有标注
+
+ }, {
+ key: 'sendDeleteCurPageAnnotation',
+ value: function sendDeleteCurPageAnnotation(_param) {
+ for (var key in this.annoInfos) {
+ var item = this.annoInfos[key];
+ if (item && item.parentId == _GlobalConfig2.default.activeDocId && item.curPageNo == _GlobalConfig2.default.activeDocCurPage) {
+ loger.log("sendDeleteCurPageAnnotation 删除当前页面上的标注", key);
+ this.sendDeleteAnnotaion({ "itemIdx": key });
+ }
+ }
+ }
+ //删除所有标注
+
+ }, {
+ key: 'sendDeleteAllAnnotation',
+ value: function sendDeleteAllAnnotation(_param) {
+ for (var key in this.annoInfos) {
+ this.sendDeleteAnnotaion({ "itemIdx": key });
+ }
+ }
+
+ //删除标注,发送信息
+
+ }, {
+ key: 'sendDeleteAnnotaion',
+ value: function sendDeleteAnnotaion(_param) {
+ if (_param == null) {
+ loger.warn("要删除的数据不存在");
+ return;
+ }
+ //{"itemIdx":itemIdx}
+ var tableDeleteItemPdu = new _pdus2.default['RCRegistryTableDeleteItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_DELETE_PDU];
+ // repeated uint32 item_idx = 2;
+ tableDeleteItemPdu.type = _pdus2.default.RCPDU_REG_TABLE_DELETE_PDU; //
+ tableDeleteItemPdu.itemIdx = parseInt(_param.itemIdx); //这里需要设置要删除的数据的itemIdx,每条数据的这个id都不一样
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_ID;
+ updateObjPdu.subType = tableDeleteItemPdu.type;
+ updateObjPdu.userData = tableDeleteItemPdu.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ console.log("白板发送删除数据=============" + tableDeleteItemPdu.itemIdx);
+ this.sendUniform(adapterPdu, true);
+ }
+
+ //更新标注
+
+ }, {
+ key: 'sendUpdaterAnnotaion',
+ value: function sendUpdaterAnnotaion(_param) {
+ if (_param == null || _EngineUtils2.default.isEmptyObject(_param)) {
+ loger.log('sendUpdaterAnnotaion失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+ itemIdx = _param.itemIdx;
+ var whiteBoardModelPdu = this.packPdu(_param, itemIdx);
+ //console.log(whiteBoardModelPdu);
+
+ if (whiteBoardModelPdu == null) {
+ loger.log('sendInsetAnnotaion失败,参数错误');
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return;
+ }
+
+ var tableItemPdu = new _pdus2.default['RCRegistryTableItemPdu']();
+ tableItemPdu.itemIdx = itemIdx;
+ tableItemPdu.owner = 0; //收到flash的是这个值,不清楚先写固定
+ tableItemPdu.registerObjId = _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_ID;
+ tableItemPdu.itemData = whiteBoardModelPdu.toArrayBuffer();
+
+ //updater
+ var whiteBoardUpdateItem = new _pdus2.default['RCRegistryTableUpdateItemPdu']();
+ //optional RCPduType_E type = 1 [default = RCPDU_REG_TABLE_UPDATE_PDU];
+ //repeated RCRegistryTableItemPdu items = 2;
+ whiteBoardUpdateItem.type = _pdus2.default.RCPDU_REG_TABLE_UPDATE_PDU; //
+ whiteBoardUpdateItem.items.push(tableItemPdu);
+
+ var updateObjPdu = new _pdus2.default['RCRegistryUpdateObjPdu']();
+ updateObjPdu.objId = _ApeConsts2.default.WHITEBOARD_OBJ_TABLE_ID;
+ updateObjPdu.subType = whiteBoardUpdateItem.type;
+ updateObjPdu.userData = whiteBoardUpdateItem.toArrayBuffer();
+
+ //同步
+ var adapterItemPdu = new _pdus2.default['RCAdapterItemPdu']();
+ adapterItemPdu.type = _pdus2.default.RCPDU_REG_UPDATE_OBJ;
+ adapterItemPdu.itemData = updateObjPdu.toArrayBuffer();
+
+ var adapterPdu = new _pdus2.default['RCAdapterPdu']();
+ adapterPdu.type = _pdus2.default.RCPDU_REG_ADAPTER;
+ adapterPdu.item.push(adapterItemPdu);
+
+ console.log("白板发送更新数据===============22");
+ this.sendUniform(adapterPdu, true);
+ }
+
+ /////收到消息处理/////////////////////////////////////////////////////////////////////////////////
+ /* whiteboardMsgComingHandler(_data) {
+ //flash RCConferenceSendDataRequestPdu
+ //loger.warn('whiteboardMsgComingHandler needs to be handled.');
+ //const recordInfo = pdu['RCWhiteboardDataRequestPdu'].decode(pdu);
+ //loger.log("whiteboardMsgComingHandler",recordInfo);
+ let receiveInfo = pdu['RCConferenceSendDataRequestPdu'].decode(_data);
+ loger.log("whiteboardMsgComingHandler",receiveInfo);
+ }*/
+
+ }, {
+ key: 'tableInsertHandler',
+ value: function tableInsertHandler(owner, itemIdx, itemData) {
+ var whiteBoardModel = this.unPackPdu(owner, itemIdx, itemData);
+ loger.log('tableInsertHandler');
+ console.log(whiteBoardModel);
+ if (whiteBoardModel) {
+ if (_GlobalConfig2.default.activeDocId == whiteBoardModel.parentId && _GlobalConfig2.default.activeDocCurPage == whiteBoardModel.curPageNo) {
+ loger.log('WHITEBOARD_ANNOTAION_INSERT 显示到界面上', whiteBoardModel);
+ //this._emit(MessageTypes.WHITEBOARD_ANNOTAION_INSERT,whiteBoardModel);
+ this.insertAandShowAnnotaion(whiteBoardModel);
+ }
+ }
+ }
+ }, {
+ key: 'tableUpdateHandler',
+ value: function tableUpdateHandler(owner, itemIdx, itemData) {
+ var whiteBoardModel = this.unPackPdu(owner, itemIdx, itemData);
+ loger.log('tableUpdateHandler');
+ console.log(whiteBoardModel);
+ if (whiteBoardModel && whiteBoardModel.parentId == _GlobalConfig2.default.activeDocId && whiteBoardModel.curPageNo == _GlobalConfig2.default.activeDocCurPage) {
+ this.updateAandShowAnnotaion();
+ }
+ }
+ }, {
+ key: 'tableDeleteHandler',
+ value: function tableDeleteHandler(object_id, tableDeleteData) {
+ // console.log("白板收到数据,tableDeleteHandler object_id="+object_id);//((18<< 16) + 1)=1179649
+ loger.log('tableDeleteHandler', object_id, tableDeleteData); //["tableDeleteHandler",1179649,{"type":231,"itemIdx":[1486301768]}]
+ if (tableDeleteData && tableDeleteData.itemIdx) {
+ var len = tableDeleteData.itemIdx.length;
+ var itemIdxs = tableDeleteData.itemIdx;
+ for (var i = 0; i < len; i++) {
+ if (this.annoInfos[itemIdxs[i]]) {
+ loger.log("删除白板数据:", itemIdxs[i]);
+ //this._emit(MessageTypes.WHITEBOARD_ANNOTAION_DELETE,{ "itemIdx":itemIdxs[i]});
+ delete this.annoInfos[itemIdxs[i]];
+ }
+ }
+ }
+ this.updateAandShowAnnotaion();
+ }
+ //文档更新,白板也要更新
+
+ }, {
+ key: 'docUpdateHandler',
+ value: function docUpdateHandler(_data) {
+ loger.log("白板收到文档更新的消息docUpdateHandler");
+ console.log(_data);
+
+ //如果切换了文档或翻页,清除之前的添加步骤记录
+ if (_data.action == _ApeConsts2.default.DOC_ACTION_SWITCH_DOC || _data.action == _ApeConsts2.default.DOC_ACTION_SWITCH_PAGE) {
+ this.insertHistory = [];
+ }
+ this.updateAandShowAnnotaion();
+ }
+ //删除白板数据
+
+ }, {
+ key: 'docDeleteHandler',
+ value: function docDeleteHandler(_parentId) {
+ loger.log("白板收到文档删除的消息docDeleteHandler", _parentId);
+ for (var key in this.annoInfos) {
+ var item = this.annoInfos[key];
+ if (item && item.parentId == _parentId) {
+ loger.log("文档删除,白板数据也删除,itemIdx:" + key, "_parentId:", _parentId);
+ this.sendDeleteAnnotaion({ "itemIdx": key });
+ }
+ }
+ }
+ //增量添加标注
+
+ }, {
+ key: 'insertAandShowAnnotaion',
+ value: function insertAandShowAnnotaion(_item) {
+ var annotaionItems = [_item];
+ var updateObj = {
+ "isFresh": false,
+ "annotaionItems": annotaionItems
+ };
+ loger.log("WHITEBOARD_ANNOTATION_UPDATE", annotaionItems.length);
+ this._emit(_MessageTypes2.default.WHITEBOARD_ANNOTATION_UPDATE, updateObj);
+ }
+ //整体更新并且显示标注
+
+ }, {
+ key: 'updateAandShowAnnotaion',
+ value: function updateAandShowAnnotaion() {
+ var annotaionItems = [];
+ for (var key in this.annoInfos) {
+ var item = this.annoInfos[key];
+ if (item && item.parentId == _GlobalConfig2.default.activeDocId && item.curPageNo == _GlobalConfig2.default.activeDocCurPage) {
+ annotaionItems.push(item);
+ loger.log("显示和文档对应的白板数据docUpdateHandler itemIdx:", item.itemIdx, "doc itemIdx:", _GlobalConfig2.default.activeDocId, "curPageNo:", _GlobalConfig2.default.activeDocCurPage);
+ } else {
+ //loger.log("不显示白板数据docUpdateHandler",item);
+ }
+ }
+ var updateObj = {
+ "isFresh": true,
+ "annotaionItems": annotaionItems
+ };
+ loger.log("WHITEBOARD_ANNOTATION_UPDATE", annotaionItems.length);
+ this._emit(_MessageTypes2.default.WHITEBOARD_ANNOTATION_UPDATE, updateObj);
+ }
+
+ ///////白板数据的封包和解包/////////////////////////////////////////
+
+ }, {
+ key: 'packPdu',
+ value: function packPdu(_param, _itemIdx) {
+ /* required uint32 type= 1;//白板类型
+ required uint32 id= 2;//id 每一次绘制的唯一标识
+ required uint32 initiator=3; //绘制来自谁
+ optional string pointGroup=4; //坐标点集数组的JSON字符串
+ optional string color= 5 [default = "#000000"]; //颜色
+ optional uint32 thickness= 6 ;//线条粗细
+ optional uint32 radius= 7;//园的半径
+ optional uint32 fontSize= 8;//字体大小
+ optional uint32 fontName= 9;//字体名称
+ optional uint32 text= 10;//文本内容*/
+
+ //验证坐标点集合数组是否合法
+ if (_param.pointGroup == null || _param.pointGroup.length < 1) {
+ this._emit(_MessageTypes2.default.MCU_ERROR, _MessageTypes2.default.ERR_APE_INTERFACE_PARAM_WRONG);
+ return null;
+ }
+ //判断type类型,根据type设置不同的参数
+ var whiteBoardModelPdu = new _pdus2.default['RCWhiteBoardDataModelPdu']();
+ switch (_param.type) {
+ case TYPE_BIGHT:
+ break;
+ case TYPE_LINE:
+ break;
+ case TYPE_RECT:
+ break;
+ case TYPE_CIRCLE:
+ whiteBoardModelPdu.radius = parseInt(_param.radius);
+ break;
+ case TYPE_TEXT:
+ whiteBoardModelPdu.fontSize = parseInt(_param.fontSize);
+ whiteBoardModelPdu.fontName = _param.fontName || null;
+ whiteBoardModelPdu.text = _param.text || null;
+ break;
+ default:
+ //其它类型不做处理
+ return null;
+ break;
+ }
+ //下面4个是必须的参数
+ whiteBoardModelPdu.type = _param.type;
+ whiteBoardModelPdu.itemIdx = _itemIdx;
+ whiteBoardModelPdu.initiator = _GlobalConfig2.default.nodeId;
+
+ /* whiteBoardModelPdu.parentId=_param.parentId||0;
+ whiteBoardModelPdu.curPage=_param.curPage||1;*/
+
+ whiteBoardModelPdu.parentId = _GlobalConfig2.default.activeDocId; //当前激活的文档id
+ whiteBoardModelPdu.curPageNo = _GlobalConfig2.default.activeDocCurPage; //当前激活的文档页码
+
+ whiteBoardModelPdu.pointGroup = _EngineUtils2.default.arrayToJsonString(_param.pointGroup);
+ whiteBoardModelPdu.color = _param.color || "#000000";
+
+ return whiteBoardModelPdu;
+ }
+ }, {
+ key: 'unPackPdu',
+ value: function unPackPdu(owner, itemIdx, itemData) {
+ try {
+ loger.log("白板收到数据===unPackPdu ");
+ var whiteBoardModelPdu = _pdus2.default['RCWhiteBoardDataModelPdu'].decode(itemData);
+ //console.log(whiteBoardModelPdu);
+ //loger.log(whiteBoardModelPdu);
+ var _pointGroup = _EngineUtils2.default.arrayFromJsonString(whiteBoardModelPdu.pointGroup);
+ whiteBoardModelPdu.pointGroup = _pointGroup;
+ this.annoInfos[itemIdx] = whiteBoardModelPdu;
+ return whiteBoardModelPdu;
+ } catch (err) {
+ console.log("unPackPdu Pdu解析错误,itemIdx=" + itemIdx + " err:" + err.message);
+ }
+ return null;
+ }
+ }]);
+
+ return WhiteBoardApe;
+ }(_Ape3.default);
+
+ var _default = WhiteBoardApe;
+ exports.default = _default;
+ ;
+
+ var _temp = function () {
+ if (typeof __REACT_HOT_LOADER__ === 'undefined') {
+ return;
+ }
+
+ __REACT_HOT_LOADER__.register(loger, 'loger', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(itemIdx, 'itemIdx', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(TYPE_BIGHT, 'TYPE_BIGHT', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(TYPE_LINE, 'TYPE_LINE', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(TYPE_RECT, 'TYPE_RECT', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(TYPE_CIRCLE, 'TYPE_CIRCLE', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(TYPE_TEXT, 'TYPE_TEXT', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(WhiteBoardApe, 'WhiteBoardApe', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+
+ __REACT_HOT_LOADER__.register(_default, 'default', 'D:/work/McuClient/src/apes/WhiteBoardApe.js');
+ }();
+
+ ;
+
+/***/ },
+/* 47 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var require;var __WEBPACK_AMD_DEFINE_RESULT__;/* WEBPACK VAR INJECTION */(function(process, global, module) {/*!
+ * @overview es6-promise - a tiny implementation of Promises/A+.
+ * @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
+ * @license Licensed under MIT license
+ * See https://raw.githubusercontent.com/jakearchibald/es6-promise/master/LICENSE
+ * @version 3.2.1
+ */
+
+ (function() {
+ "use strict";
+ function lib$es6$promise$utils$$objectOrFunction(x) {
+ return typeof x === 'function' || (typeof x === 'object' && x !== null);
+ }
+
+ function lib$es6$promise$utils$$isFunction(x) {
+ return typeof x === 'function';
+ }
+
+ function lib$es6$promise$utils$$isMaybeThenable(x) {
+ return typeof x === 'object' && x !== null;
+ }
+
+ var lib$es6$promise$utils$$_isArray;
+ if (!Array.isArray) {
+ lib$es6$promise$utils$$_isArray = function (x) {
+ return Object.prototype.toString.call(x) === '[object Array]';
+ };
+ } else {
+ lib$es6$promise$utils$$_isArray = Array.isArray;
+ }
+
+ var lib$es6$promise$utils$$isArray = lib$es6$promise$utils$$_isArray;
+ var lib$es6$promise$asap$$len = 0;
+ var lib$es6$promise$asap$$vertxNext;
+ var lib$es6$promise$asap$$customSchedulerFn;
+
+ var lib$es6$promise$asap$$asap = function asap(callback, arg) {
+ lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len] = callback;
+ lib$es6$promise$asap$$queue[lib$es6$promise$asap$$len + 1] = arg;
+ lib$es6$promise$asap$$len += 2;
+ if (lib$es6$promise$asap$$len === 2) {
+ // If len is 2, that means that we need to schedule an async flush.
+ // If additional callbacks are queued before the queue is flushed, they
+ // will be processed by this flush that we are scheduling.
+ if (lib$es6$promise$asap$$customSchedulerFn) {
+ lib$es6$promise$asap$$customSchedulerFn(lib$es6$promise$asap$$flush);
+ } else {
+ lib$es6$promise$asap$$scheduleFlush();
+ }
+ }
+ }
+
+ function lib$es6$promise$asap$$setScheduler(scheduleFn) {
+ lib$es6$promise$asap$$customSchedulerFn = scheduleFn;
+ }
+
+ function lib$es6$promise$asap$$setAsap(asapFn) {
+ lib$es6$promise$asap$$asap = asapFn;
+ }
+
+ var lib$es6$promise$asap$$browserWindow = (typeof window !== 'undefined') ? window : undefined;
+ var lib$es6$promise$asap$$browserGlobal = lib$es6$promise$asap$$browserWindow || {};
+ var lib$es6$promise$asap$$BrowserMutationObserver = lib$es6$promise$asap$$browserGlobal.MutationObserver || lib$es6$promise$asap$$browserGlobal.WebKitMutationObserver;
+ var lib$es6$promise$asap$$isNode = typeof self === 'undefined' && typeof process !== 'undefined' && {}.toString.call(process) === '[object process]';
+
+ // test for web worker but not in IE10
+ var lib$es6$promise$asap$$isWorker = typeof Uint8ClampedArray !== 'undefined' &&
+ typeof importScripts !== 'undefined' &&
+ typeof MessageChannel !== 'undefined';
+
+ // node
+ function lib$es6$promise$asap$$useNextTick() {
+ // node version 0.10.x displays a deprecation warning when nextTick is used recursively
+ // see https://github.com/cujojs/when/issues/410 for details
+ return function() {
+ process.nextTick(lib$es6$promise$asap$$flush);
+ };
+ }
+
+ // vertx
+ function lib$es6$promise$asap$$useVertxTimer() {
+ return function() {
+ lib$es6$promise$asap$$vertxNext(lib$es6$promise$asap$$flush);
+ };
+ }
+
+ function lib$es6$promise$asap$$useMutationObserver() {
+ var iterations = 0;
+ var observer = new lib$es6$promise$asap$$BrowserMutationObserver(lib$es6$promise$asap$$flush);
+ var node = document.createTextNode('');
+ observer.observe(node, { characterData: true });
+
+ return function() {
+ node.data = (iterations = ++iterations % 2);
+ };
+ }
+
+ // web worker
+ function lib$es6$promise$asap$$useMessageChannel() {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = lib$es6$promise$asap$$flush;
+ return function () {
+ channel.port2.postMessage(0);
+ };
+ }
+
+ function lib$es6$promise$asap$$useSetTimeout() {
+ return function() {
+ setTimeout(lib$es6$promise$asap$$flush, 1);
+ };
+ }
+
+ var lib$es6$promise$asap$$queue = new Array(1000);
+ function lib$es6$promise$asap$$flush() {
+ for (var i = 0; i < lib$es6$promise$asap$$len; i+=2) {
+ var callback = lib$es6$promise$asap$$queue[i];
+ var arg = lib$es6$promise$asap$$queue[i+1];
+
+ callback(arg);
+
+ lib$es6$promise$asap$$queue[i] = undefined;
+ lib$es6$promise$asap$$queue[i+1] = undefined;
+ }
+
+ lib$es6$promise$asap$$len = 0;
+ }
+
+ function lib$es6$promise$asap$$attemptVertx() {
+ try {
+ var r = require;
+ var vertx = __webpack_require__(48);
+ lib$es6$promise$asap$$vertxNext = vertx.runOnLoop || vertx.runOnContext;
+ return lib$es6$promise$asap$$useVertxTimer();
+ } catch(e) {
+ return lib$es6$promise$asap$$useSetTimeout();
+ }
+ }
+
+ var lib$es6$promise$asap$$scheduleFlush;
+ // Decide what async method to use to triggering processing of queued callbacks:
+ if (lib$es6$promise$asap$$isNode) {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useNextTick();
+ } else if (lib$es6$promise$asap$$BrowserMutationObserver) {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMutationObserver();
+ } else if (lib$es6$promise$asap$$isWorker) {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useMessageChannel();
+ } else if (lib$es6$promise$asap$$browserWindow === undefined && "function" === 'function') {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$attemptVertx();
+ } else {
+ lib$es6$promise$asap$$scheduleFlush = lib$es6$promise$asap$$useSetTimeout();
+ }
+ function lib$es6$promise$then$$then(onFulfillment, onRejection) {
+ var parent = this;
+
+ var child = new this.constructor(lib$es6$promise$$internal$$noop);
+
+ if (child[lib$es6$promise$$internal$$PROMISE_ID] === undefined) {
+ lib$es6$promise$$internal$$makePromise(child);
+ }
+
+ var state = parent._state;
+
+ if (state) {
+ var callback = arguments[state - 1];
+ lib$es6$promise$asap$$asap(function(){
+ lib$es6$promise$$internal$$invokeCallback(state, child, callback, parent._result);
+ });
+ } else {
+ lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection);
+ }
+
+ return child;
+ }
+ var lib$es6$promise$then$$default = lib$es6$promise$then$$then;
+ function lib$es6$promise$promise$resolve$$resolve(object) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ if (object && typeof object === 'object' && object.constructor === Constructor) {
+ return object;
+ }
+
+ var promise = new Constructor(lib$es6$promise$$internal$$noop);
+ lib$es6$promise$$internal$$resolve(promise, object);
+ return promise;
+ }
+ var lib$es6$promise$promise$resolve$$default = lib$es6$promise$promise$resolve$$resolve;
+ var lib$es6$promise$$internal$$PROMISE_ID = Math.random().toString(36).substring(16);
+
+ function lib$es6$promise$$internal$$noop() {}
+
+ var lib$es6$promise$$internal$$PENDING = void 0;
+ var lib$es6$promise$$internal$$FULFILLED = 1;
+ var lib$es6$promise$$internal$$REJECTED = 2;
+
+ var lib$es6$promise$$internal$$GET_THEN_ERROR = new lib$es6$promise$$internal$$ErrorObject();
+
+ function lib$es6$promise$$internal$$selfFulfillment() {
+ return new TypeError("You cannot resolve a promise with itself");
+ }
+
+ function lib$es6$promise$$internal$$cannotReturnOwn() {
+ return new TypeError('A promises callback cannot return that same promise.');
+ }
+
+ function lib$es6$promise$$internal$$getThen(promise) {
+ try {
+ return promise.then;
+ } catch(error) {
+ lib$es6$promise$$internal$$GET_THEN_ERROR.error = error;
+ return lib$es6$promise$$internal$$GET_THEN_ERROR;
+ }
+ }
+
+ function lib$es6$promise$$internal$$tryThen(then, value, fulfillmentHandler, rejectionHandler) {
+ try {
+ then.call(value, fulfillmentHandler, rejectionHandler);
+ } catch(e) {
+ return e;
+ }
+ }
+
+ function lib$es6$promise$$internal$$handleForeignThenable(promise, thenable, then) {
+ lib$es6$promise$asap$$asap(function(promise) {
+ var sealed = false;
+ var error = lib$es6$promise$$internal$$tryThen(then, thenable, function(value) {
+ if (sealed) { return; }
+ sealed = true;
+ if (thenable !== value) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ } else {
+ lib$es6$promise$$internal$$fulfill(promise, value);
+ }
+ }, function(reason) {
+ if (sealed) { return; }
+ sealed = true;
+
+ lib$es6$promise$$internal$$reject(promise, reason);
+ }, 'Settle: ' + (promise._label || ' unknown promise'));
+
+ if (!sealed && error) {
+ sealed = true;
+ lib$es6$promise$$internal$$reject(promise, error);
+ }
+ }, promise);
+ }
+
+ function lib$es6$promise$$internal$$handleOwnThenable(promise, thenable) {
+ if (thenable._state === lib$es6$promise$$internal$$FULFILLED) {
+ lib$es6$promise$$internal$$fulfill(promise, thenable._result);
+ } else if (thenable._state === lib$es6$promise$$internal$$REJECTED) {
+ lib$es6$promise$$internal$$reject(promise, thenable._result);
+ } else {
+ lib$es6$promise$$internal$$subscribe(thenable, undefined, function(value) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ }, function(reason) {
+ lib$es6$promise$$internal$$reject(promise, reason);
+ });
+ }
+ }
+
+ function lib$es6$promise$$internal$$handleMaybeThenable(promise, maybeThenable, then) {
+ if (maybeThenable.constructor === promise.constructor &&
+ then === lib$es6$promise$then$$default &&
+ constructor.resolve === lib$es6$promise$promise$resolve$$default) {
+ lib$es6$promise$$internal$$handleOwnThenable(promise, maybeThenable);
+ } else {
+ if (then === lib$es6$promise$$internal$$GET_THEN_ERROR) {
+ lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$GET_THEN_ERROR.error);
+ } else if (then === undefined) {
+ lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
+ } else if (lib$es6$promise$utils$$isFunction(then)) {
+ lib$es6$promise$$internal$$handleForeignThenable(promise, maybeThenable, then);
+ } else {
+ lib$es6$promise$$internal$$fulfill(promise, maybeThenable);
+ }
+ }
+ }
+
+ function lib$es6$promise$$internal$$resolve(promise, value) {
+ if (promise === value) {
+ lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$selfFulfillment());
+ } else if (lib$es6$promise$utils$$objectOrFunction(value)) {
+ lib$es6$promise$$internal$$handleMaybeThenable(promise, value, lib$es6$promise$$internal$$getThen(value));
+ } else {
+ lib$es6$promise$$internal$$fulfill(promise, value);
+ }
+ }
+
+ function lib$es6$promise$$internal$$publishRejection(promise) {
+ if (promise._onerror) {
+ promise._onerror(promise._result);
+ }
+
+ lib$es6$promise$$internal$$publish(promise);
+ }
+
+ function lib$es6$promise$$internal$$fulfill(promise, value) {
+ if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
+
+ promise._result = value;
+ promise._state = lib$es6$promise$$internal$$FULFILLED;
+
+ if (promise._subscribers.length !== 0) {
+ lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, promise);
+ }
+ }
+
+ function lib$es6$promise$$internal$$reject(promise, reason) {
+ if (promise._state !== lib$es6$promise$$internal$$PENDING) { return; }
+ promise._state = lib$es6$promise$$internal$$REJECTED;
+ promise._result = reason;
+
+ lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publishRejection, promise);
+ }
+
+ function lib$es6$promise$$internal$$subscribe(parent, child, onFulfillment, onRejection) {
+ var subscribers = parent._subscribers;
+ var length = subscribers.length;
+
+ parent._onerror = null;
+
+ subscribers[length] = child;
+ subscribers[length + lib$es6$promise$$internal$$FULFILLED] = onFulfillment;
+ subscribers[length + lib$es6$promise$$internal$$REJECTED] = onRejection;
+
+ if (length === 0 && parent._state) {
+ lib$es6$promise$asap$$asap(lib$es6$promise$$internal$$publish, parent);
+ }
+ }
+
+ function lib$es6$promise$$internal$$publish(promise) {
+ var subscribers = promise._subscribers;
+ var settled = promise._state;
+
+ if (subscribers.length === 0) { return; }
+
+ var child, callback, detail = promise._result;
+
+ for (var i = 0; i < subscribers.length; i += 3) {
+ child = subscribers[i];
+ callback = subscribers[i + settled];
+
+ if (child) {
+ lib$es6$promise$$internal$$invokeCallback(settled, child, callback, detail);
+ } else {
+ callback(detail);
+ }
+ }
+
+ promise._subscribers.length = 0;
+ }
+
+ function lib$es6$promise$$internal$$ErrorObject() {
+ this.error = null;
+ }
+
+ var lib$es6$promise$$internal$$TRY_CATCH_ERROR = new lib$es6$promise$$internal$$ErrorObject();
+
+ function lib$es6$promise$$internal$$tryCatch(callback, detail) {
+ try {
+ return callback(detail);
+ } catch(e) {
+ lib$es6$promise$$internal$$TRY_CATCH_ERROR.error = e;
+ return lib$es6$promise$$internal$$TRY_CATCH_ERROR;
+ }
+ }
+
+ function lib$es6$promise$$internal$$invokeCallback(settled, promise, callback, detail) {
+ var hasCallback = lib$es6$promise$utils$$isFunction(callback),
+ value, error, succeeded, failed;
+
+ if (hasCallback) {
+ value = lib$es6$promise$$internal$$tryCatch(callback, detail);
+
+ if (value === lib$es6$promise$$internal$$TRY_CATCH_ERROR) {
+ failed = true;
+ error = value.error;
+ value = null;
+ } else {
+ succeeded = true;
+ }
+
+ if (promise === value) {
+ lib$es6$promise$$internal$$reject(promise, lib$es6$promise$$internal$$cannotReturnOwn());
+ return;
+ }
+
+ } else {
+ value = detail;
+ succeeded = true;
+ }
+
+ if (promise._state !== lib$es6$promise$$internal$$PENDING) {
+ // noop
+ } else if (hasCallback && succeeded) {
+ lib$es6$promise$$internal$$resolve(promise, value);
+ } else if (failed) {
+ lib$es6$promise$$internal$$reject(promise, error);
+ } else if (settled === lib$es6$promise$$internal$$FULFILLED) {
+ lib$es6$promise$$internal$$fulfill(promise, value);
+ } else if (settled === lib$es6$promise$$internal$$REJECTED) {
+ lib$es6$promise$$internal$$reject(promise, value);
+ }
+ }
+
+ function lib$es6$promise$$internal$$initializePromise(promise, resolver) {
+ try {
+ resolver(function resolvePromise(value){
+ lib$es6$promise$$internal$$resolve(promise, value);
+ }, function rejectPromise(reason) {
+ lib$es6$promise$$internal$$reject(promise, reason);
+ });
+ } catch(e) {
+ lib$es6$promise$$internal$$reject(promise, e);
+ }
+ }
+
+ var lib$es6$promise$$internal$$id = 0;
+ function lib$es6$promise$$internal$$nextId() {
+ return lib$es6$promise$$internal$$id++;
+ }
+
+ function lib$es6$promise$$internal$$makePromise(promise) {
+ promise[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$id++;
+ promise._state = undefined;
+ promise._result = undefined;
+ promise._subscribers = [];
+ }
+
+ function lib$es6$promise$promise$all$$all(entries) {
+ return new lib$es6$promise$enumerator$$default(this, entries).promise;
+ }
+ var lib$es6$promise$promise$all$$default = lib$es6$promise$promise$all$$all;
+ function lib$es6$promise$promise$race$$race(entries) {
+ /*jshint validthis:true */
+ var Constructor = this;
+
+ if (!lib$es6$promise$utils$$isArray(entries)) {
+ return new Constructor(function(resolve, reject) {
+ reject(new TypeError('You must pass an array to race.'));
+ });
+ } else {
+ return new Constructor(function(resolve, reject) {
+ var length = entries.length;
+ for (var i = 0; i < length; i++) {
+ Constructor.resolve(entries[i]).then(resolve, reject);
+ }
+ });
+ }
+ }
+ var lib$es6$promise$promise$race$$default = lib$es6$promise$promise$race$$race;
+ function lib$es6$promise$promise$reject$$reject(reason) {
+ /*jshint validthis:true */
+ var Constructor = this;
+ var promise = new Constructor(lib$es6$promise$$internal$$noop);
+ lib$es6$promise$$internal$$reject(promise, reason);
+ return promise;
+ }
+ var lib$es6$promise$promise$reject$$default = lib$es6$promise$promise$reject$$reject;
+
+
+ function lib$es6$promise$promise$$needsResolver() {
+ throw new TypeError('You must pass a resolver function as the first argument to the promise constructor');
+ }
+
+ function lib$es6$promise$promise$$needsNew() {
+ throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");
+ }
+
+ var lib$es6$promise$promise$$default = lib$es6$promise$promise$$Promise;
+ /**
+ Promise objects represent the eventual result of an asynchronous operation. The
+ primary way of interacting with a promise is through its `then` method, which
+ registers callbacks to receive either a promise's eventual value or the reason
+ why the promise cannot be fulfilled.
+
+ Terminology
+ -----------
+
+ - `promise` is an object or function with a `then` method whose behavior conforms to this specification.
+ - `thenable` is an object or function that defines a `then` method.
+ - `value` is any legal JavaScript value (including undefined, a thenable, or a promise).
+ - `exception` is a value that is thrown using the throw statement.
+ - `reason` is a value that indicates why a promise was rejected.
+ - `settled` the final resting state of a promise, fulfilled or rejected.
+
+ A promise can be in one of three states: pending, fulfilled, or rejected.
+
+ Promises that are fulfilled have a fulfillment value and are in the fulfilled
+ state. Promises that are rejected have a rejection reason and are in the
+ rejected state. A fulfillment value is never a thenable.
+
+ Promises can also be said to *resolve* a value. If this value is also a
+ promise, then the original promise's settled state will match the value's
+ settled state. So a promise that *resolves* a promise that rejects will
+ itself reject, and a promise that *resolves* a promise that fulfills will
+ itself fulfill.
+
+
+ Basic Usage:
+ ------------
+
+ ```js
+ var promise = new Promise(function(resolve, reject) {
+ // on success
+ resolve(value);
+
+ // on failure
+ reject(reason);
+ });
+
+ promise.then(function(value) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Advanced Usage:
+ ---------------
+
+ Promises shine when abstracting away asynchronous interactions such as
+ `XMLHttpRequest`s.
+
+ ```js
+ function getJSON(url) {
+ return new Promise(function(resolve, reject){
+ var xhr = new XMLHttpRequest();
+
+ xhr.open('GET', url);
+ xhr.onreadystatechange = handler;
+ xhr.responseType = 'json';
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.send();
+
+ function handler() {
+ if (this.readyState === this.DONE) {
+ if (this.status === 200) {
+ resolve(this.response);
+ } else {
+ reject(new Error('getJSON: `' + url + '` failed with status: [' + this.status + ']'));
+ }
+ }
+ };
+ });
+ }
+
+ getJSON('/posts.json').then(function(json) {
+ // on fulfillment
+ }, function(reason) {
+ // on rejection
+ });
+ ```
+
+ Unlike callbacks, promises are great composable primitives.
+
+ ```js
+ Promise.all([
+ getJSON('/posts'),
+ getJSON('/comments')
+ ]).then(function(values){
+ values[0] // => postsJSON
+ values[1] // => commentsJSON
+
+ return values;
+ });
+ ```
+
+ @class Promise
+ @param {function} resolver
+ Useful for tooling.
+ @constructor
+ */
+ function lib$es6$promise$promise$$Promise(resolver) {
+ this[lib$es6$promise$$internal$$PROMISE_ID] = lib$es6$promise$$internal$$nextId();
+ this._result = this._state = undefined;
+ this._subscribers = [];
+
+ if (lib$es6$promise$$internal$$noop !== resolver) {
+ typeof resolver !== 'function' && lib$es6$promise$promise$$needsResolver();
+ this instanceof lib$es6$promise$promise$$Promise ? lib$es6$promise$$internal$$initializePromise(this, resolver) : lib$es6$promise$promise$$needsNew();
+ }
+ }
+
+ lib$es6$promise$promise$$Promise.all = lib$es6$promise$promise$all$$default;
+ lib$es6$promise$promise$$Promise.race = lib$es6$promise$promise$race$$default;
+ lib$es6$promise$promise$$Promise.resolve = lib$es6$promise$promise$resolve$$default;
+ lib$es6$promise$promise$$Promise.reject = lib$es6$promise$promise$reject$$default;
+ lib$es6$promise$promise$$Promise._setScheduler = lib$es6$promise$asap$$setScheduler;
+ lib$es6$promise$promise$$Promise._setAsap = lib$es6$promise$asap$$setAsap;
+ lib$es6$promise$promise$$Promise._asap = lib$es6$promise$asap$$asap;
+
+ lib$es6$promise$promise$$Promise.prototype = {
+ constructor: lib$es6$promise$promise$$Promise,
+
+ /**
+ The primary way of interacting with a promise is through its `then` method,
+ which registers callbacks to receive either a promise's eventual value or the
+ reason why the promise cannot be fulfilled.
+
+ ```js
+ findUser().then(function(user){
+ // user is available
+ }, function(reason){
+ // user is unavailable, and you are given the reason why
+ });
+ ```
+
+ Chaining
+ --------
+
+ The return value of `then` is itself a promise. This second, 'downstream'
+ promise is resolved with the return value of the first promise's fulfillment
+ or rejection handler, or rejected if the handler throws an exception.
+
+ ```js
+ findUser().then(function (user) {
+ return user.name;
+ }, function (reason) {
+ return 'default name';
+ }).then(function (userName) {
+ // If `findUser` fulfilled, `userName` will be the user's name, otherwise it
+ // will be `'default name'`
+ });
+
+ findUser().then(function (user) {
+ throw new Error('Found user, but still unhappy');
+ }, function (reason) {
+ throw new Error('`findUser` rejected and we're unhappy');
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // if `findUser` fulfilled, `reason` will be 'Found user, but still unhappy'.
+ // If `findUser` rejected, `reason` will be '`findUser` rejected and we're unhappy'.
+ });
+ ```
+ If the downstream promise does not specify a rejection handler, rejection reasons will be propagated further downstream.
+
+ ```js
+ findUser().then(function (user) {
+ throw new PedagogicalException('Upstream error');
+ }).then(function (value) {
+ // never reached
+ }).then(function (value) {
+ // never reached
+ }, function (reason) {
+ // The `PedgagocialException` is propagated all the way down to here
+ });
+ ```
+
+ Assimilation
+ ------------
+
+ Sometimes the value you want to propagate to a downstream promise can only be
+ retrieved asynchronously. This can be achieved by returning a promise in the
+ fulfillment or rejection handler. The downstream promise will then be pending
+ until the returned promise is settled. This is called *assimilation*.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // The user's comments are now available
+ });
+ ```
+
+ If the assimliated promise rejects, then the downstream promise will also reject.
+
+ ```js
+ findUser().then(function (user) {
+ return findCommentsByAuthor(user);
+ }).then(function (comments) {
+ // If `findCommentsByAuthor` fulfills, we'll have the value here
+ }, function (reason) {
+ // If `findCommentsByAuthor` rejects, we'll have the reason here
+ });
+ ```
+
+ Simple Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var result;
+
+ try {
+ result = findResult();
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+ findResult(function(result, err){
+ if (err) {
+ // failure
+ } else {
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findResult().then(function(result){
+ // success
+ }, function(reason){
+ // failure
+ });
+ ```
+
+ Advanced Example
+ --------------
+
+ Synchronous Example
+
+ ```javascript
+ var author, books;
+
+ try {
+ author = findAuthor();
+ books = findBooksByAuthor(author);
+ // success
+ } catch(reason) {
+ // failure
+ }
+ ```
+
+ Errback Example
+
+ ```js
+
+ function foundBooks(books) {
+
+ }
+
+ function failure(reason) {
+
+ }
+
+ findAuthor(function(author, err){
+ if (err) {
+ failure(err);
+ // failure
+ } else {
+ try {
+ findBoooksByAuthor(author, function(books, err) {
+ if (err) {
+ failure(err);
+ } else {
+ try {
+ foundBooks(books);
+ } catch(reason) {
+ failure(reason);
+ }
+ }
+ });
+ } catch(error) {
+ failure(err);
+ }
+ // success
+ }
+ });
+ ```
+
+ Promise Example;
+
+ ```javascript
+ findAuthor().
+ then(findBooksByAuthor).
+ then(function(books){
+ // found books
+ }).catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method then
+ @param {Function} onFulfilled
+ @param {Function} onRejected
+ Useful for tooling.
+ @return {Promise}
+ */
+ then: lib$es6$promise$then$$default,
+
+ /**
+ `catch` is simply sugar for `then(undefined, onRejection)` which makes it the same
+ as the catch block of a try/catch statement.
+
+ ```js
+ function findAuthor(){
+ throw new Error('couldn't find that author');
+ }
+
+ // synchronous
+ try {
+ findAuthor();
+ } catch(reason) {
+ // something went wrong
+ }
+
+ // async with promises
+ findAuthor().catch(function(reason){
+ // something went wrong
+ });
+ ```
+
+ @method catch
+ @param {Function} onRejection
+ Useful for tooling.
+ @return {Promise}
+ */
+ 'catch': function(onRejection) {
+ return this.then(null, onRejection);
+ }
+ };
+ var lib$es6$promise$enumerator$$default = lib$es6$promise$enumerator$$Enumerator;
+ function lib$es6$promise$enumerator$$Enumerator(Constructor, input) {
+ this._instanceConstructor = Constructor;
+ this.promise = new Constructor(lib$es6$promise$$internal$$noop);
+
+ if (!this.promise[lib$es6$promise$$internal$$PROMISE_ID]) {
+ lib$es6$promise$$internal$$makePromise(this.promise);
+ }
+
+ if (lib$es6$promise$utils$$isArray(input)) {
+ this._input = input;
+ this.length = input.length;
+ this._remaining = input.length;
+
+ this._result = new Array(this.length);
+
+ if (this.length === 0) {
+ lib$es6$promise$$internal$$fulfill(this.promise, this._result);
+ } else {
+ this.length = this.length || 0;
+ this._enumerate();
+ if (this._remaining === 0) {
+ lib$es6$promise$$internal$$fulfill(this.promise, this._result);
+ }
+ }
+ } else {
+ lib$es6$promise$$internal$$reject(this.promise, lib$es6$promise$enumerator$$validationError());
+ }
+ }
+
+ function lib$es6$promise$enumerator$$validationError() {
+ return new Error('Array Methods must be provided an Array');
+ }
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._enumerate = function() {
+ var length = this.length;
+ var input = this._input;
+
+ for (var i = 0; this._state === lib$es6$promise$$internal$$PENDING && i < length; i++) {
+ this._eachEntry(input[i], i);
+ }
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._eachEntry = function(entry, i) {
+ var c = this._instanceConstructor;
+ var resolve = c.resolve;
+
+ if (resolve === lib$es6$promise$promise$resolve$$default) {
+ var then = lib$es6$promise$$internal$$getThen(entry);
+
+ if (then === lib$es6$promise$then$$default &&
+ entry._state !== lib$es6$promise$$internal$$PENDING) {
+ this._settledAt(entry._state, i, entry._result);
+ } else if (typeof then !== 'function') {
+ this._remaining--;
+ this._result[i] = entry;
+ } else if (c === lib$es6$promise$promise$$default) {
+ var promise = new c(lib$es6$promise$$internal$$noop);
+ lib$es6$promise$$internal$$handleMaybeThenable(promise, entry, then);
+ this._willSettleAt(promise, i);
+ } else {
+ this._willSettleAt(new c(function(resolve) { resolve(entry); }), i);
+ }
+ } else {
+ this._willSettleAt(resolve(entry), i);
+ }
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._settledAt = function(state, i, value) {
+ var promise = this.promise;
+
+ if (promise._state === lib$es6$promise$$internal$$PENDING) {
+ this._remaining--;
+
+ if (state === lib$es6$promise$$internal$$REJECTED) {
+ lib$es6$promise$$internal$$reject(promise, value);
+ } else {
+ this._result[i] = value;
+ }
+ }
+
+ if (this._remaining === 0) {
+ lib$es6$promise$$internal$$fulfill(promise, this._result);
+ }
+ };
+
+ lib$es6$promise$enumerator$$Enumerator.prototype._willSettleAt = function(promise, i) {
+ var enumerator = this;
+
+ lib$es6$promise$$internal$$subscribe(promise, undefined, function(value) {
+ enumerator._settledAt(lib$es6$promise$$internal$$FULFILLED, i, value);
+ }, function(reason) {
+ enumerator._settledAt(lib$es6$promise$$internal$$REJECTED, i, reason);
+ });
+ };
+ function lib$es6$promise$polyfill$$polyfill() {
+ var local;
+
+ if (typeof global !== 'undefined') {
+ local = global;
+ } else if (typeof self !== 'undefined') {
+ local = self;
+ } else {
+ try {
+ local = Function('return this')();
+ } catch (e) {
+ throw new Error('polyfill failed because global object is unavailable in this environment');
+ }
+ }
+
+ var P = local.Promise;
+
+ if (P && Object.prototype.toString.call(P.resolve()) === '[object Promise]' && !P.cast) {
+ return;
+ }
+
+ local.Promise = lib$es6$promise$promise$$default;
+ }
+ var lib$es6$promise$polyfill$$default = lib$es6$promise$polyfill$$polyfill;
+
+ var lib$es6$promise$umd$$ES6Promise = {
+ 'Promise': lib$es6$promise$promise$$default,
+ 'polyfill': lib$es6$promise$polyfill$$default
+ };
+
+ /* global define:true module:true window: true */
+ if ("function" === 'function' && __webpack_require__(28)['amd']) {
+ !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return lib$es6$promise$umd$$ES6Promise; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof module !== 'undefined' && module['exports']) {
+ module['exports'] = lib$es6$promise$umd$$ES6Promise;
+ } else if (typeof this !== 'undefined') {
+ this['ES6Promise'] = lib$es6$promise$umd$$ES6Promise;
+ }
+
+ lib$es6$promise$polyfill$$default();
+ }).call(this);
+
+
+ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(27), (function() { return this; }()), __webpack_require__(12)(module)))
+
+/***/ },
+/* 48 */
+/***/ function(module, exports) {
+
+ /* (ignored) */
+
+/***/ },
+/* 49 */
+/***/ function(module, exports) {
+
+ (function(self) {
+ 'use strict';
+
+ if (self.fetch) {
+ return
+ }
+
+ var support = {
+ searchParams: 'URLSearchParams' in self,
+ iterable: 'Symbol' in self && 'iterator' in Symbol,
+ blob: 'FileReader' in self && 'Blob' in self && (function() {
+ try {
+ new Blob()
+ return true
+ } catch(e) {
+ return false
+ }
+ })(),
+ formData: 'FormData' in self,
+ arrayBuffer: 'ArrayBuffer' in self
+ }
+
+ function normalizeName(name) {
+ if (typeof name !== 'string') {
+ name = String(name)
+ }
+ if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
+ throw new TypeError('Invalid character in header field name')
+ }
+ return name.toLowerCase()
+ }
+
+ function normalizeValue(value) {
+ if (typeof value !== 'string') {
+ value = String(value)
+ }
+ return value
+ }
+
+ // Build a destructive iterator for the value list
+ function iteratorFor(items) {
+ var iterator = {
+ next: function() {
+ var value = items.shift()
+ return {done: value === undefined, value: value}
+ }
+ }
+
+ if (support.iterable) {
+ iterator[Symbol.iterator] = function() {
+ return iterator
+ }
+ }
+
+ return iterator
+ }
+
+ function Headers(headers) {
+ this.map = {}
+
+ if (headers instanceof Headers) {
+ headers.forEach(function(value, name) {
+ this.append(name, value)
+ }, this)
+
+ } else if (headers) {
+ Object.getOwnPropertyNames(headers).forEach(function(name) {
+ this.append(name, headers[name])
+ }, this)
+ }
+ }
+
+ Headers.prototype.append = function(name, value) {
+ name = normalizeName(name)
+ value = normalizeValue(value)
+ var list = this.map[name]
+ if (!list) {
+ list = []
+ this.map[name] = list
+ }
+ list.push(value)
+ }
+
+ Headers.prototype['delete'] = function(name) {
+ delete this.map[normalizeName(name)]
+ }
+
+ Headers.prototype.get = function(name) {
+ var values = this.map[normalizeName(name)]
+ return values ? values[0] : null
+ }
+
+ Headers.prototype.getAll = function(name) {
+ return this.map[normalizeName(name)] || []
+ }
+
+ Headers.prototype.has = function(name) {
+ return this.map.hasOwnProperty(normalizeName(name))
+ }
+
+ Headers.prototype.set = function(name, value) {
+ this.map[normalizeName(name)] = [normalizeValue(value)]
+ }
+
+ Headers.prototype.forEach = function(callback, thisArg) {
+ Object.getOwnPropertyNames(this.map).forEach(function(name) {
+ this.map[name].forEach(function(value) {
+ callback.call(thisArg, value, name, this)
+ }, this)
+ }, this)
+ }
+
+ Headers.prototype.keys = function() {
+ var items = []
+ this.forEach(function(value, name) { items.push(name) })
+ return iteratorFor(items)
+ }
+
+ Headers.prototype.values = function() {
+ var items = []
+ this.forEach(function(value) { items.push(value) })
+ return iteratorFor(items)
+ }
+
+ Headers.prototype.entries = function() {
+ var items = []
+ this.forEach(function(value, name) { items.push([name, value]) })
+ return iteratorFor(items)
+ }
+
+ if (support.iterable) {
+ Headers.prototype[Symbol.iterator] = Headers.prototype.entries
+ }
+
+ function consumed(body) {
+ if (body.bodyUsed) {
+ return Promise.reject(new TypeError('Already read'))
+ }
+ body.bodyUsed = true
+ }
+
+ function fileReaderReady(reader) {
+ return new Promise(function(resolve, reject) {
+ reader.onload = function() {
+ resolve(reader.result)
+ }
+ reader.onerror = function() {
+ reject(reader.error)
+ }
+ })
+ }
+
+ function readBlobAsArrayBuffer(blob) {
+ var reader = new FileReader()
+ reader.readAsArrayBuffer(blob)
+ return fileReaderReady(reader)
+ }
+
+ function readBlobAsText(blob) {
+ var reader = new FileReader()
+ reader.readAsText(blob)
+ return fileReaderReady(reader)
+ }
+
+ function Body() {
+ this.bodyUsed = false
+
+ this._initBody = function(body) {
+ this._bodyInit = body
+ if (typeof body === 'string') {
+ this._bodyText = body
+ } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
+ this._bodyBlob = body
+ } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
+ this._bodyFormData = body
+ } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
+ this._bodyText = body.toString()
+ } else if (!body) {
+ this._bodyText = ''
+ } else if (support.arrayBuffer && ArrayBuffer.prototype.isPrototypeOf(body)) {
+ // Only support ArrayBuffers for POST method.
+ // Receiving ArrayBuffers happens via Blobs, instead.
+ } else {
+ throw new Error('unsupported BodyInit type')
+ }
+
+ if (!this.headers.get('content-type')) {
+ if (typeof body === 'string') {
+ this.headers.set('content-type', 'text/plain;charset=UTF-8')
+ } else if (this._bodyBlob && this._bodyBlob.type) {
+ this.headers.set('content-type', this._bodyBlob.type)
+ } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
+ this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
+ }
+ }
+ }
+
+ if (support.blob) {
+ this.blob = function() {
+ var rejected = consumed(this)
+ if (rejected) {
+ return rejected
+ }
+
+ if (this._bodyBlob) {
+ return Promise.resolve(this._bodyBlob)
+ } else if (this._bodyFormData) {
+ throw new Error('could not read FormData body as blob')
+ } else {
+ return Promise.resolve(new Blob([this._bodyText]))
+ }
+ }
+
+ this.arrayBuffer = function() {
+ return this.blob().then(readBlobAsArrayBuffer)
+ }
+
+ this.text = function() {
+ var rejected = consumed(this)
+ if (rejected) {
+ return rejected
+ }
+
+ if (this._bodyBlob) {
+ return readBlobAsText(this._bodyBlob)
+ } else if (this._bodyFormData) {
+ throw new Error('could not read FormData body as text')
+ } else {
+ return Promise.resolve(this._bodyText)
+ }
+ }
+ } else {
+ this.text = function() {
+ var rejected = consumed(this)
+ return rejected ? rejected : Promise.resolve(this._bodyText)
+ }
+ }
+
+ if (support.formData) {
+ this.formData = function() {
+ return this.text().then(decode)
+ }
+ }
+
+ this.json = function() {
+ return this.text().then(JSON.parse)
+ }
+
+ return this
+ }
+
+ // HTTP methods whose capitalization should be normalized
+ var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']
+
+ function normalizeMethod(method) {
+ var upcased = method.toUpperCase()
+ return (methods.indexOf(upcased) > -1) ? upcased : method
+ }
+
+ function Request(input, options) {
+ options = options || {}
+ var body = options.body
+ if (Request.prototype.isPrototypeOf(input)) {
+ if (input.bodyUsed) {
+ throw new TypeError('Already read')
+ }
+ this.url = input.url
+ this.credentials = input.credentials
+ if (!options.headers) {
+ this.headers = new Headers(input.headers)
+ }
+ this.method = input.method
+ this.mode = input.mode
+ if (!body) {
+ body = input._bodyInit
+ input.bodyUsed = true
+ }
+ } else {
+ this.url = input
+ }
+
+ this.credentials = options.credentials || this.credentials || 'omit'
+ if (options.headers || !this.headers) {
+ this.headers = new Headers(options.headers)
+ }
+ this.method = normalizeMethod(options.method || this.method || 'GET')
+ this.mode = options.mode || this.mode || null
+ this.referrer = null
+
+ if ((this.method === 'GET' || this.method === 'HEAD') && body) {
+ throw new TypeError('Body not allowed for GET or HEAD requests')
+ }
+ this._initBody(body)
+ }
+
+ Request.prototype.clone = function() {
+ return new Request(this)
+ }
+
+ function decode(body) {
+ var form = new FormData()
+ body.trim().split('&').forEach(function(bytes) {
+ if (bytes) {
+ var split = bytes.split('=')
+ var name = split.shift().replace(/\+/g, ' ')
+ var value = split.join('=').replace(/\+/g, ' ')
+ form.append(decodeURIComponent(name), decodeURIComponent(value))
+ }
+ })
+ return form
+ }
+
+ function headers(xhr) {
+ var head = new Headers()
+ var pairs = (xhr.getAllResponseHeaders() || '').trim().split('\n')
+ pairs.forEach(function(header) {
+ var split = header.trim().split(':')
+ var key = split.shift().trim()
+ var value = split.join(':').trim()
+ head.append(key, value)
+ })
+ return head
+ }
+
+ Body.call(Request.prototype)
+
+ function Response(bodyInit, options) {
+ if (!options) {
+ options = {}
+ }
+
+ this.type = 'default'
+ this.status = options.status
+ this.ok = this.status >= 200 && this.status < 300
+ this.statusText = options.statusText
+ this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
+ this.url = options.url || ''
+ this._initBody(bodyInit)
+ }
+
+ Body.call(Response.prototype)
+
+ Response.prototype.clone = function() {
+ return new Response(this._bodyInit, {
+ status: this.status,
+ statusText: this.statusText,
+ headers: new Headers(this.headers),
+ url: this.url
+ })
+ }
+
+ Response.error = function() {
+ var response = new Response(null, {status: 0, statusText: ''})
+ response.type = 'error'
+ return response
+ }
+
+ var redirectStatuses = [301, 302, 303, 307, 308]
+
+ Response.redirect = function(url, status) {
+ if (redirectStatuses.indexOf(status) === -1) {
+ throw new RangeError('Invalid status code')
+ }
+
+ return new Response(null, {status: status, headers: {location: url}})
+ }
+
+ self.Headers = Headers
+ self.Request = Request
+ self.Response = Response
+
+ self.fetch = function(input, init) {
+ return new Promise(function(resolve, reject) {
+ var request
+ if (Request.prototype.isPrototypeOf(input) && !init) {
+ request = input
+ } else {
+ request = new Request(input, init)
+ }
+
+ var xhr = new XMLHttpRequest()
+
+ function responseURL() {
+ if ('responseURL' in xhr) {
+ return xhr.responseURL
+ }
+
+ // Avoid security warnings on getResponseHeader when not allowed by CORS
+ if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
+ return xhr.getResponseHeader('X-Request-URL')
+ }
+
+ return
+ }
+
+ xhr.onload = function() {
+ var options = {
+ status: xhr.status,
+ statusText: xhr.statusText,
+ headers: headers(xhr),
+ url: responseURL()
+ }
+ var body = 'response' in xhr ? xhr.response : xhr.responseText
+ resolve(new Response(body, options))
+ }
+
+ xhr.onerror = function() {
+ reject(new TypeError('Network request failed'))
+ }
+
+ xhr.ontimeout = function() {
+ reject(new TypeError('Network request failed'))
+ }
+
+ xhr.open(request.method, request.url, true)
+
+ if (request.credentials === 'include') {
+ xhr.withCredentials = true
+ }
+
+ if ('responseType' in xhr && support.blob) {
+ xhr.responseType = 'blob'
+ }
+
+ request.headers.forEach(function(value, name) {
+ xhr.setRequestHeader(name, value)
+ })
+
+ xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
+ })
+ }
+ self.fetch.polyfill = true
+ })(typeof self !== 'undefined' ? self : this);
+
+
+/***/ },
+/* 50 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(a){if("function"==="function"&&__webpack_require__(51)&&__webpack_require__(51).jQuery){!(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(52)], __WEBPACK_AMD_DEFINE_FACTORY__ = (a), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__))}else{if(typeof module!=="undefined"&&module.exports){a(__webpack_require__(52))}else{a(jQuery)}}}(function(f){var y="1.6.15",p="left",o="right",e="up",x="down",c="in",A="out",m="none",s="auto",l="swipe",t="pinch",B="tap",j="doubletap",b="longtap",z="hold",E="horizontal",u="vertical",i="all",r=10,g="start",k="move",h="end",q="cancel",a="ontouchstart" in window,v=window.navigator.msPointerEnabled&&!window.navigator.pointerEnabled&&!a,d=(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&!a,C="TouchSwipe";var n={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,hold:null,triggerOnTouchEnd:true,triggerOnTouchLeave:false,allowPageScroll:"auto",fallbackToMouseEvents:true,excludedElements:"label, button, input, select, textarea, a, .noSwipe",preventDefaultEvents:true};f.fn.swipe=function(H){var G=f(this),F=G.data(C);if(F&&typeof H==="string"){if(F[H]){return F[H].apply(this,Array.prototype.slice.call(arguments,1))}else{f.error("Method "+H+" does not exist on jQuery.swipe")}}else{if(F&&typeof H==="object"){F.option.apply(this,arguments)}else{if(!F&&(typeof H==="object"||!H)){return w.apply(this,arguments)}}}return G};f.fn.swipe.version=y;f.fn.swipe.defaults=n;f.fn.swipe.phases={PHASE_START:g,PHASE_MOVE:k,PHASE_END:h,PHASE_CANCEL:q};f.fn.swipe.directions={LEFT:p,RIGHT:o,UP:e,DOWN:x,IN:c,OUT:A};f.fn.swipe.pageScroll={NONE:m,HORIZONTAL:E,VERTICAL:u,AUTO:s};f.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,FOUR:4,FIVE:5,ALL:i};function w(F){if(F&&(F.allowPageScroll===undefined&&(F.swipe!==undefined||F.swipeStatus!==undefined))){F.allowPageScroll=m}if(F.click!==undefined&&F.tap===undefined){F.tap=F.click}if(!F){F={}}F=f.extend({},f.fn.swipe.defaults,F);return this.each(function(){var H=f(this);var G=H.data(C);if(!G){G=new D(this,F);H.data(C,G)}})}function D(a5,au){var au=f.extend({},au);var az=(a||d||!au.fallbackToMouseEvents),K=az?(d?(v?"MSPointerDown":"pointerdown"):"touchstart"):"mousedown",ax=az?(d?(v?"MSPointerMove":"pointermove"):"touchmove"):"mousemove",V=az?(d?(v?"MSPointerUp":"pointerup"):"touchend"):"mouseup",T=az?(d?"mouseleave":null):"mouseleave",aD=(d?(v?"MSPointerCancel":"pointercancel"):"touchcancel");var ag=0,aP=null,a2=null,ac=0,a1=0,aZ=0,H=1,ap=0,aJ=0,N=null;var aR=f(a5);var aa="start";var X=0;var aQ={};var U=0,a3=0,a6=0,ay=0,O=0;var aW=null,af=null;try{aR.bind(K,aN);aR.bind(aD,ba)}catch(aj){f.error("events not supported "+K+","+aD+" on jQuery.swipe")}this.enable=function(){aR.bind(K,aN);aR.bind(aD,ba);return aR};this.disable=function(){aK();return aR};this.destroy=function(){aK();aR.data(C,null);aR=null};this.option=function(bd,bc){if(typeof bd==="object"){au=f.extend(au,bd)}else{if(au[bd]!==undefined){if(bc===undefined){return au[bd]}else{au[bd]=bc}}else{if(!bd){return au}else{f.error("Option "+bd+" does not exist on jQuery.swipe.options")}}}return null};function aN(be){if(aB()){return}if(f(be.target).closest(au.excludedElements,aR).length>0){return}var bf=be.originalEvent?be.originalEvent:be;var bd,bg=bf.touches,bc=bg?bg[0]:bf;aa=g;if(bg){X=bg.length}else{if(au.preventDefaultEvents!==false){be.preventDefault()}}ag=0;aP=null;a2=null;aJ=null;ac=0;a1=0;aZ=0;H=1;ap=0;N=ab();S();ai(0,bc);if(!bg||(X===au.fingers||au.fingers===i)||aX()){U=ar();if(X==2){ai(1,bg[1]);a1=aZ=at(aQ[0].start,aQ[1].start)}if(au.swipeStatus||au.pinchStatus){bd=P(bf,aa)}}else{bd=false}if(bd===false){aa=q;P(bf,aa);return bd}else{if(au.hold){af=setTimeout(f.proxy(function(){aR.trigger("hold",[bf.target]);if(au.hold){bd=au.hold.call(aR,bf,bf.target)}},this),au.longTapThreshold)}an(true)}return null}function a4(bf){var bi=bf.originalEvent?bf.originalEvent:bf;if(aa===h||aa===q||al()){return}var be,bj=bi.touches,bd=bj?bj[0]:bi;var bg=aH(bd);a3=ar();if(bj){X=bj.length}if(au.hold){clearTimeout(af)}aa=k;if(X==2){if(a1==0){ai(1,bj[1]);a1=aZ=at(aQ[0].start,aQ[1].start)}else{aH(bj[1]);aZ=at(aQ[0].end,aQ[1].end);aJ=aq(aQ[0].end,aQ[1].end)}H=a8(a1,aZ);ap=Math.abs(a1-aZ)}if((X===au.fingers||au.fingers===i)||!bj||aX()){aP=aL(bg.start,bg.end);a2=aL(bg.last,bg.end);ak(bf,a2);ag=aS(bg.start,bg.end);ac=aM();aI(aP,ag);be=P(bi,aa);if(!au.triggerOnTouchEnd||au.triggerOnTouchLeave){var bc=true;if(au.triggerOnTouchLeave){var bh=aY(this);bc=F(bg.end,bh)}if(!au.triggerOnTouchEnd&&bc){aa=aC(k)}else{if(au.triggerOnTouchLeave&&!bc){aa=aC(h)}}if(aa==q||aa==h){P(bi,aa)}}}else{aa=q;P(bi,aa)}if(be===false){aa=q;P(bi,aa)}}function M(bc){var bd=bc.originalEvent?bc.originalEvent:bc,be=bd.touches;if(be){if(be.length&&!al()){G(bd);return true}else{if(be.length&&al()){return true}}}if(al()){X=ay}a3=ar();ac=aM();if(bb()||!am()){aa=q;P(bd,aa)}else{if(au.triggerOnTouchEnd||(au.triggerOnTouchEnd==false&&aa===k)){if(au.preventDefaultEvents!==false){bc.preventDefault()}aa=h;P(bd,aa)}else{if(!au.triggerOnTouchEnd&&a7()){aa=h;aF(bd,aa,B)}else{if(aa===k){aa=q;P(bd,aa)}}}}an(false);return null}function ba(){X=0;a3=0;U=0;a1=0;aZ=0;H=1;S();an(false)}function L(bc){var bd=bc.originalEvent?bc.originalEvent:bc;if(au.triggerOnTouchLeave){aa=aC(h);P(bd,aa)}}function aK(){aR.unbind(K,aN);aR.unbind(aD,ba);aR.unbind(ax,a4);aR.unbind(V,M);if(T){aR.unbind(T,L)}an(false)}function aC(bg){var bf=bg;var be=aA();var bd=am();var bc=bb();if(!be||bc){bf=q}else{if(bd&&bg==k&&(!au.triggerOnTouchEnd||au.triggerOnTouchLeave)){bf=h}else{if(!bd&&bg==h&&au.triggerOnTouchLeave){bf=q}}}return bf}function P(be,bc){var bd,bf=be.touches;if(J()||W()){bd=aF(be,bc,l)}if((Q()||aX())&&bd!==false){bd=aF(be,bc,t)}if(aG()&&bd!==false){bd=aF(be,bc,j)}else{if(ao()&&bd!==false){bd=aF(be,bc,b)}else{if(ah()&&bd!==false){bd=aF(be,bc,B)}}}if(bc===q){if(W()){bd=aF(be,bc,l)}if(aX()){bd=aF(be,bc,t)}ba(be)}if(bc===h){if(bf){if(!bf.length){ba(be)}}else{ba(be)}}return bd}function aF(bf,bc,be){var bd;if(be==l){aR.trigger("swipeStatus",[bc,aP||null,ag||0,ac||0,X,aQ,a2]);if(au.swipeStatus){bd=au.swipeStatus.call(aR,bf,bc,aP||null,ag||0,ac||0,X,aQ,a2);if(bd===false){return false}}if(bc==h&&aV()){clearTimeout(aW);clearTimeout(af);aR.trigger("swipe",[aP,ag,ac,X,aQ,a2]);if(au.swipe){bd=au.swipe.call(aR,bf,aP,ag,ac,X,aQ,a2);if(bd===false){return false}}switch(aP){case p:aR.trigger("swipeLeft",[aP,ag,ac,X,aQ,a2]);if(au.swipeLeft){bd=au.swipeLeft.call(aR,bf,aP,ag,ac,X,aQ,a2)}break;case o:aR.trigger("swipeRight",[aP,ag,ac,X,aQ,a2]);if(au.swipeRight){bd=au.swipeRight.call(aR,bf,aP,ag,ac,X,aQ,a2)}break;case e:aR.trigger("swipeUp",[aP,ag,ac,X,aQ,a2]);if(au.swipeUp){bd=au.swipeUp.call(aR,bf,aP,ag,ac,X,aQ,a2)}break;case x:aR.trigger("swipeDown",[aP,ag,ac,X,aQ,a2]);if(au.swipeDown){bd=au.swipeDown.call(aR,bf,aP,ag,ac,X,aQ,a2)}break}}}if(be==t){aR.trigger("pinchStatus",[bc,aJ||null,ap||0,ac||0,X,H,aQ]);if(au.pinchStatus){bd=au.pinchStatus.call(aR,bf,bc,aJ||null,ap||0,ac||0,X,H,aQ);if(bd===false){return false}}if(bc==h&&a9()){switch(aJ){case c:aR.trigger("pinchIn",[aJ||null,ap||0,ac||0,X,H,aQ]);if(au.pinchIn){bd=au.pinchIn.call(aR,bf,aJ||null,ap||0,ac||0,X,H,aQ)}break;case A:aR.trigger("pinchOut",[aJ||null,ap||0,ac||0,X,H,aQ]);if(au.pinchOut){bd=au.pinchOut.call(aR,bf,aJ||null,ap||0,ac||0,X,H,aQ)}break}}}if(be==B){if(bc===q||bc===h){clearTimeout(aW);clearTimeout(af);if(Z()&&!I()){O=ar();aW=setTimeout(f.proxy(function(){O=null;aR.trigger("tap",[bf.target]);if(au.tap){bd=au.tap.call(aR,bf,bf.target)}},this),au.doubleTapThreshold)}else{O=null;aR.trigger("tap",[bf.target]);if(au.tap){bd=au.tap.call(aR,bf,bf.target)}}}}else{if(be==j){if(bc===q||bc===h){clearTimeout(aW);clearTimeout(af);O=null;aR.trigger("doubletap",[bf.target]);if(au.doubleTap){bd=au.doubleTap.call(aR,bf,bf.target)}}}else{if(be==b){if(bc===q||bc===h){clearTimeout(aW);O=null;aR.trigger("longtap",[bf.target]);if(au.longTap){bd=au.longTap.call(aR,bf,bf.target)}}}}}return bd}function am(){var bc=true;if(au.threshold!==null){bc=ag>=au.threshold}return bc}function bb(){var bc=false;if(au.cancelThreshold!==null&&aP!==null){bc=(aT(aP)-ag)>=au.cancelThreshold}return bc}function ae(){if(au.pinchThreshold!==null){return ap>=au.pinchThreshold}return true}function aA(){var bc;if(au.maxTimeThreshold){if(ac>=au.maxTimeThreshold){bc=false}else{bc=true}}else{bc=true}return bc}function ak(bc,bd){if(au.preventDefaultEvents===false){return}if(au.allowPageScroll===m){bc.preventDefault()}else{var be=au.allowPageScroll===s;switch(bd){case p:if((au.swipeLeft&&be)||(!be&&au.allowPageScroll!=E)){bc.preventDefault()}break;case o:if((au.swipeRight&&be)||(!be&&au.allowPageScroll!=E)){bc.preventDefault()}break;case e:if((au.swipeUp&&be)||(!be&&au.allowPageScroll!=u)){bc.preventDefault()}break;case x:if((au.swipeDown&&be)||(!be&&au.allowPageScroll!=u)){bc.preventDefault()}break}}}function a9(){var bd=aO();var bc=Y();var be=ae();return bd&&bc&&be}function aX(){return !!(au.pinchStatus||au.pinchIn||au.pinchOut)}function Q(){return !!(a9()&&aX())}function aV(){var bf=aA();var bh=am();var be=aO();var bc=Y();var bd=bb();var bg=!bd&&bc&&be&&bh&&bf;return bg}function W(){return !!(au.swipe||au.swipeStatus||au.swipeLeft||au.swipeRight||au.swipeUp||au.swipeDown)}function J(){return !!(aV()&&W())}function aO(){return((X===au.fingers||au.fingers===i)||!a)}function Y(){return aQ[0].end.x!==0}function a7(){return !!(au.tap)}function Z(){return !!(au.doubleTap)}function aU(){return !!(au.longTap)}function R(){if(O==null){return false}var bc=ar();return(Z()&&((bc-O)<=au.doubleTapThreshold))}function I(){return R()}function aw(){return((X===1||!a)&&(isNaN(ag)||ag<au.threshold))}function a0(){return((ac>au.longTapThreshold)&&(ag<r))}function ah(){return !!(aw()&&a7())}function aG(){return !!(R()&&Z())}function ao(){return !!(a0()&&aU())}function G(bc){a6=ar();ay=bc.touches.length+1}function S(){a6=0;ay=0}function al(){var bc=false;if(a6){var bd=ar()-a6;if(bd<=au.fingerReleaseThreshold){bc=true}}return bc}function aB(){return !!(aR.data(C+"_intouch")===true)}function an(bc){if(!aR){return}if(bc===true){aR.bind(ax,a4);aR.bind(V,M);if(T){aR.bind(T,L)}}else{aR.unbind(ax,a4,false);aR.unbind(V,M,false);if(T){aR.unbind(T,L,false)}}aR.data(C+"_intouch",bc===true)}function ai(be,bc){var bd={start:{x:0,y:0},last:{x:0,y:0},end:{x:0,y:0}};bd.start.x=bd.last.x=bd.end.x=bc.pageX||bc.clientX;bd.start.y=bd.last.y=bd.end.y=bc.pageY||bc.clientY;aQ[be]=bd;return bd}function aH(bc){var be=bc.identifier!==undefined?bc.identifier:0;var bd=ad(be);if(bd===null){bd=ai(be,bc)}bd.last.x=bd.end.x;bd.last.y=bd.end.y;bd.end.x=bc.pageX||bc.clientX;bd.end.y=bc.pageY||bc.clientY;return bd}function ad(bc){return aQ[bc]||null}function aI(bc,bd){bd=Math.max(bd,aT(bc));N[bc].distance=bd}function aT(bc){if(N[bc]){return N[bc].distance}return undefined}function ab(){var bc={};bc[p]=av(p);bc[o]=av(o);bc[e]=av(e);bc[x]=av(x);return bc}function av(bc){return{direction:bc,distance:0}}function aM(){return a3-U}function at(bf,be){var bd=Math.abs(bf.x-be.x);var bc=Math.abs(bf.y-be.y);return Math.round(Math.sqrt(bd*bd+bc*bc))}function a8(bc,bd){var be=(bd/bc)*1;return be.toFixed(2)}function aq(){if(H<1){return A}else{return c}}function aS(bd,bc){return Math.round(Math.sqrt(Math.pow(bc.x-bd.x,2)+Math.pow(bc.y-bd.y,2)))}function aE(bf,bd){var bc=bf.x-bd.x;var bh=bd.y-bf.y;var be=Math.atan2(bh,bc);var bg=Math.round(be*180/Math.PI);if(bg<0){bg=360-Math.abs(bg)}return bg}function aL(bd,bc){var be=aE(bd,bc);if((be<=45)&&(be>=0)){return p}else{if((be<=360)&&(be>=315)){return p}else{if((be>=135)&&(be<=225)){return o}else{if((be>45)&&(be<135)){return x}else{return e}}}}}function ar(){var bc=new Date();return bc.getTime()}function aY(bc){bc=f(bc);var be=bc.offset();var bd={left:be.left,right:be.left+bc.outerWidth(),top:be.top,bottom:be.top+bc.outerHeight()};return bd}function F(bc,bd){return(bc.x>bd.left&&bc.x<bd.right&&bc.y>bd.top&&bc.y<bd.bottom)}}}));
+
+/***/ },
+/* 51 */
+/***/ function(module, exports) {
+
+ /* WEBPACK VAR INJECTION */(function(__webpack_amd_options__) {module.exports = __webpack_amd_options__;
+
+ /* WEBPACK VAR INJECTION */}.call(exports, {}))
+
+/***/ },
+/* 52 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*eslint-disable no-unused-vars*/
+ /*!
+ * jQuery JavaScript Library v3.1.0
+ * https://jquery.com/
+ *
+ * Includes Sizzle.js
+ * https://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2016-07-07T21:44Z
+ */
+ ( function( global, factory ) {
+
+ "use strict";
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+ // Pass this if window is not defined yet
+ } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+ // Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+ // throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+ // arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+ // enough that all such attempts are guarded in a try block.
+ "use strict";
+
+ var arr = [];
+
+ var document = window.document;
+
+ var getProto = Object.getPrototypeOf;
+
+ var slice = arr.slice;
+
+ var concat = arr.concat;
+
+ var push = arr.push;
+
+ var indexOf = arr.indexOf;
+
+ var class2type = {};
+
+ var toString = class2type.toString;
+
+ var hasOwn = class2type.hasOwnProperty;
+
+ var fnToString = hasOwn.toString;
+
+ var ObjectFunctionString = fnToString.call( Object );
+
+ var support = {};
+
+
+
+ function DOMEval( code, doc ) {
+ doc = doc || document;
+
+ var script = doc.createElement( "script" );
+
+ script.text = code;
+ doc.head.appendChild( script ).parentNode.removeChild( script );
+ }
+ /* global Symbol */
+ // Defining this global in .eslintrc would create a danger of using the global
+ // unguarded in another place, it seems safer to define global only for this module
+
+
+
+ var
+ version = "3.1.0",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android <=4.0 only
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([a-z])/g,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+ jQuery.fn = jQuery.prototype = {
+
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num != null ?
+
+ // Return just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ each: function( callback ) {
+ return jQuery.each( this, callback );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map( this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ } ) );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor();
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: arr.sort,
+ splice: arr.splice
+ };
+
+ jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[ 0 ] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+ target = {};
+ }
+
+ // Extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+
+ // Only deal with non-null/undefined values
+ if ( ( options = arguments[ i ] ) != null ) {
+
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+ ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
+
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray( src ) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject( src ) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+ };
+
+ jQuery.extend( {
+
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ isFunction: function( obj ) {
+ return jQuery.type( obj ) === "function";
+ },
+
+ isArray: Array.isArray,
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+
+ // As of jQuery 3.0, isNumeric is limited to
+ // strings and numbers (primitives or objects)
+ // that can be coerced to finite numbers (gh-2662)
+ var type = jQuery.type( obj );
+ return ( type === "number" || type === "string" ) &&
+
+ // parseFloat NaNs numeric-cast false positives ("")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ !isNaN( obj - parseFloat( obj ) );
+ },
+
+ isPlainObject: function( obj ) {
+ var proto, Ctor;
+
+ // Detect obvious negatives
+ // Use toString instead of jQuery.type to catch host objects
+ if ( !obj || toString.call( obj ) !== "[object Object]" ) {
+ return false;
+ }
+
+ proto = getProto( obj );
+
+ // Objects with no prototype (e.g., `Object.create( null )`) are plain
+ if ( !proto ) {
+ return true;
+ }
+
+ // Objects with prototype are plain iff they were constructed by a global Object function
+ Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
+ return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
+ },
+
+ isEmptyObject: function( obj ) {
+
+ /* eslint-disable no-unused-vars */
+ // See https://github.com/eslint/eslint/issues/6125
+ var name;
+
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+
+ // Support: Android <=2.3 only (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call( obj ) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ globalEval: function( code ) {
+ DOMEval( code );
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ each: function( obj, callback ) {
+ var length, i = 0;
+
+ if ( isArrayLike( obj ) ) {
+ length = obj.length;
+ for ( ; i < length; i++ ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android <=4.0 only
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArrayLike( Object( arr ) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
+ },
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var length, value,
+ i = 0,
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArrayLike( elems ) ) {
+ length = elems.length;
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: Date.now,
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+ } );
+
+ if ( typeof Symbol === "function" ) {
+ jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+ }
+
+ // Populate the class2type map
+ jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+ function( i, name ) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+ } );
+
+ function isArrayLike( obj ) {
+
+ // Support: real iOS 8.2 only (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = !!obj && "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+ }
+ var Sizzle =
+ /*!
+ * Sizzle CSS Selector Engine v2.3.0
+ * https://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-01-04
+ */
+ (function( window ) {
+
+ var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // https://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+
+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + identifier + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + identifier + ")" ),
+ "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+ "TAG": new RegExp( "^(" + identifier + "|[*])" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+
+ // CSS escapes
+ // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // CSS string/identifier serialization
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
+ rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,
+ fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ },
+
+ disabledAncestor = addCombinator(
+ function( elem ) {
+ return elem.disabled === true;
+ },
+ { dir: "parentNode", next: "legend" }
+ );
+
+ // Optimize for push.apply( _, NodeList )
+ try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+ } catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+ }
+
+ function Sizzle( selector, context, results, seed ) {
+ var m, i, elem, nid, match, groups, newSelector,
+ newContext = context && context.ownerDocument,
+
+ // nodeType defaults to 9, since context defaults to document
+ nodeType = context ? context.nodeType : 9;
+
+ results = results || [];
+
+ // Return early from calls with invalid selector or context
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ // Try to shortcut find operations (as opposed to filters) in HTML documents
+ if ( !seed ) {
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+ context = context || document;
+
+ if ( documentIsHTML ) {
+
+ // If the selector is sufficiently simple, try using a "get*By*" DOM method
+ // (excepting DocumentFragment context, where the methods don't exist)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+ // ID selector
+ if ( (m = match[1]) ) {
+
+ // Document context
+ if ( nodeType === 9 ) {
+ if ( (elem = context.getElementById( m )) ) {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+
+ // Element context
+ } else {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( newContext && (elem = newContext.getElementById( m )) &&
+ contains( context, elem ) &&
+ elem.id === m ) {
+
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Type selector
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Class selector
+ } else if ( (m = match[3]) && support.getElementsByClassName &&
+ context.getElementsByClassName ) {
+
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // Take advantage of querySelectorAll
+ if ( support.qsa &&
+ !compilerCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+ if ( nodeType !== 1 ) {
+ newContext = context;
+ newSelector = selector;
+
+ // qSA looks outside Element context, which is not what we want
+ // Thanks to Andrew Dupont for this workaround technique
+ // Support: IE <=8
+ // Exclude object elements
+ } else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+ // Capture the context ID, setting it first if necessary
+ if ( (nid = context.getAttribute( "id" )) ) {
+ nid = nid.replace( rcssescape, fcssescape );
+ } else {
+ context.setAttribute( "id", (nid = expando) );
+ }
+
+ // Prefix every selector in the list
+ groups = tokenize( selector );
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = "#" + nid + " " + toSelector( groups[i] );
+ }
+ newSelector = groups.join( "," );
+
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ } finally {
+ if ( nid === expando ) {
+ context.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+ }
+
+ /**
+ * Create key-value caches of limited size
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+ function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+ }
+
+ /**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+ function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+ }
+
+ /**
+ * Support testing using an element
+ * @param {Function} fn Passed the created element and returns a boolean result
+ */
+ function assert( fn ) {
+ var el = document.createElement("fieldset");
+
+ try {
+ return !!fn( el );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( el.parentNode ) {
+ el.parentNode.removeChild( el );
+ }
+ // release memory in IE
+ el = null;
+ }
+ }
+
+ /**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+ function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = arr.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+ }
+
+ /**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+ function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ a.sourceIndex - b.sourceIndex;
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+ }
+
+ /**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+ function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+ }
+
+ /**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+ function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+ }
+
+ /**
+ * Returns a function to use in pseudos for :enabled/:disabled
+ * @param {Boolean} disabled true for :disabled; false for :enabled
+ */
+ function createDisabledPseudo( disabled ) {
+ // Known :disabled false positives:
+ // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset)
+ // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
+ return function( elem ) {
+
+ // Check form elements and option elements for explicit disabling
+ return "label" in elem && elem.disabled === disabled ||
+ "form" in elem && elem.disabled === disabled ||
+
+ // Check non-disabled form elements for fieldset[disabled] ancestors
+ "form" in elem && elem.disabled === false && (
+ // Support: IE6-11+
+ // Ancestry is covered for us
+ elem.isDisabled === disabled ||
+
+ // Otherwise, assume any non-<option> under fieldset[disabled] is disabled
+ /* jshint -W018 */
+ elem.isDisabled !== !disabled &&
+ ("label" in elem || !disabledAncestor( elem )) !== disabled
+ );
+ };
+ }
+
+ /**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+ function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+ }
+
+ /**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+ function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+ }
+
+ // Expose support vars for convenience
+ support = Sizzle.support = {};
+
+ /**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+ isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+ };
+
+ /**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+ setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, subWindow,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // Return early if doc is invalid or already selected
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Update global variables
+ document = doc;
+ docElem = document.documentElement;
+ documentIsHTML = !isXML( document );
+
+ // Support: IE 9-11, Edge
+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+ if ( preferredDoc !== document &&
+ (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
+
+ // Support: IE 11, Edge
+ if ( subWindow.addEventListener ) {
+ subWindow.addEventListener( "unload", unloadHandler, false );
+
+ // Support: IE 9 - 10 only
+ } else if ( subWindow.attachEvent ) {
+ subWindow.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( el ) {
+ el.className = "i";
+ return !el.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( el ) {
+ el.appendChild( document.createComment("") );
+ return !el.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programmatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( el ) {
+ docElem.appendChild( el ).id = expando;
+ return !document.getElementsByName || !document.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var m = context.getElementById( id );
+ return m ? [ m ] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" &&
+ elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See https://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( el ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // https://bugs.jquery.com/ticket/12359
+ docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\r\\' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( el.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !el.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !el.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibling-combinator selector` fails
+ if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( el ) {
+ el.innerHTML = "<a href='' disabled='disabled'></a>" +
+ "<select disabled='disabled'><option/></select>";
+
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = document.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ el.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( el.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( el.querySelectorAll(":enabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Support: IE9-11+
+ // IE's :disabled selector does not pick up the children of disabled fieldsets
+ docElem.appendChild( el ).disabled = true;
+ if ( el.querySelectorAll(":disabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ el.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( el ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( el, "*" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( el, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully self-exclusive
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === document ? -1 :
+ b === document ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return document;
+ };
+
+ Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+ };
+
+ Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ !compilerCache[ expr + " " ] &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+ };
+
+ Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+ };
+
+ Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+ };
+
+ Sizzle.escape = function( sel ) {
+ return (sel + "").replace( rcssescape, fcssescape );
+ };
+
+ Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+ };
+
+ /**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+ Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+ };
+
+ /**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+ getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+ };
+
+ Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, uniqueCache, outerCache, node, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType,
+ diff = false;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) {
+
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+
+ // Seek `elem` from a previously-cached index
+
+ // ...in a gzip-friendly way
+ node = parent;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex && cache[ 2 ];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ } else {
+ // Use previously-cached element index if available
+ if ( useCache ) {
+ // ...in a gzip-friendly way
+ node = elem;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex;
+ }
+
+ // xml :nth-child(...)
+ // or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ if ( diff === false ) {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) &&
+ ++diff ) {
+
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ uniqueCache[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": createDisabledPseudo( false ),
+ "disabled": createDisabledPseudo( true ),
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+ };
+
+ Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+ // Add button/input type pseudos
+ for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+ }
+ for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+ }
+
+ // Easy API for creating new setFilters
+ function setFilters() {}
+ setFilters.prototype = Expr.filters = Expr.pseudos;
+ Expr.setFilters = new setFilters();
+
+ tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+ };
+
+ function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+ }
+
+ function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ skip = combinator.next,
+ key = skip || dir,
+ checkNonElements = base && key === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, uniqueCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+ if ( skip && skip === elem.nodeName.toLowerCase() ) {
+ elem = elem[ dir ] || elem;
+ } else if ( (oldCache = uniqueCache[ key ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ uniqueCache[ key ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+
+ function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+ }
+
+ function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+ }
+
+ function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+ }
+
+ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+ }
+
+ function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+ }
+
+ function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context === document || context || outermost;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ if ( !context && elem.ownerDocument !== document ) {
+ setDocument( elem );
+ xml = !documentIsHTML;
+ }
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context || document, xml) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // `i` is now the count of elements visited above, and adding it to `matchedCount`
+ // makes the latter nonnegative.
+ matchedCount += i;
+
+ // Apply set filters to unmatched elements
+ // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+ // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+ // no element matchers and no seed.
+ // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+ // case, which will result in a "00" `matchedCount` that differs from `i` but is also
+ // numerically zero.
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+ }
+
+ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+ };
+
+ /**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+ select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is only one selector in the list and no seed
+ // (the latter of which guarantees us context)
+ if ( match.length === 1 ) {
+
+ // Reduce context if the leading compound selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+ };
+
+ // One-time assignments
+
+ // Sort stability
+ support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+ // Support: Chrome 14-35+
+ // Always assume duplicates if they aren't passed to the comparison function
+ support.detectDuplicates = !!hasDuplicate;
+
+ // Initialize against the default document
+ setDocument();
+
+ // Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+ // Detached nodes confoundingly follow *each other*
+ support.sortDetached = assert(function( el ) {
+ // Should return 1, but returns 4 (following)
+ return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
+ });
+
+ // Support: IE<8
+ // Prevent attribute/property "interpolation"
+ // https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+ if ( !assert(function( el ) {
+ el.innerHTML = "<a href='#'></a>";
+ return el.firstChild.getAttribute("href") === "#" ;
+ }) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+ }
+
+ // Support: IE<9
+ // Use defaultValue in place of getAttribute("value")
+ if ( !support.attributes || !assert(function( el ) {
+ el.innerHTML = "<input/>";
+ el.firstChild.setAttribute( "value", "" );
+ return el.firstChild.getAttribute( "value" ) === "";
+ }) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+ }
+
+ // Support: IE<9
+ // Use getAttributeNode to fetch booleans when getAttribute lies
+ if ( !assert(function( el ) {
+ return el.getAttribute("disabled") == null;
+ }) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+ }
+
+ return Sizzle;
+
+ })( window );
+
+
+
+ jQuery.find = Sizzle;
+ jQuery.expr = Sizzle.selectors;
+
+ // Deprecated
+ jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+ jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
+ jQuery.text = Sizzle.getText;
+ jQuery.isXMLDoc = Sizzle.isXML;
+ jQuery.contains = Sizzle.contains;
+ jQuery.escapeSelector = Sizzle.escape;
+
+
+
+
+ var dir = function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+ };
+
+
+ var siblings = function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+ };
+
+
+ var rneedsContext = jQuery.expr.match.needsContext;
+
+ var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
+
+
+
+ var risSimple = /^.[^:#\[\.,]*$/;
+
+ // Implement the identical functionality for filter and not
+ function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ return !!qualifier.call( elem, i, elem ) !== not;
+ } );
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ } );
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
+ } );
+ }
+
+ jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ } ) );
+ };
+
+ jQuery.fn.extend( {
+ find: function( selector ) {
+ var i, ret,
+ len = this.length,
+ self = this;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter( function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ } ) );
+ }
+
+ ret = this.pushStack( [] );
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ return len > 1 ? jQuery.uniqueSort( ret ) : ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], false ) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], true ) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+ } );
+
+
+ // Initialize a jQuery object
+
+
+ // A central reference to the root jQuery(document)
+ var rootjQuery,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ // Shortcut simple #id case for speed
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
+
+ init = jQuery.fn.init = function( selector, context, root ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Method init() accepts an alternate rootjQuery
+ // so migrate can support jQuery.sub (gh-2101)
+ root = root || rootjQuery;
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector[ 0 ] === "<" &&
+ selector[ selector.length - 1 ] === ">" &&
+ selector.length >= 3 ) {
+
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && ( match[ 1 ] || !context ) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[ 1 ] ) {
+ context = context instanceof jQuery ? context[ 0 ] : context;
+
+ // Option to run scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[ 1 ],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[ 2 ] );
+
+ if ( elem ) {
+
+ // Inject the element directly into the jQuery object
+ this[ 0 ] = elem;
+ this.length = 1;
+ }
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || root ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this[ 0 ] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return root.ready !== undefined ?
+ root.ready( selector ) :
+
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+ // Give the init function the jQuery prototype for later instantiation
+ init.prototype = jQuery.fn;
+
+ // Initialize central reference
+ rootjQuery = jQuery( document );
+
+
+ var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+
+ // Methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+ jQuery.fn.extend( {
+ has: function( target ) {
+ var targets = jQuery( target, this ),
+ l = targets.length;
+
+ return this.filter( function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[ i ] ) ) {
+ return true;
+ }
+ }
+ } );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ targets = typeof selectors !== "string" && jQuery( selectors );
+
+ // Positional selectors never match, since there's no _selection_ context
+ if ( !rneedsContext.test( selectors ) ) {
+ for ( ; i < l; i++ ) {
+ for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
+
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && ( targets ?
+ targets.index( cur ) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector( cur, selectors ) ) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
+ },
+
+ // Determine the position of an element within the set
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // Index in selector
+ if ( typeof elem === "string" ) {
+ return indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.uniqueSort(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter( selector )
+ );
+ }
+ } );
+
+ function sibling( cur, dir ) {
+ while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
+ return cur;
+ }
+
+ jQuery.each( {
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return siblings( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return siblings( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+ }
+ }, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var matched = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ matched = jQuery.filter( selector, matched );
+ }
+
+ if ( this.length > 1 ) {
+
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ jQuery.uniqueSort( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+ } );
+ var rnotwhite = ( /\S+/g );
+
+
+
+ // Convert String-formatted options into Object-formatted ones
+ function createOptions( options ) {
+ var object = {};
+ jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ } );
+ return object;
+ }
+
+ /*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+ jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ createOptions( options ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+
+ // Last fire value for non-forgettable lists
+ memory,
+
+ // Flag to know if list was already fired
+ fired,
+
+ // Flag to prevent firing
+ locked,
+
+ // Actual callback list
+ list = [],
+
+ // Queue of execution data for repeatable lists
+ queue = [],
+
+ // Index of currently firing callback (modified by add/remove as needed)
+ firingIndex = -1,
+
+ // Fire callbacks
+ fire = function() {
+
+ // Enforce single-firing
+ locked = options.once;
+
+ // Execute callbacks for all pending executions,
+ // respecting firingIndex overrides and runtime changes
+ fired = firing = true;
+ for ( ; queue.length; firingIndex = -1 ) {
+ memory = queue.shift();
+ while ( ++firingIndex < list.length ) {
+
+ // Run callback and check for early termination
+ if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+ options.stopOnFalse ) {
+
+ // Jump to end and forget the data so .add doesn't re-fire
+ firingIndex = list.length;
+ memory = false;
+ }
+ }
+ }
+
+ // Forget the data if we're done with it
+ if ( !options.memory ) {
+ memory = false;
+ }
+
+ firing = false;
+
+ // Clean up if we're done firing for good
+ if ( locked ) {
+
+ // Keep an empty list if we have data for future add calls
+ if ( memory ) {
+ list = [];
+
+ // Otherwise, this object is spent
+ } else {
+ list = "";
+ }
+ }
+ },
+
+ // Actual Callbacks object
+ self = {
+
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+
+ // If we have memory from a past run, we should fire after adding
+ if ( memory && !firing ) {
+ firingIndex = list.length - 1;
+ queue.push( memory );
+ }
+
+ ( function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ if ( jQuery.isFunction( arg ) ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
+ // Inspect recursively
+ add( arg );
+ }
+ } );
+ } )( arguments );
+
+ if ( memory && !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Remove a callback from the list
+ remove: function() {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+
+ // Handle firing indexes
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ } );
+ return this;
+ },
+
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ?
+ jQuery.inArray( fn, list ) > -1 :
+ list.length > 0;
+ },
+
+ // Remove all callbacks from the list
+ empty: function() {
+ if ( list ) {
+ list = [];
+ }
+ return this;
+ },
+
+ // Disable .fire and .add
+ // Abort any current/pending executions
+ // Clear all callbacks and values
+ disable: function() {
+ locked = queue = [];
+ list = memory = "";
+ return this;
+ },
+ disabled: function() {
+ return !list;
+ },
+
+ // Disable .fire
+ // Also disable .add unless we have memory (since it would have no effect)
+ // Abort any pending executions
+ lock: function() {
+ locked = queue = [];
+ if ( !memory && !firing ) {
+ list = memory = "";
+ }
+ return this;
+ },
+ locked: function() {
+ return !!locked;
+ },
+
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( !locked ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ queue.push( args );
+ if ( !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+ };
+
+
+ function Identity( v ) {
+ return v;
+ }
+ function Thrower( ex ) {
+ throw ex;
+ }
+
+ function adoptValue( value, resolve, reject ) {
+ var method;
+
+ try {
+
+ // Check for promise aspect first to privilege synchronous behavior
+ if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
+ method.call( value ).done( resolve ).fail( reject );
+
+ // Other thenables
+ } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
+ method.call( value, resolve, reject );
+
+ // Other non-thenables
+ } else {
+
+ // Support: Android 4.0 only
+ // Strict mode functions invoked without .call/.apply get global-object context
+ resolve.call( undefined, value );
+ }
+
+ // For Promises/A+, convert exceptions into rejections
+ // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
+ // Deferred#then to conditionally suppress rejection.
+ } catch ( value ) {
+
+ // Support: Android 4.0 only
+ // Strict mode functions invoked without .call/.apply get global-object context
+ reject.call( undefined, value );
+ }
+ }
+
+ jQuery.extend( {
+
+ Deferred: function( func ) {
+ var tuples = [
+
+ // action, add listener, callbacks,
+ // ... .then handlers, argument index, [final state]
+ [ "notify", "progress", jQuery.Callbacks( "memory" ),
+ jQuery.Callbacks( "memory" ), 2 ],
+ [ "resolve", "done", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 0, "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 1, "rejected" ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ "catch": function( fn ) {
+ return promise.then( null, fn );
+ },
+
+ // Keep pipe for back-compat
+ pipe: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+
+ return jQuery.Deferred( function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+
+ // Map tuples (progress, done, fail) to arguments (done, fail, progress)
+ var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
+
+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
+ // deferred.done(function() { bind to newDefer or newDefer.resolve })
+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
+ deferred[ tuple[ 1 ] ]( function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .progress( newDefer.notify )
+ .done( newDefer.resolve )
+ .fail( newDefer.reject );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ](
+ this,
+ fn ? [ returned ] : arguments
+ );
+ }
+ } );
+ } );
+ fns = null;
+ } ).promise();
+ },
+ then: function( onFulfilled, onRejected, onProgress ) {
+ var maxDepth = 0;
+ function resolve( depth, deferred, handler, special ) {
+ return function() {
+ var that = this,
+ args = arguments,
+ mightThrow = function() {
+ var returned, then;
+
+ // Support: Promises/A+ section 2.3.3.3.3
+ // https://promisesaplus.com/#point-59
+ // Ignore double-resolution attempts
+ if ( depth < maxDepth ) {
+ return;
+ }
+
+ returned = handler.apply( that, args );
+
+ // Support: Promises/A+ section 2.3.1
+ // https://promisesaplus.com/#point-48
+ if ( returned === deferred.promise() ) {
+ throw new TypeError( "Thenable self-resolution" );
+ }
+
+ // Support: Promises/A+ sections 2.3.3.1, 3.5
+ // https://promisesaplus.com/#point-54
+ // https://promisesaplus.com/#point-75
+ // Retrieve `then` only once
+ then = returned &&
+
+ // Support: Promises/A+ section 2.3.4
+ // https://promisesaplus.com/#point-64
+ // Only check objects and functions for thenability
+ ( typeof returned === "object" ||
+ typeof returned === "function" ) &&
+ returned.then;
+
+ // Handle a returned thenable
+ if ( jQuery.isFunction( then ) ) {
+
+ // Special processors (notify) just wait for resolution
+ if ( special ) {
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special )
+ );
+
+ // Normal processors (resolve) also hook into progress
+ } else {
+
+ // ...and disregard older resolution values
+ maxDepth++;
+
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special ),
+ resolve( maxDepth, deferred, Identity,
+ deferred.notifyWith )
+ );
+ }
+
+ // Handle all other returned values
+ } else {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Identity ) {
+ that = undefined;
+ args = [ returned ];
+ }
+
+ // Process the value(s)
+ // Default process is resolve
+ ( special || deferred.resolveWith )( that, args );
+ }
+ },
+
+ // Only normal processors (resolve) catch and reject exceptions
+ process = special ?
+ mightThrow :
+ function() {
+ try {
+ mightThrow();
+ } catch ( e ) {
+
+ if ( jQuery.Deferred.exceptionHook ) {
+ jQuery.Deferred.exceptionHook( e,
+ process.stackTrace );
+ }
+
+ // Support: Promises/A+ section 2.3.3.3.4.1
+ // https://promisesaplus.com/#point-61
+ // Ignore post-resolution exceptions
+ if ( depth + 1 >= maxDepth ) {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Thrower ) {
+ that = undefined;
+ args = [ e ];
+ }
+
+ deferred.rejectWith( that, args );
+ }
+ }
+ };
+
+ // Support: Promises/A+ section 2.3.3.3.1
+ // https://promisesaplus.com/#point-57
+ // Re-resolve promises immediately to dodge false rejection from
+ // subsequent errors
+ if ( depth ) {
+ process();
+ } else {
+
+ // Call an optional hook to record the stack, in case of exception
+ // since it's otherwise lost when execution goes async
+ if ( jQuery.Deferred.getStackHook ) {
+ process.stackTrace = jQuery.Deferred.getStackHook();
+ }
+ window.setTimeout( process );
+ }
+ };
+ }
+
+ return jQuery.Deferred( function( newDefer ) {
+
+ // progress_handlers.add( ... )
+ tuples[ 0 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onProgress ) ?
+ onProgress :
+ Identity,
+ newDefer.notifyWith
+ )
+ );
+
+ // fulfilled_handlers.add( ... )
+ tuples[ 1 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onFulfilled ) ?
+ onFulfilled :
+ Identity
+ )
+ );
+
+ // rejected_handlers.add( ... )
+ tuples[ 2 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onRejected ) ?
+ onRejected :
+ Thrower
+ )
+ );
+ } ).promise();
+ },
+
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 5 ];
+
+ // promise.progress = list.add
+ // promise.done = list.add
+ // promise.fail = list.add
+ promise[ tuple[ 1 ] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(
+ function() {
+
+ // state = "resolved" (i.e., fulfilled)
+ // state = "rejected"
+ state = stateString;
+ },
+
+ // rejected_callbacks.disable
+ // fulfilled_callbacks.disable
+ tuples[ 3 - i ][ 2 ].disable,
+
+ // progress_callbacks.lock
+ tuples[ 0 ][ 2 ].lock
+ );
+ }
+
+ // progress_handlers.fire
+ // fulfilled_handlers.fire
+ // rejected_handlers.fire
+ list.add( tuple[ 3 ].fire );
+
+ // deferred.notify = function() { deferred.notifyWith(...) }
+ // deferred.resolve = function() { deferred.resolveWith(...) }
+ // deferred.reject = function() { deferred.rejectWith(...) }
+ deferred[ tuple[ 0 ] ] = function() {
+ deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
+ return this;
+ };
+
+ // deferred.notifyWith = list.fireWith
+ // deferred.resolveWith = list.fireWith
+ // deferred.rejectWith = list.fireWith
+ deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
+ } );
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( singleValue ) {
+ var
+
+ // count of uncompleted subordinates
+ remaining = arguments.length,
+
+ // count of unprocessed arguments
+ i = remaining,
+
+ // subordinate fulfillment data
+ resolveContexts = Array( i ),
+ resolveValues = slice.call( arguments ),
+
+ // the master Deferred
+ master = jQuery.Deferred(),
+
+ // subordinate callback factory
+ updateFunc = function( i ) {
+ return function( value ) {
+ resolveContexts[ i ] = this;
+ resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( !( --remaining ) ) {
+ master.resolveWith( resolveContexts, resolveValues );
+ }
+ };
+ };
+
+ // Single- and empty arguments are adopted like Promise.resolve
+ if ( remaining <= 1 ) {
+ adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject );
+
+ // Use .then() to unwrap secondary thenables (cf. gh-3000)
+ if ( master.state() === "pending" ||
+ jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
+
+ return master.then();
+ }
+ }
+
+ // Multiple arguments are aggregated like Promise.all array elements
+ while ( i-- ) {
+ adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
+ }
+
+ return master.promise();
+ }
+ } );
+
+
+ // These usually indicate a programmer mistake during development,
+ // warn about them ASAP rather than swallowing them by default.
+ var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
+
+ jQuery.Deferred.exceptionHook = function( error, stack ) {
+
+ // Support: IE 8 - 9 only
+ // Console exists when dev tools are open, which can happen at any time
+ if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
+ window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
+ }
+ };
+
+
+
+
+ jQuery.readyException = function( error ) {
+ window.setTimeout( function() {
+ throw error;
+ } );
+ };
+
+
+
+
+ // The deferred used on DOM ready
+ var readyList = jQuery.Deferred();
+
+ jQuery.fn.ready = function( fn ) {
+
+ readyList
+ .then( fn )
+
+ // Wrap jQuery.readyException in a function so that the lookup
+ // happens at the time of error handling instead of callback
+ // registration.
+ .catch( function( error ) {
+ jQuery.readyException( error );
+ } );
+
+ return this;
+ };
+
+ jQuery.extend( {
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+ }
+ } );
+
+ jQuery.ready.then = readyList.then;
+
+ // The ready event handler and self cleanup method
+ function completed() {
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
+ }
+
+ // Catch cases where $(document).ready() is called
+ // after the browser event has already occurred.
+ // Support: IE <=9 - 10 only
+ // Older IE sometimes signals "interactive" too soon
+ if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
+
+ } else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+ }
+
+
+
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ len = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ access( elems, fn, i, key[ i ], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < len; i++ ) {
+ fn(
+ elems[ i ], key, raw ?
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ len ? fn( elems[ 0 ], key ) : emptyGet;
+ };
+ var acceptData = function( owner ) {
+
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+ };
+
+
+
+
+ function Data() {
+ this.expando = jQuery.expando + Data.uid++;
+ }
+
+ Data.uid = 1;
+
+ Data.prototype = {
+
+ cache: function( owner ) {
+
+ // Check if the owner object already has a cache
+ var value = owner[ this.expando ];
+
+ // If not, create one
+ if ( !value ) {
+ value = {};
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( acceptData( owner ) ) {
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable property
+ // configurable must be true to allow the property to be
+ // deleted when data is removed
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ configurable: true
+ } );
+ }
+ }
+ }
+
+ return value;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ cache = this.cache( owner );
+
+ // Handle: [ owner, key, value ] args
+ // Always use camelCase key (gh-2257)
+ if ( typeof data === "string" ) {
+ cache[ jQuery.camelCase( data ) ] = value;
+
+ // Handle: [ owner, { properties } ] args
+ } else {
+
+ // Copy the properties one-by-one to the cache object
+ for ( prop in data ) {
+ cache[ jQuery.camelCase( prop ) ] = data[ prop ];
+ }
+ }
+ return cache;
+ },
+ get: function( owner, key ) {
+ return key === undefined ?
+ this.cache( owner ) :
+
+ // Always use camelCase key (gh-2257)
+ owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
+ },
+ access: function( owner, key, value ) {
+
+ // In cases where either:
+ //
+ // 1. No key was specified
+ // 2. A string key was specified, but no value provided
+ //
+ // Take the "read" path and allow the get method to determine
+ // which value to return, respectively either:
+ //
+ // 1. The entire cache object
+ // 2. The data stored at the key
+ //
+ if ( key === undefined ||
+ ( ( key && typeof key === "string" ) && value === undefined ) ) {
+
+ return this.get( owner, key );
+ }
+
+ // When the key is not a string, or both a key and value
+ // are specified, set or extend (existing objects) with either:
+ //
+ // 1. An object of properties
+ // 2. A key and value
+ //
+ this.set( owner, key, value );
+
+ // Since the "set" path can have two possible entry points
+ // return the expected data based on which path was taken[*]
+ return value !== undefined ? value : key;
+ },
+ remove: function( owner, key ) {
+ var i,
+ cache = owner[ this.expando ];
+
+ if ( cache === undefined ) {
+ return;
+ }
+
+ if ( key !== undefined ) {
+
+ // Support array or space separated string of keys
+ if ( jQuery.isArray( key ) ) {
+
+ // If key is an array of keys...
+ // We always set camelCase keys, so remove that.
+ key = key.map( jQuery.camelCase );
+ } else {
+ key = jQuery.camelCase( key );
+
+ // If a key with the spaces exists, use it.
+ // Otherwise, create an array by matching non-whitespace
+ key = key in cache ?
+ [ key ] :
+ ( key.match( rnotwhite ) || [] );
+ }
+
+ i = key.length;
+
+ while ( i-- ) {
+ delete cache[ key[ i ] ];
+ }
+ }
+
+ // Remove the expando if there's no more data
+ if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
+
+ // Support: Chrome <=35 - 45
+ // Webkit & Blink performance suffers when deleting properties
+ // from DOM nodes, so set to undefined instead
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = undefined;
+ } else {
+ delete owner[ this.expando ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ var cache = owner[ this.expando ];
+ return cache !== undefined && !jQuery.isEmptyObject( cache );
+ }
+ };
+ var dataPriv = new Data();
+
+ var dataUser = new Data();
+
+
+
+ // Implementation Summary
+ //
+ // 1. Enforce API surface and semantic compatibility with 1.9.x branch
+ // 2. Improve the module's maintainability by reducing the storage
+ // paths to a single mechanism.
+ // 3. Use the same single mechanism to support "private" and "user" data.
+ // 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+ // 5. Avoid exposing implementation details on user objects (eg. expando properties)
+ // 6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+ var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /[A-Z]/g;
+
+ function dataAttr( elem, key, data ) {
+ var name;
+
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? JSON.parse( data ) :
+ data;
+ } catch ( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ dataUser.set( elem, key, data );
+ } else {
+ data = undefined;
+ }
+ }
+ return data;
+ }
+
+ jQuery.extend( {
+ hasData: function( elem ) {
+ return dataUser.hasData( elem ) || dataPriv.hasData( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return dataUser.access( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ dataUser.remove( elem, name );
+ },
+
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to dataPriv methods, these can be deprecated.
+ _data: function( elem, name, data ) {
+ return dataPriv.access( elem, name, data );
+ },
+
+ _removeData: function( elem, name ) {
+ dataPriv.remove( elem, name );
+ }
+ } );
+
+ jQuery.fn.extend( {
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[ 0 ],
+ attrs = elem && elem.attributes;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = dataUser.get( elem );
+
+ if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE 11 only
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice( 5 ) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ dataPriv.set( elem, "hasDataAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each( function() {
+ dataUser.set( this, key );
+ } );
+ }
+
+ return access( this, function( value ) {
+ var data;
+
+ // The calling jQuery object (element matches) is not empty
+ // (and therefore has an element appears at this[ 0 ]) and the
+ // `value` parameter was not undefined. An empty jQuery object
+ // will result in `undefined` for elem = this[ 0 ] which will
+ // throw an exception if an attempt to read a data cache is made.
+ if ( elem && value === undefined ) {
+
+ // Attempt to get data from the cache
+ // The key will always be camelCased in Data
+ data = dataUser.get( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to "discover" the data in
+ // HTML5 custom data-* attrs
+ data = dataAttr( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // We tried really hard, but the data doesn't exist.
+ return;
+ }
+
+ // Set the data...
+ this.each( function() {
+
+ // We always store the camelCased key
+ dataUser.set( this, key, value );
+ } );
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each( function() {
+ dataUser.remove( this, key );
+ } );
+ }
+ } );
+
+
+ jQuery.extend( {
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = dataPriv.get( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray( data ) ) {
+ queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // Clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // Not public - generate a queueHooks object, or return the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+ empty: jQuery.Callbacks( "once memory" ).add( function() {
+ dataPriv.remove( elem, [ type + "queue", key ] );
+ } )
+ } );
+ }
+ } );
+
+ jQuery.fn.extend( {
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[ 0 ], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each( function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // Ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ dequeue: function( type ) {
+ return this.each( function() {
+ jQuery.dequeue( this, type );
+ } );
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+ } );
+ var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+ var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
+
+ var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+ var isHiddenWithinTree = function( elem, el ) {
+
+ // isHiddenWithinTree might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+
+ // Inline style trumps all
+ return elem.style.display === "none" ||
+ elem.style.display === "" &&
+
+ // Otherwise, check computed style
+ // Support: Firefox <=43 - 45
+ // Disconnected elements can have computed display: none, so first confirm that elem is
+ // in the document.
+ jQuery.contains( elem.ownerDocument, elem ) &&
+
+ jQuery.css( elem, "display" ) === "none";
+ };
+
+ var swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ };
+
+
+
+
+ function adjustCSS( elem, prop, valueParts, tween ) {
+ var adjusted,
+ scale = 1,
+ maxIterations = 20,
+ currentValue = tween ?
+ function() {
+ return tween.cur();
+ } :
+ function() {
+ return jQuery.css( elem, prop, "" );
+ },
+ initial = currentValue(),
+ unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ rcssNum.exec( jQuery.css( elem, prop ) );
+
+ if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+ // Trust units reported by jQuery.css
+ unit = unit || initialInUnit[ 3 ];
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ initialInUnit = +initial || 1;
+
+ do {
+
+ // If previous iteration zeroed out, double until we get *something*.
+ // Use string for doubling so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ initialInUnit = initialInUnit / scale;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // Break the loop if scale is unchanged or perfect, or if we've just had enough.
+ } while (
+ scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+ );
+ }
+
+ if ( valueParts ) {
+ initialInUnit = +initialInUnit || +initial || 0;
+
+ // Apply relative offset (+=/-=) if specified
+ adjusted = valueParts[ 1 ] ?
+ initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+ +valueParts[ 2 ];
+ if ( tween ) {
+ tween.unit = unit;
+ tween.start = initialInUnit;
+ tween.end = adjusted;
+ }
+ }
+ return adjusted;
+ }
+
+
+ var defaultDisplayMap = {};
+
+ function getDefaultDisplay( elem ) {
+ var temp,
+ doc = elem.ownerDocument,
+ nodeName = elem.nodeName,
+ display = defaultDisplayMap[ nodeName ];
+
+ if ( display ) {
+ return display;
+ }
+
+ temp = doc.body.appendChild( doc.createElement( nodeName ) ),
+ display = jQuery.css( temp, "display" );
+
+ temp.parentNode.removeChild( temp );
+
+ if ( display === "none" ) {
+ display = "block";
+ }
+ defaultDisplayMap[ nodeName ] = display;
+
+ return display;
+ }
+
+ function showHide( elements, show ) {
+ var display, elem,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ // Determine new display value for elements that need to change
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ display = elem.style.display;
+ if ( show ) {
+
+ // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
+ // check is required in this first loop unless we have a nonempty display value (either
+ // inline or about-to-be-restored)
+ if ( display === "none" ) {
+ values[ index ] = dataPriv.get( elem, "display" ) || null;
+ if ( !values[ index ] ) {
+ elem.style.display = "";
+ }
+ }
+ if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
+ values[ index ] = getDefaultDisplay( elem );
+ }
+ } else {
+ if ( display !== "none" ) {
+ values[ index ] = "none";
+
+ // Remember what we're overwriting
+ dataPriv.set( elem, "display", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop to avoid constant reflow
+ for ( index = 0; index < length; index++ ) {
+ if ( values[ index ] != null ) {
+ elements[ index ].style.display = values[ index ];
+ }
+ }
+
+ return elements;
+ }
+
+ jQuery.fn.extend( {
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each( function() {
+ if ( isHiddenWithinTree( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ } );
+ }
+ } );
+ var rcheckableType = ( /^(?:checkbox|radio)$/i );
+
+ var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
+
+ var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+
+
+
+ // We have to close these tags to support XHTML (#13200)
+ var wrapMap = {
+
+ // Support: IE <=9 only
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+ // XHTML parsers do not magically insert elements in the
+ // same way that tag soup parsers do. So we cannot shorten
+ // this by omitting <tbody> or other required elements.
+ thead: [ 1, "<table>", "</table>" ],
+ col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ _default: [ 0, "", "" ]
+ };
+
+ // Support: IE <=9 only
+ wrapMap.optgroup = wrapMap.option;
+
+ wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+ wrapMap.th = wrapMap.td;
+
+
+ function getAll( context, tag ) {
+
+ // Support: IE <=9 - 11 only
+ // Use typeof to avoid zero-argument method invocation on host objects (#15151)
+ var ret = typeof context.getElementsByTagName !== "undefined" ?
+ context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== "undefined" ?
+ context.querySelectorAll( tag || "*" ) :
+ [];
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], ret ) :
+ ret;
+ }
+
+
+ // Mark scripts as having already been evaluated
+ function setGlobalEval( elems, refElements ) {
+ var i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ dataPriv.set(
+ elems[ i ],
+ "globalEval",
+ !refElements || dataPriv.get( refElements[ i ], "globalEval" )
+ );
+ }
+ }
+
+
+ var rhtml = /<|&#?\w+;/;
+
+ function buildFragment( elems, context, scripts, selection, ignored ) {
+ var elem, tmp, tag, wrap, contains, j,
+ fragment = context.createDocumentFragment(),
+ nodes = [],
+ i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Ensure the created nodes are orphaned (#12392)
+ tmp.textContent = "";
+ }
+ }
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+
+ i = 0;
+ while ( ( elem = nodes[ i++ ] ) ) {
+
+ // Skip elements already in the context collection (trac-4087)
+ if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+ if ( ignored ) {
+ ignored.push( elem );
+ }
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( fragment.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( ( elem = tmp[ j++ ] ) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ return fragment;
+ }
+
+
+ ( function() {
+ var fragment = document.createDocumentFragment(),
+ div = fragment.appendChild( document.createElement( "div" ) ),
+ input = document.createElement( "input" );
+
+ // Support: Android 4.0 - 4.3 only
+ // Check state lost if the name is set (#11217)
+ // Support: Windows Web Apps (WWA)
+ // `name` and `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "radio" );
+ input.setAttribute( "checked", "checked" );
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+
+ // Support: Android <=4.1 only
+ // Older WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE <=11 only
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+ } )();
+ var documentElement = document.documentElement;
+
+
+
+ var
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+
+ function returnTrue() {
+ return true;
+ }
+
+ function returnFalse() {
+ return false;
+ }
+
+ // Support: IE <=9 only
+ // See #13393 for more info
+ function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+ }
+
+ function on( elem, types, selector, data, fn, one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ on( elem, type, selector, data, types[ type ], one );
+ }
+ return elem;
+ }
+
+ if ( data == null && fn == null ) {
+
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return elem;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return elem.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ } );
+ }
+
+ /*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+ jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var handleObjIn, eventHandle, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.get( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Ensure that invalid selectors throw exceptions at attach time
+ // Evaluate against documentElement in case elem is a non-element node (e.g., document)
+ if ( selector ) {
+ jQuery.find.matchesSelector( documentElement, selector );
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !( events = elemData.events ) ) {
+ events = elemData.events = {};
+ }
+ if ( !( eventHandle = elemData.handle ) ) {
+ eventHandle = elemData.handle = function( e ) {
+
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
+ jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+ };
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend( {
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join( "." )
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !( handlers = events[ type ] ) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener if the special events handler returns false
+ if ( !special.setup ||
+ special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var j, origCount, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+ if ( !elemData || !( events = elemData.events ) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[ 2 ] &&
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector ||
+ selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown ||
+ special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove data and the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ dataPriv.remove( elem, "handle events" );
+ }
+ },
+
+ dispatch: function( nativeEvent ) {
+
+ // Make a writable jQuery.Event from the native event object
+ var event = jQuery.event.fix( nativeEvent );
+
+ var i, j, ret, matched, handleObj, handlerQueue,
+ args = new Array( arguments.length ),
+ handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[ 0 ] = event;
+
+ for ( i = 1; i < arguments.length; i++ ) {
+ args[ i ] = arguments[ i ];
+ }
+
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( ( handleObj = matched.handlers[ j++ ] ) &&
+ !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or 2) have namespace(s)
+ // a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
+ handleObj.handler ).apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( ( event.result = ret ) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var i, matches, sel, handleObj,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Support: IE <=9
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ //
+ // Support: Firefox <=42
+ // Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
+ if ( delegateCount && cur.nodeType &&
+ ( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
+
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) > -1 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push( { elem: cur, handlers: matches } );
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
+ }
+
+ return handlerQueue;
+ },
+
+ addProp: function( name, hook ) {
+ Object.defineProperty( jQuery.Event.prototype, name, {
+ enumerable: true,
+ configurable: true,
+
+ get: jQuery.isFunction( hook ) ?
+ function() {
+ if ( this.originalEvent ) {
+ return hook( this.originalEvent );
+ }
+ } :
+ function() {
+ if ( this.originalEvent ) {
+ return this.originalEvent[ name ];
+ }
+ },
+
+ set: function( value ) {
+ Object.defineProperty( this, name, {
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: value
+ } );
+ }
+ } );
+ },
+
+ fix: function( originalEvent ) {
+ return originalEvent[ jQuery.expando ] ?
+ originalEvent :
+ new jQuery.Event( originalEvent );
+ },
+
+ special: {
+ load: {
+
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ this.focus();
+ return false;
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return jQuery.nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined && event.originalEvent ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ }
+ };
+
+ jQuery.removeEvent = function( elem, type, handle ) {
+
+ // This "if" is needed for plain objects
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle );
+ }
+ };
+
+ jQuery.Event = function( src, props ) {
+
+ // Allow instantiation without the 'new' keyword
+ if ( !( this instanceof jQuery.Event ) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = src.defaultPrevented ||
+ src.defaultPrevented === undefined &&
+
+ // Support: Android <=2.3 only
+ src.returnValue === false ?
+ returnTrue :
+ returnFalse;
+
+ // Create target properties
+ // Support: Safari <=6 - 7 only
+ // Target should not be a text node (#504, #13143)
+ this.target = ( src.target && src.target.nodeType === 3 ) ?
+ src.target.parentNode :
+ src.target;
+
+ this.currentTarget = src.currentTarget;
+ this.relatedTarget = src.relatedTarget;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+ };
+
+ // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+ // https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+ jQuery.Event.prototype = {
+ constructor: jQuery.Event,
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+ isSimulated: false,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.preventDefault();
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopPropagation();
+ }
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+ };
+
+ // Includes all common event props including KeyEvent and MouseEvent specific props
+ jQuery.each( {
+ altKey: true,
+ bubbles: true,
+ cancelable: true,
+ changedTouches: true,
+ ctrlKey: true,
+ detail: true,
+ eventPhase: true,
+ metaKey: true,
+ pageX: true,
+ pageY: true,
+ shiftKey: true,
+ view: true,
+ "char": true,
+ charCode: true,
+ key: true,
+ keyCode: true,
+ button: true,
+ buttons: true,
+ clientX: true,
+ clientY: true,
+ offsetX: true,
+ offsetY: true,
+ pointerId: true,
+ pointerType: true,
+ screenX: true,
+ screenY: true,
+ targetTouches: true,
+ toElement: true,
+ touches: true,
+
+ which: function( event ) {
+ var button = event.button;
+
+ // Add which for key events
+ if ( event.which == null && rkeyEvent.test( event.type ) ) {
+ return event.charCode != null ? event.charCode : event.keyCode;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
+ return ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event.which;
+ }
+ }, jQuery.event.addProp );
+
+ // Create mouseenter/leave events using mouseover/out and event-time checks
+ // so that event delegation works in jQuery.
+ // Do the same for pointerenter/pointerleave and pointerover/pointerout
+ //
+ // Support: Safari 7 only
+ // Safari sends mouseenter too often; see:
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=470258
+ // for the description of the bug (it existed in older Chrome versions as well).
+ jQuery.each( {
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+ }, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mouseenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+ } );
+
+ jQuery.fn.extend( {
+
+ on: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn );
+ },
+ one: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ?
+ handleObj.origType + "." + handleObj.namespace :
+ handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each( function() {
+ jQuery.event.remove( this, types, fn, selector );
+ } );
+ }
+ } );
+
+
+ var
+
+ /* eslint-disable max-len */
+
+ // See https://github.com/eslint/eslint/issues/3229
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
+
+ /* eslint-enable */
+
+ // Support: IE <=10 - 11, Edge 12 - 13
+ // In IE/Edge using regex groups here causes severe slowdowns.
+ // See https://connect.microsoft.com/IE/feedback/details/1736512/
+ rnoInnerhtml = /<script|<style|<link/i,
+
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
+
+ function manipulationTarget( elem, content ) {
+ if ( jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
+
+ return elem.getElementsByTagName( "tbody" )[ 0 ] || elem;
+ }
+
+ return elem;
+ }
+
+ // Replace/restore the type attribute of script elements for safe DOM manipulation
+ function disableScript( elem ) {
+ elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
+ return elem;
+ }
+ function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+
+ if ( match ) {
+ elem.type = match[ 1 ];
+ } else {
+ elem.removeAttribute( "type" );
+ }
+
+ return elem;
+ }
+
+ function cloneCopyEvent( src, dest ) {
+ var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // 1. Copy private data: events, handlers, etc.
+ if ( dataPriv.hasData( src ) ) {
+ pdataOld = dataPriv.access( src );
+ pdataCur = dataPriv.set( dest, pdataOld );
+ events = pdataOld.events;
+
+ if ( events ) {
+ delete pdataCur.handle;
+ pdataCur.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+ }
+
+ // 2. Copy user data
+ if ( dataUser.hasData( src ) ) {
+ udataOld = dataUser.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ dataUser.set( dest, udataCur );
+ }
+ }
+
+ // Fix IE bugs, see support tests
+ function fixInput( src, dest ) {
+ var nodeName = dest.nodeName.toLowerCase();
+
+ // Fails to persist the checked state of a cloned checkbox or radio button.
+ if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ dest.checked = src.checked;
+
+ // Fails to return the selected option to the default selected state when cloning options
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+ }
+
+ function domManip( collection, args, callback, ignored ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = collection.length,
+ iNoClone = l - 1,
+ value = args[ 0 ],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return collection.each( function( index ) {
+ var self = collection.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ domManip( self, args, callback, ignored );
+ } );
+ }
+
+ if ( l ) {
+ fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ // Require either new content or an interest in ignored elements to invoke the callback
+ if ( first || ignored ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item
+ // instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( collection[ i ], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !dataPriv.access( node, "globalEval" ) &&
+ jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return collection;
+ }
+
+ function remove( elem, selector, keepData ) {
+ var node,
+ nodes = selector ? jQuery.filter( selector, elem ) : elem,
+ i = 0;
+
+ for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+ if ( !keepData && node.nodeType === 1 ) {
+ jQuery.cleanData( getAll( node ) );
+ }
+
+ if ( node.parentNode ) {
+ if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+ setGlobalEval( getAll( node, "script" ) );
+ }
+ node.parentNode.removeChild( node );
+ }
+ }
+
+ return elem;
+ }
+
+ jQuery.extend( {
+ htmlPrefilter: function( html ) {
+ return html.replace( rxhtmlTag, "<$1></$2>" );
+ },
+
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Fix IE cloning issues
+ if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+ !jQuery.isXMLDoc( elem ) ) {
+
+ // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ fixInput( srcElements[ i ], destElements[ i ] );
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ // Return the cloned set
+ return clone;
+ },
+
+ cleanData: function( elems ) {
+ var data, elem, type,
+ special = jQuery.event.special,
+ i = 0;
+
+ for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+ if ( acceptData( elem ) ) {
+ if ( ( data = elem[ dataPriv.expando ] ) ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataPriv.expando ] = undefined;
+ }
+ if ( elem[ dataUser.expando ] ) {
+
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataUser.expando ] = undefined;
+ }
+ }
+ }
+ }
+ } );
+
+ jQuery.fn.extend( {
+ detach: function( selector ) {
+ return remove( this, selector, true );
+ },
+
+ remove: function( selector ) {
+ return remove( this, selector );
+ },
+
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().each( function() {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.textContent = value;
+ }
+ } );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ } );
+ },
+
+ prepend: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ } );
+ },
+
+ before: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ } );
+ },
+
+ after: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ } );
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; ( elem = this[ i ] ) != null; i++ ) {
+ if ( elem.nodeType === 1 ) {
+
+ // Prevent memory leaks
+ jQuery.cleanData( getAll( elem, false ) );
+
+ // Remove any remaining nodes
+ elem.textContent = "";
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function() {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ } );
+ },
+
+ html: function( value ) {
+ return access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined && elem.nodeType === 1 ) {
+ return elem.innerHTML;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+ value = jQuery.htmlPrefilter( value );
+
+ try {
+ for ( ; i < l; i++ ) {
+ elem = this[ i ] || {};
+
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch ( e ) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var ignored = [];
+
+ // Make the changes, replacing each non-ignored context element with the new content
+ return domManip( this, arguments, function( elem ) {
+ var parent = this.parentNode;
+
+ if ( jQuery.inArray( this, ignored ) < 0 ) {
+ jQuery.cleanData( getAll( this ) );
+ if ( parent ) {
+ parent.replaceChild( elem, this );
+ }
+ }
+
+ // Force callback invocation
+ }, ignored );
+ }
+ } );
+
+ jQuery.each( {
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+ }, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1,
+ i = 0;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone( true );
+ jQuery( insert[ i ] )[ original ]( elems );
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // .get() because push.apply(_, arraylike) throws on ancient WebKit
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+ } );
+ var rmargin = ( /^margin/ );
+
+ var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+ var getStyles = function( elem ) {
+
+ // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ var view = elem.ownerDocument.defaultView;
+
+ if ( !view || !view.opener ) {
+ view = window;
+ }
+
+ return view.getComputedStyle( elem );
+ };
+
+
+
+ ( function() {
+
+ // Executing both pixelPosition & boxSizingReliable tests require only one layout
+ // so they're executed at the same time to save the second computation.
+ function computeStyleTests() {
+
+ // This is a singleton, we need to execute it only once
+ if ( !div ) {
+ return;
+ }
+
+ div.style.cssText =
+ "box-sizing:border-box;" +
+ "position:relative;display:block;" +
+ "margin:auto;border:1px;padding:1px;" +
+ "top:1%;width:50%";
+ div.innerHTML = "";
+ documentElement.appendChild( container );
+
+ var divStyle = window.getComputedStyle( div );
+ pixelPositionVal = divStyle.top !== "1%";
+
+ // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
+ reliableMarginLeftVal = divStyle.marginLeft === "2px";
+ boxSizingReliableVal = divStyle.width === "4px";
+
+ // Support: Android 4.0 - 4.3 only
+ // Some styles come back with percentage values, even though they shouldn't
+ div.style.marginRight = "50%";
+ pixelMarginRightVal = divStyle.marginRight === "4px";
+
+ documentElement.removeChild( container );
+
+ // Nullify the div so it wouldn't be stored in the memory and
+ // it will also be a sign that checks already performed
+ div = null;
+ }
+
+ var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+ container = document.createElement( "div" ),
+ div = document.createElement( "div" );
+
+ // Finish early in limited (non-browser) environments
+ if ( !div.style ) {
+ return;
+ }
+
+ // Support: IE <=9 - 11 only
+ // Style of cloned element affects source element cloned (#8908)
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+ "padding:0;margin-top:1px;position:absolute";
+ container.appendChild( div );
+
+ jQuery.extend( support, {
+ pixelPosition: function() {
+ computeStyleTests();
+ return pixelPositionVal;
+ },
+ boxSizingReliable: function() {
+ computeStyleTests();
+ return boxSizingReliableVal;
+ },
+ pixelMarginRight: function() {
+ computeStyleTests();
+ return pixelMarginRightVal;
+ },
+ reliableMarginLeft: function() {
+ computeStyleTests();
+ return reliableMarginLeftVal;
+ }
+ } );
+ } )();
+
+
+ function curCSS( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+
+ // Support: IE <=9 only
+ // getPropertyValue is only needed for .css('filter') (#12537)
+ if ( computed ) {
+ ret = computed.getPropertyValue( name ) || computed[ name ];
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Android Browser returns percentage for some values,
+ // but width seems to be reliably pixels.
+ // This is against the CSSOM draft spec:
+ // https://drafts.csswg.org/cssom/#resolved-values
+ if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret !== undefined ?
+
+ // Support: IE <=9 - 11 only
+ // IE returns zIndex value as an integer.
+ ret + "" :
+ ret;
+ }
+
+
+ function addGetHookIf( conditionFn, hookFn ) {
+
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ if ( conditionFn() ) {
+
+ // Hook not needed (or it's not possible to use it due
+ // to missing dependency), remove it.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+ return ( this.get = hookFn ).apply( this, arguments );
+ }
+ };
+ }
+
+
+ var
+
+ // Swappable if display is none or starts with table
+ // except "table", "table-cell", or "table-caption"
+ // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "Moz", "ms" ],
+ emptyStyle = document.createElement( "div" ).style;
+
+ // Return a css property mapped to a potentially vendor prefixed property
+ function vendorPropName( name ) {
+
+ // Shortcut for names that are not vendor prefixed
+ if ( name in emptyStyle ) {
+ return name;
+ }
+
+ // Check for vendor prefixed names
+ var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in emptyStyle ) {
+ return name;
+ }
+ }
+ }
+
+ function setPositiveNumber( elem, value, subtract ) {
+
+ // Any relative (+/-) values have already been
+ // normalized at this point
+ var matches = rcssNum.exec( value );
+ return matches ?
+
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
+ value;
+ }
+
+ function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+
+ // Both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // At this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+
+ // At this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // At this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+ }
+
+ function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var val,
+ valueIsBorderBox = true,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a disconnected node
+ // in IE throws an error.
+ if ( elem.getClientRects().length ) {
+ val = elem.getBoundingClientRect()[ name ];
+ }
+
+ // Some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test( val ) ) {
+ return val;
+ }
+
+ // Check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // Use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+ }
+
+ jQuery.extend( {
+
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "animationIterationCount": true,
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ "float": "cssFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] ||
+ ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
+
+ // Gets hook for the prefixed version, then unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // Convert "+=" or "-=" to relative numbers (#7345)
+ if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+ value = adjustCSS( elem, name, ret );
+
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set (#7116)
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add the unit (except for certain CSS properties)
+ if ( type === "number" ) {
+ value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
+ }
+
+ // background-* props affect original clone's values
+ if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !( "set" in hooks ) ||
+ ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
+
+ style[ name ] = value;
+ }
+
+ } else {
+
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks &&
+ ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
+
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var val, num, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] ||
+ ( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
+
+ // Try prefixed name followed by the unprefixed name
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ // Convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Make numeric if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || isFinite( num ) ? num || 0 : val;
+ }
+ return val;
+ }
+ } );
+
+ jQuery.each( [ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+
+ // Certain elements can have dimension info if we invisibly show them
+ // but it must have a current display style that would benefit
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+
+ // Support: Safari 8+
+ // Table columns in Safari have non-zero offsetWidth & zero
+ // getBoundingClientRect().width unless display is changed.
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a disconnected node
+ // in IE throws an error.
+ ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ } ) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var matches,
+ styles = extra && getStyles( elem ),
+ subtract = extra && augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ );
+
+ // Convert to pixels if value adjustment is needed
+ if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+ ( matches[ 3 ] || "px" ) !== "px" ) {
+
+ elem.style[ name ] = value;
+ value = jQuery.css( elem, name );
+ }
+
+ return setPositiveNumber( elem, value, subtract );
+ }
+ };
+ } );
+
+ jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
+ function( elem, computed ) {
+ if ( computed ) {
+ return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+ elem.getBoundingClientRect().left -
+ swap( elem, { marginLeft: 0 }, function() {
+ return elem.getBoundingClientRect().left;
+ } )
+ ) + "px";
+ }
+ }
+ );
+
+ // These hooks are used by animate to expand properties
+ jQuery.each( {
+ margin: "",
+ padding: "",
+ border: "Width"
+ }, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // Assumes a single number if not a string
+ parts = typeof value === "string" ? value.split( " " ) : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+ } );
+
+ jQuery.fn.extend( {
+ css: function( name, value ) {
+ return access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ }
+ } );
+
+
+ function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+ }
+ jQuery.Tween = Tween;
+
+ Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || jQuery.easing._default;
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+ };
+
+ Tween.prototype.init.prototype = Tween.prototype;
+
+ Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ // Use a property on the element directly when it is not a DOM element,
+ // or when there is no matching style property that exists.
+ if ( tween.elem.nodeType !== 1 ||
+ tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // Passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails.
+ // Simple values such as "10px" are parsed to Float;
+ // complex values such as "rotate(1rad)" are returned as-is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+
+ // Use step hook for back compat.
+ // Use cssHook if its there.
+ // Use .style if available and use plain properties where available.
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.nodeType === 1 &&
+ ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
+ jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+ };
+
+ // Support: IE <=9 only
+ // Panic based approach to setting things on disconnected nodes
+ Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ };
+
+ jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ },
+ _default: "swing"
+ };
+
+ jQuery.fx = Tween.prototype.init;
+
+ // Back compat <1.8 extension point
+ jQuery.fx.step = {};
+
+
+
+
+ var
+ fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rrun = /queueHooks$/;
+
+ function raf() {
+ if ( timerId ) {
+ window.requestAnimationFrame( raf );
+ jQuery.fx.tick();
+ }
+ }
+
+ // Animations created synchronously will run synchronously
+ function createFxNow() {
+ window.setTimeout( function() {
+ fxNow = undefined;
+ } );
+ return ( fxNow = jQuery.now() );
+ }
+
+ // Generate parameters to create a standard animation
+ function genFx( type, includeWidth ) {
+ var which,
+ i = 0,
+ attrs = { height: type };
+
+ // If we include width, step value is 1 to do all cssExpand values,
+ // otherwise step value is 2 to skip over Left and Right
+ includeWidth = includeWidth ? 1 : 0;
+ for ( ; i < 4; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+ }
+
+ function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
+
+ // We're done with this property
+ return tween;
+ }
+ }
+ }
+
+ function defaultPrefilter( elem, props, opts ) {
+ var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
+ isBox = "width" in props || "height" in props,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHiddenWithinTree( elem ),
+ dataShow = dataPriv.get( elem, "fxshow" );
+
+ // Queue-skipping animations hijack the fx hooks
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always( function() {
+
+ // Ensure the complete handler is called before this completes
+ anim.always( function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ } );
+ } );
+ }
+
+ // Detect show/hide animations
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.test( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // Pretend to be hidden if this is a "show" and
+ // there is still data from a stopped show/hide
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+
+ // Ignore all other no-op show/hide data
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+ }
+ }
+
+ // Bail out if this is a no-op like .hide().hide()
+ propTween = !jQuery.isEmptyObject( props );
+ if ( !propTween && jQuery.isEmptyObject( orig ) ) {
+ return;
+ }
+
+ // Restrict "overflow" and "display" styles during box animations
+ if ( isBox && elem.nodeType === 1 ) {
+
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Record all 3 overflow attributes because IE does not infer the shorthand
+ // from identically-valued overflowX and overflowY
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Identify a display type, preferring old show/hide data over the CSS cascade
+ restoreDisplay = dataShow && dataShow.display;
+ if ( restoreDisplay == null ) {
+ restoreDisplay = dataPriv.get( elem, "display" );
+ }
+ display = jQuery.css( elem, "display" );
+ if ( display === "none" ) {
+ if ( restoreDisplay ) {
+ display = restoreDisplay;
+ } else {
+
+ // Get nonempty value(s) by temporarily forcing visibility
+ showHide( [ elem ], true );
+ restoreDisplay = elem.style.display || restoreDisplay;
+ display = jQuery.css( elem, "display" );
+ showHide( [ elem ] );
+ }
+ }
+
+ // Animate inline elements as inline-block
+ if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
+ if ( jQuery.css( elem, "float" ) === "none" ) {
+
+ // Restore the original display value at the end of pure show/hide animations
+ if ( !propTween ) {
+ anim.done( function() {
+ style.display = restoreDisplay;
+ } );
+ if ( restoreDisplay == null ) {
+ display = style.display;
+ restoreDisplay = display === "none" ? "" : display;
+ }
+ }
+ style.display = "inline-block";
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ anim.always( function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ } );
+ }
+
+ // Implement show/hide animations
+ propTween = false;
+ for ( prop in orig ) {
+
+ // General show/hide setup for this element animation
+ if ( !propTween ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
+ }
+
+ // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+
+ // Show elements before animating them
+ if ( hidden ) {
+ showHide( [ elem ], true );
+ }
+
+ /* eslint-disable no-loop-func */
+
+ anim.done( function() {
+
+ /* eslint-enable no-loop-func */
+
+ // The final step of a "hide" animation is actually hiding the element
+ if ( !hidden ) {
+ showHide( [ elem ] );
+ }
+ dataPriv.remove( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ } );
+ }
+
+ // Per-property setup
+ propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = propTween.start;
+ if ( hidden ) {
+ propTween.end = propTween.start;
+ propTween.start = 0;
+ }
+ }
+ }
+ }
+
+ function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // Not quite $.extend, this won't overwrite existing keys.
+ // Reusing 'index' because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+ }
+
+ function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = Animation.prefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+
+ // Don't match elem in the :animated selector
+ delete tick.elem;
+ } ),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+
+ // Support: Android 2.3 only
+ // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ] );
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise( {
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, {
+ specialEasing: {},
+ easing: jQuery.easing._default
+ }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+
+ // If we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // Resolve when we played the last frame; otherwise, reject
+ if ( gotoEnd ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ } ),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length; index++ ) {
+ result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ if ( jQuery.isFunction( result.stop ) ) {
+ jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+ jQuery.proxy( result.stop, result );
+ }
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ } )
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+ }
+
+ jQuery.Animation = jQuery.extend( Animation, {
+
+ tweeners: {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value );
+ adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+ return tween;
+ } ]
+ },
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.match( rnotwhite );
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length; index++ ) {
+ prop = props[ index ];
+ Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+ Animation.tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilters: [ defaultPrefilter ],
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ Animation.prefilters.unshift( callback );
+ } else {
+ Animation.prefilters.push( callback );
+ }
+ }
+ } );
+
+ jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ // Go to the end state if fx are off or if document is hidden
+ if ( jQuery.fx.off || document.hidden ) {
+ opt.duration = 0;
+
+ } else {
+ opt.duration = typeof opt.duration === "number" ?
+ opt.duration : opt.duration in jQuery.fx.speeds ?
+ jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+ }
+
+ // Normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+ };
+
+ jQuery.fn.extend( {
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // Show any hidden elements after setting opacity to 0
+ return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
+
+ // Animate to the value specified
+ .end().animate( { opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || dataPriv.get( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each( function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = dataPriv.get( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this &&
+ ( type == null || timers[ index ].queue === type ) ) {
+
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Start the next in the queue if the last step wasn't forced.
+ // Timers currently will call their complete callbacks, which
+ // will dequeue but only if they were gotoEnd.
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each( function() {
+ var index,
+ data = dataPriv.get( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // Enable finishing flag on private data
+ data.finish = true;
+
+ // Empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // Look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // Turn off finishing flag
+ delete data.finish;
+ } );
+ }
+ } );
+
+ jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+ } );
+
+ // Generate shortcuts for custom animations
+ jQuery.each( {
+ slideDown: genFx( "show" ),
+ slideUp: genFx( "hide" ),
+ slideToggle: genFx( "toggle" ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+ }, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+ } );
+
+ jQuery.timers = [];
+ jQuery.fx.tick = function() {
+ var timer,
+ i = 0,
+ timers = jQuery.timers;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+ };
+
+ jQuery.fx.timer = function( timer ) {
+ jQuery.timers.push( timer );
+ if ( timer() ) {
+ jQuery.fx.start();
+ } else {
+ jQuery.timers.pop();
+ }
+ };
+
+ jQuery.fx.interval = 13;
+ jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = window.requestAnimationFrame ?
+ window.requestAnimationFrame( raf ) :
+ window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+ };
+
+ jQuery.fx.stop = function() {
+ if ( window.cancelAnimationFrame ) {
+ window.cancelAnimationFrame( timerId );
+ } else {
+ window.clearInterval( timerId );
+ }
+
+ timerId = null;
+ };
+
+ jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+
+ // Default speed
+ _default: 400
+ };
+
+
+ // Based off of the plugin by Clint Helfers, with permission.
+ // https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
+ jQuery.fn.delay = function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = window.setTimeout( next, time );
+ hooks.stop = function() {
+ window.clearTimeout( timeout );
+ };
+ } );
+ };
+
+
+ ( function() {
+ var input = document.createElement( "input" ),
+ select = document.createElement( "select" ),
+ opt = select.appendChild( document.createElement( "option" ) );
+
+ input.type = "checkbox";
+
+ // Support: Android <=4.3 only
+ // Default value for a checkbox should be "on"
+ support.checkOn = input.value !== "";
+
+ // Support: IE <=11 only
+ // Must access selectedIndex to make default options select
+ support.optSelected = opt.selected;
+
+ // Support: IE <=11 only
+ // An input loses its value after becoming a radio
+ input = document.createElement( "input" );
+ input.value = "t";
+ input.type = "radio";
+ support.radioValue = input.value === "t";
+ } )();
+
+
+ var boolHook,
+ attrHandle = jQuery.expr.attrHandle;
+
+ jQuery.fn.extend( {
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each( function() {
+ jQuery.removeAttr( this, name );
+ } );
+ }
+ } );
+
+ jQuery.extend( {
+ attr: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set attributes on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // Attribute hooks are determined by the lowercase version
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
+ }
+
+ if ( value !== undefined ) {
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+ }
+
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ? undefined : ret;
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" &&
+ jQuery.nodeName( elem, "input" ) ) {
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name,
+ i = 0,
+ attrNames = value && value.match( rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( ( name = attrNames[ i++ ] ) ) {
+ elem.removeAttribute( name );
+ }
+ }
+ }
+ } );
+
+ // Hooks for boolean attributes
+ boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ elem.setAttribute( name, name );
+ }
+ return name;
+ }
+ };
+
+ jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+ var getter = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = function( elem, name, isXML ) {
+ var ret, handle,
+ lowercaseName = name.toLowerCase();
+
+ if ( !isXML ) {
+
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ lowercaseName ];
+ attrHandle[ lowercaseName ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ lowercaseName :
+ null;
+ attrHandle[ lowercaseName ] = handle;
+ }
+ return ret;
+ };
+ } );
+
+
+
+
+ var rfocusable = /^(?:input|select|textarea|button)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+ jQuery.fn.extend( {
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ return this.each( function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ } );
+ }
+ } );
+
+ jQuery.extend( {
+ prop: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set properties on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ return ( elem[ name ] = value );
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ return elem[ name ];
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+
+ // Support: IE <=9 - 11 only
+ // elem.tabIndex doesn't always return the
+ // correct value when it hasn't been explicitly set
+ // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ return tabindex ?
+ parseInt( tabindex, 10 ) :
+ rfocusable.test( elem.nodeName ) ||
+ rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ -1;
+ }
+ }
+ },
+
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ }
+ } );
+
+ // Support: IE <=11 only
+ // Accessing the selectedIndex property
+ // forces the browser to respect setting selected
+ // on the option
+ // The getter ensures a default option is selected
+ // when in an optgroup
+ if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ },
+ set: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+ };
+ }
+
+ jQuery.each( [
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+ ], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+ } );
+
+
+
+
+ var rclass = /[\t\r\n\f]/g;
+
+ function getClass( elem ) {
+ return elem.getAttribute && elem.getAttribute( "class" ) || "";
+ }
+
+ jQuery.fn.extend( {
+ addClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( !arguments.length ) {
+ return this.attr( "class", "" );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnotwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 &&
+ ( " " + curValue + " " ).replace( rclass, " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).toggleClass(
+ value.call( this, i, getClass( this ), stateVal ),
+ stateVal
+ );
+ } );
+ }
+
+ return this.each( function() {
+ var className, i, self, classNames;
+
+ if ( type === "string" ) {
+
+ // Toggle individual class names
+ i = 0;
+ self = jQuery( this );
+ classNames = value.match( rnotwhite ) || [];
+
+ while ( ( className = classNames[ i++ ] ) ) {
+
+ // Check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( value === undefined || type === "boolean" ) {
+ className = getClass( this );
+ if ( className ) {
+
+ // Store className if set
+ dataPriv.set( this, "__className__", className );
+ }
+
+ // If the element has a class name or if we're passed `false`,
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || value === false ?
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
+ );
+ }
+ }
+ } );
+ },
+
+ hasClass: function( selector ) {
+ var className, elem,
+ i = 0;
+
+ className = " " + selector + " ";
+ while ( ( elem = this[ i++ ] ) ) {
+ if ( elem.nodeType === 1 &&
+ ( " " + getClass( elem ) + " " ).replace( rclass, " " )
+ .indexOf( className ) > -1
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ } );
+
+
+
+
+ var rreturn = /\r/g,
+ rspaces = /[\x20\t\r\n\f]+/g;
+
+ jQuery.fn.extend( {
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[ 0 ];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] ||
+ jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks &&
+ "get" in hooks &&
+ ( ret = hooks.get( elem, "value" ) ) !== undefined
+ ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+
+ // Handle most common string cases
+ ret.replace( rreturn, "" ) :
+
+ // Handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each( function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+
+ } else if ( typeof val === "number" ) {
+ val += "";
+
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ } );
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ } );
+ }
+ } );
+
+ jQuery.extend( {
+ valHooks: {
+ option: {
+ get: function( elem ) {
+
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+
+ // Support: IE <=10 - 11 only
+ // option.text throws exceptions (#14686, #14858)
+ // Strip and collapse whitespace
+ // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+ jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one",
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Support: IE <=9 only
+ // IE8-9 doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+
+ // Don't return options that are disabled or in a disabled optgroup
+ !option.disabled &&
+ ( !option.parentNode.disabled ||
+ !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+
+ /* eslint-disable no-cond-assign */
+
+ if ( option.selected =
+ jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
+ ) {
+ optionSet = true;
+ }
+
+ /* eslint-enable no-cond-assign */
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ }
+ } );
+
+ // Radios and checkboxes getter/setter
+ jQuery.each( [ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+ };
+ }
+ } );
+
+
+
+
+ // Return jQuery for attributes-only inclusion
+
+
+ var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+ jQuery.extend( jQuery.event, {
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "." ) > -1 ) {
+
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split( "." );
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf( ":" ) < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join( "." );
+ event.rnamespace = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === ( elem.ownerDocument || document ) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+ dataPriv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( ( !special._default ||
+ special._default.apply( eventPath.pop(), data ) === false ) &&
+ acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name as the event.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Piggyback on a donor event to simulate a different one
+ // Used only for `focus(in | out)` events
+ simulate: function( type, elem, event ) {
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true
+ }
+ );
+
+ jQuery.event.trigger( e, null, elem );
+ }
+
+ } );
+
+ jQuery.fn.extend( {
+
+ trigger: function( type, data ) {
+ return this.each( function() {
+ jQuery.event.trigger( type, data, this );
+ } );
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[ 0 ];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+ } );
+
+
+ jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup contextmenu" ).split( " " ),
+ function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+ } );
+
+ jQuery.fn.extend( {
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+ } );
+
+
+
+
+ support.focusin = "onfocusin" in window;
+
+
+ // Support: Firefox <=44
+ // Firefox doesn't have focus(in | out) events
+ // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+ //
+ // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
+ // focus(in | out) events fire after focus & blur events,
+ // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+ // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
+ if ( !support.focusin ) {
+ jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ dataPriv.remove( doc, fix );
+
+ } else {
+ dataPriv.access( doc, fix, attaches );
+ }
+ }
+ };
+ } );
+ }
+ var location = window.location;
+
+ var nonce = jQuery.now();
+
+ var rquery = ( /\?/ );
+
+
+
+ // Cross-browser xml parsing
+ jQuery.parseXML = function( data ) {
+ var xml;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+
+ // Support: IE 9 - 11 only
+ // IE throws on parseFromString with invalid input.
+ try {
+ xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+ } catch ( e ) {
+ xml = undefined;
+ }
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ };
+
+
+ var
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+ function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams(
+ prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
+ v,
+ traditional,
+ add
+ );
+ }
+ } );
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+ }
+
+ // Serialize an array of form elements or a set of
+ // key/values into a query string
+ jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, valueOrFunction ) {
+
+ // If value is a function, invoke it and use its return value
+ var value = jQuery.isFunction( valueOrFunction ) ?
+ valueOrFunction() :
+ valueOrFunction;
+
+ s[ s.length ] = encodeURIComponent( key ) + "=" +
+ encodeURIComponent( value == null ? "" : value );
+ };
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ } );
+
+ } else {
+
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" );
+ };
+
+ jQuery.fn.extend( {
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map( function() {
+
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ } )
+ .filter( function() {
+ var type = this.type;
+
+ // Use .is( ":disabled" ) so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ } )
+ .map( function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ).get();
+ }
+ } );
+
+
+ var
+ r20 = /%20/g,
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat( "*" ),
+
+ // Anchor tag for parsing the document origin
+ originAnchor = document.createElement( "a" );
+ originAnchor.href = location.href;
+
+ // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+ function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+
+ // For each dataType in the dataTypeExpression
+ while ( ( dataType = dataTypes[ i++ ] ) ) {
+
+ // Prepend if requested
+ if ( dataType[ 0 ] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
+
+ // Otherwise append
+ } else {
+ ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
+ }
+ }
+ }
+ };
+ }
+
+ // Base inspection function for prefilters and transports
+ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if ( typeof dataTypeOrTransport === "string" &&
+ !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ } );
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+ }
+
+ // A special extend for ajax options
+ // that takes "flat" options (not to be deep extended)
+ // Fixes #9887
+ function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+ }
+
+ /* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+ function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var ct, type, finalDataType, firstDataType,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while ( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+ }
+
+ /* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+ function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s.throws ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return {
+ state: "parsererror",
+ error: conv ? e : "No conversion from " + prev + " to " + current
+ };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+ }
+
+ jQuery.extend( {
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: location.href,
+ type: "GET",
+ isLocal: rlocalProtocol.test( location.protocol ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /\bxml\b/,
+ html: /\bhtml/,
+ json: /\bjson\b/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": JSON.parse,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var transport,
+
+ // URL without anti-cache param
+ cacheURL,
+
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+
+ // timeout handle
+ timeoutTimer,
+
+ // Url cleanup var
+ urlAnchor,
+
+ // Request state (becomes false upon send and true upon completion)
+ completed,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ // Loop variable
+ i,
+
+ // uncached part of the url
+ uncached,
+
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+
+ // Callbacks context
+ callbackContext = s.context || s,
+
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context &&
+ ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+
+ // Default abort message
+ strAbort = "canceled",
+
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( completed ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return completed ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( completed == null ) {
+ name = requestHeadersNames[ name.toLowerCase() ] =
+ requestHeadersNames[ name.toLowerCase() ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( completed == null ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( completed ) {
+
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ } else {
+
+ // Lazy-add the new callbacks in a way that preserves old ones
+ for ( code in map ) {
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+
+ // Add protocol if not provided (prefilters might expect it)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || location.href ) + "" )
+ .replace( rprotocol, location.protocol + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+ // A cross-domain request is in order when the origin doesn't match the current origin.
+ if ( s.crossDomain == null ) {
+ urlAnchor = document.createElement( "a" );
+
+ // Support: IE <=8 - 11, Edge 12 - 13
+ // IE throws exception on accessing the href property if url is malformed,
+ // e.g. http://example.com:80x/
+ try {
+ urlAnchor.href = s.url;
+
+ // Support: IE <=8 - 11 only
+ // Anchor's host property isn't correctly set when s.url is relative
+ urlAnchor.href = urlAnchor.href;
+ s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+ urlAnchor.protocol + "//" + urlAnchor.host;
+ } catch ( e ) {
+
+ // If there is an error parsing the URL, assume it is crossDomain,
+ // it can be rejected by the transport if it is invalid
+ s.crossDomain = true;
+ }
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ // Remove hash to simplify url manipulation
+ cacheURL = s.url.replace( rhash, "" );
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // Remember the hash so we can put it back
+ uncached = s.url.slice( cacheURL.length );
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
+
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in uncached url if needed
+ if ( s.cache === false ) {
+ cacheURL = cacheURL.replace( rts, "" );
+ uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
+ }
+
+ // Put hash and anti-cache on the URL that will be requested (gh-1732)
+ s.url = cacheURL + uncached;
+
+ // Change '%20' to '+' if this is encoded form body content (gh-2658)
+ } else if ( s.data && s.processData &&
+ ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
+ s.data = s.data.replace( r20, "+" );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+ s.accepts[ s.dataTypes[ 0 ] ] +
+ ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend &&
+ ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
+
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // Aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ completeDeferred.add( s.complete );
+ jqXHR.done( s.success );
+ jqXHR.fail( s.error );
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+
+ // If request was aborted inside ajaxSend, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = window.setTimeout( function() {
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ completed = false;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+
+ // Rethrow post-completion exceptions
+ if ( completed ) {
+ throw e;
+ }
+
+ // Propagate others as results
+ done( -1, e );
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Ignore repeat invocations
+ if ( completed ) {
+ return;
+ }
+
+ completed = true;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ window.clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader( "Last-Modified" );
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader( "etag" );
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+
+ // Extract error from statusText and normalize for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+ } );
+
+ jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+
+ // Shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ // The url can be an options object (which then must have .url)
+ return jQuery.ajax( jQuery.extend( {
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ }, jQuery.isPlainObject( url ) && url ) );
+ };
+ } );
+
+
+ jQuery._evalUrl = function( url ) {
+ return jQuery.ajax( {
+ url: url,
+
+ // Make this explicit, since user can override this through ajaxSetup (#11264)
+ type: "GET",
+ dataType: "script",
+ cache: true,
+ async: false,
+ global: false,
+ "throws": true
+ } );
+ };
+
+
+ jQuery.fn.extend( {
+ wrapAll: function( html ) {
+ var wrap;
+
+ if ( this[ 0 ] ) {
+ if ( jQuery.isFunction( html ) ) {
+ html = html.call( this[ 0 ] );
+ }
+
+ // The elements to wrap the target around
+ wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+ if ( this[ 0 ].parentNode ) {
+ wrap.insertBefore( this[ 0 ] );
+ }
+
+ wrap.map( function() {
+ var elem = this;
+
+ while ( elem.firstElementChild ) {
+ elem = elem.firstElementChild;
+ }
+
+ return elem;
+ } ).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).wrapInner( html.call( this, i ) );
+ } );
+ }
+
+ return this.each( function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ } );
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each( function( i ) {
+ jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
+ } );
+ },
+
+ unwrap: function( selector ) {
+ this.parent( selector ).not( "body" ).each( function() {
+ jQuery( this ).replaceWith( this.childNodes );
+ } );
+ return this;
+ }
+ } );
+
+
+ jQuery.expr.pseudos.hidden = function( elem ) {
+ return !jQuery.expr.pseudos.visible( elem );
+ };
+ jQuery.expr.pseudos.visible = function( elem ) {
+ return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
+ };
+
+
+
+
+ jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch ( e ) {}
+ };
+
+ var xhrSuccessStatus = {
+
+ // File protocol always yields status code 0, assume 200
+ 0: 200,
+
+ // Support: IE <=9 only
+ // #1450: sometimes IE returns 1223 when it should be 204
+ 1223: 204
+ },
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+ support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+ support.ajax = xhrSupported = !!xhrSupported;
+
+ jQuery.ajaxTransport( function( options ) {
+ var callback, errorCallback;
+
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr();
+
+ xhr.open(
+ options.type,
+ options.url,
+ options.async,
+ options.username,
+ options.password
+ );
+
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Set headers
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+
+ // Callback
+ callback = function( type ) {
+ return function() {
+ if ( callback ) {
+ callback = errorCallback = xhr.onload =
+ xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+
+ // Support: IE <=9 only
+ // On a manual native abort, IE9 throws
+ // errors on any property access that is not readyState
+ if ( typeof xhr.status !== "number" ) {
+ complete( 0, "error" );
+ } else {
+ complete(
+
+ // File: protocol always yields status 0; see #8605, #14207
+ xhr.status,
+ xhr.statusText
+ );
+ }
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+
+ // Support: IE <=9 only
+ // IE9 has no XHR2 but throws on binary (trac-11426)
+ // For XHR2 non-text, let the caller handle it (gh-2498)
+ ( xhr.responseType || "text" ) !== "text" ||
+ typeof xhr.responseText !== "string" ?
+ { binary: xhr.response } :
+ { text: xhr.responseText },
+ xhr.getAllResponseHeaders()
+ );
+ }
+ }
+ };
+ };
+
+ // Listen to events
+ xhr.onload = callback();
+ errorCallback = xhr.onerror = callback( "error" );
+
+ // Support: IE 9 only
+ // Use onreadystatechange to replace onabort
+ // to handle uncaught aborts
+ if ( xhr.onabort !== undefined ) {
+ xhr.onabort = errorCallback;
+ } else {
+ xhr.onreadystatechange = function() {
+
+ // Check readyState before timeout as it changes
+ if ( xhr.readyState === 4 ) {
+
+ // Allow onerror to be called first,
+ // but that will not handle a native abort
+ // Also, save errorCallback to a variable
+ // as xhr.onerror cannot be accessed
+ window.setTimeout( function() {
+ if ( callback ) {
+ errorCallback();
+ }
+ } );
+ }
+ };
+ }
+
+ // Create the abort callback
+ callback = callback( "abort" );
+
+ try {
+
+ // Do send the request (this may raise an exception)
+ xhr.send( options.hasContent && options.data || null );
+ } catch ( e ) {
+
+ // #14683: Only rethrow if this hasn't been notified as an error yet
+ if ( callback ) {
+ throw e;
+ }
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+ } );
+
+
+
+
+ // Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
+ jQuery.ajaxPrefilter( function( s ) {
+ if ( s.crossDomain ) {
+ s.contents.script = false;
+ }
+ } );
+
+ // Install script dataType
+ jQuery.ajaxSetup( {
+ accepts: {
+ script: "text/javascript, application/javascript, " +
+ "application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /\b(?:java|ecma)script\b/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+ } );
+
+ // Handle cache's special case and crossDomain
+ jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ }
+ } );
+
+ // Bind script tag hack transport
+ jQuery.ajaxTransport( "script", function( s ) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+ var script, callback;
+ return {
+ send: function( _, complete ) {
+ script = jQuery( "<script>" ).prop( {
+ charset: s.scriptCharset,
+ src: s.url
+ } ).on(
+ "load error",
+ callback = function( evt ) {
+ script.remove();
+ callback = null;
+ if ( evt ) {
+ complete( evt.type === "error" ? 404 : 200, evt.type );
+ }
+ }
+ );
+
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ document.head.appendChild( script[ 0 ] );
+ },
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+ } );
+
+
+
+
+ var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+ // Default jsonp settings
+ jQuery.ajaxSetup( {
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+ } );
+
+ // Detect, normalize options and install callbacks for jsonp requests
+ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" &&
+ ( s.contentType || "" )
+ .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
+ rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters[ "script json" ] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // Force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always( function() {
+
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
+
+ // Otherwise restore preexisting value
+ } else {
+ window[ callbackName ] = overwritten;
+ }
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+
+ // Make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // Save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ } );
+
+ // Delegate to script
+ return "script";
+ }
+ } );
+
+
+
+
+ // Support: Safari 8 only
+ // In Safari 8 documents created via document.implementation.createHTMLDocument
+ // collapse sibling forms: the second one becomes a child of the first one.
+ // Because of that, this security measure has to be disabled in Safari 8.
+ // https://bugs.webkit.org/show_bug.cgi?id=137337
+ support.createHTMLDocument = ( function() {
+ var body = document.implementation.createHTMLDocument( "" ).body;
+ body.innerHTML = "<form></form><form></form>";
+ return body.childNodes.length === 2;
+ } )();
+
+
+ // Argument "data" should be string of html
+ // context (optional): If specified, the fragment will be created in this context,
+ // defaults to document
+ // keepScripts (optional): If true, will include scripts passed in the html string
+ jQuery.parseHTML = function( data, context, keepScripts ) {
+ if ( typeof data !== "string" ) {
+ return [];
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+
+ var base, parsed, scripts;
+
+ if ( !context ) {
+
+ // Stop scripts or inline event handlers from being executed immediately
+ // by using document.implementation
+ if ( support.createHTMLDocument ) {
+ context = document.implementation.createHTMLDocument( "" );
+
+ // Set the base href for the created document
+ // so any parsed elements with URLs
+ // are based on the document's URL (gh-2965)
+ base = context.createElement( "base" );
+ base.href = document.location.href;
+ context.head.appendChild( base );
+ } else {
+ context = document;
+ }
+ }
+
+ parsed = rsingleTag.exec( data );
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[ 1 ] ) ];
+ }
+
+ parsed = buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+ };
+
+
+ /**
+ * Load a url into a page
+ */
+ jQuery.fn.load = function( url, params, callback ) {
+ var selector, type, response,
+ self = this,
+ off = url.indexOf( " " );
+
+ if ( off > -1 ) {
+ selector = jQuery.trim( url.slice( off ) );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax( {
+ url: url,
+
+ // If "type" variable is undefined, then "GET" method will be used.
+ // Make value of this field explicit since
+ // user can override it through ajaxSetup method
+ type: type || "GET",
+ dataType: "html",
+ data: params
+ } ).done( function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ // If the request succeeds, this function gets "data", "status", "jqXHR"
+ // but they are ignored because response was set above.
+ // If it fails, this function gets "jqXHR", "status", "error"
+ } ).always( callback && function( jqXHR, status ) {
+ self.each( function() {
+ callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
+ } );
+ } );
+ }
+
+ return this;
+ };
+
+
+
+
+ // Attach a bunch of functions for handling common AJAX events
+ jQuery.each( [
+ "ajaxStart",
+ "ajaxStop",
+ "ajaxComplete",
+ "ajaxError",
+ "ajaxSuccess",
+ "ajaxSend"
+ ], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+ } );
+
+
+
+
+ jQuery.expr.pseudos.animated = function( elem ) {
+ return jQuery.grep( jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ } ).length;
+ };
+
+
+
+
+ /**
+ * Gets a window from an element
+ */
+ function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+ }
+
+ jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // Set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
+
+ // Need to be able to calculate position if either
+ // top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+
+ // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+ options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+
+ } else {
+ curElem.css( props );
+ }
+ }
+ };
+
+ jQuery.fn.extend( {
+ offset: function( options ) {
+
+ // Preserve chaining for setter
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each( function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ } );
+ }
+
+ var docElem, win, rect, doc,
+ elem = this[ 0 ];
+
+ if ( !elem ) {
+ return;
+ }
+
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a
+ // disconnected node in IE throws an error
+ if ( !elem.getClientRects().length ) {
+ return { top: 0, left: 0 };
+ }
+
+ rect = elem.getBoundingClientRect();
+
+ // Make sure element is not hidden (display: none)
+ if ( rect.width || rect.height ) {
+ doc = elem.ownerDocument;
+ win = getWindow( doc );
+ docElem = doc.documentElement;
+
+ return {
+ top: rect.top + win.pageYOffset - docElem.clientTop,
+ left: rect.left + win.pageXOffset - docElem.clientLeft
+ };
+ }
+
+ // Return zeros for disconnected and hidden elements (gh-2310)
+ return rect;
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ elem = this[ 0 ],
+ parentOffset = { top: 0, left: 0 };
+
+ // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
+ // because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+
+ // Assume getBoundingClientRect is there when computed position is fixed
+ offset = elem.getBoundingClientRect();
+
+ } else {
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset = {
+ top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
+ left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
+ };
+ }
+
+ // Subtract parent offsets and element margins
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+ };
+ },
+
+ // This method will return documentElement in the following cases:
+ // 1) For the element inside the iframe without offsetParent, this method will return
+ // documentElement of the parent window
+ // 2) For the hidden or detached element
+ // 3) For body or html element, i.e. in case of the html node - it will return itself
+ //
+ // but those exceptions were never presented as a real life use-cases
+ // and might be considered as more preferable results.
+ //
+ // This logic, however, is not guaranteed and can change at any point in the future
+ offsetParent: function() {
+ return this.map( function() {
+ var offsetParent = this.offsetParent;
+
+ while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || documentElement;
+ } );
+ }
+ } );
+
+ // Create scrollLeft and scrollTop methods
+ jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = "pageYOffset" === prop;
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? win[ prop ] : elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : win.pageXOffset,
+ top ? val : win.pageYOffset
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length );
+ };
+ } );
+
+ // Support: Safari <=7 - 9.1, Chrome <=37 - 49
+ // Add the top/left cssHooks using jQuery.fn.position
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
+ // getComputedStyle returns percent when specified for top/left/bottom/right;
+ // rather than make the css module depend on the offset module, just check for it here
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+
+ // If curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+ } );
+
+
+ // Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+ jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
+ function( defaultExtra, funcName ) {
+
+ // Margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+
+ // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
+ return funcName.indexOf( "outer" ) === 0 ?
+ elem[ "inner" + name ] :
+ elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+ // whichever is greatest
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable );
+ };
+ } );
+ } );
+
+
+ jQuery.fn.extend( {
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ?
+ this.off( selector, "**" ) :
+ this.off( types, selector || "**", fn );
+ }
+ } );
+
+ jQuery.parseJSON = JSON.parse;
+
+
+
+
+ // Register as a named AMD module, since jQuery can be concatenated with other
+ // files that may use define, but not via a proper concatenation script that
+ // understands anonymous AMD modules. A named AMD is safest and most robust
+ // way to register. Lowercase jquery is used because AMD module names are
+ // derived from file names, and jQuery is normally delivered in a lowercase
+ // file name. Do this after creating the global so that if an AMD module wants
+ // to call noConflict to hide this version of jQuery, it will work.
+
+ // Note that for maximum portability, libraries that are not jQuery should
+ // declare themselves as anonymous modules, and avoid setting a global if an
+ // AMD loader is present. jQuery is a special case. For more information, see
+ // https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+ if ( true ) {
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = function() {
+ return jQuery;
+ }.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ }
+
+
+
+
+
+ var
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+ jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ };
+
+ // Expose jQuery and $ identifiers, even in AMD
+ // (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+ // and CommonJS for browser emulators (#13566)
+ if ( !noGlobal ) {
+ window.jQuery = window.$ = jQuery;
+ }
+
+
+ return jQuery;
+ } );
+
+
+/***/ }
+/******/ ])
+});
+;
\ No newline at end of file
diff --git a/node_modules/fetch-jsonp/.eslintrc b/node_modules/fetch-jsonp/.eslintrc
new file mode 100644
index 0000000..099c4f2
--- /dev/null
+++ b/node_modules/fetch-jsonp/.eslintrc
@@ -0,0 +1,21 @@
+root: true
+
+env:
+ es6: true
+ node: true
+ browser: true
+ mocha: true
+
+ecmaFeatures:
+ modules: true
+
+extends:
+ "airbnb"
+
+rules:
+ quotes: 0
+ func-names: 0
+ comma-dangle: 0
+ no-new-func: 0
+ no-eq-null: 0
+ no-param-reassign: 0
diff --git a/node_modules/fetch-jsonp/.npmignore b/node_modules/fetch-jsonp/.npmignore
new file mode 100644
index 0000000..5221c38
--- /dev/null
+++ b/node_modules/fetch-jsonp/.npmignore
@@ -0,0 +1,7 @@
+.DS_Store
+*.log
+node_modules
+src
+test
+examples
+coverage
diff --git a/node_modules/fetch-jsonp/.travis.yml b/node_modules/fetch-jsonp/.travis.yml
new file mode 100644
index 0000000..c42701f
--- /dev/null
+++ b/node_modules/fetch-jsonp/.travis.yml
@@ -0,0 +1,3 @@
+language: node_js
+node_js:
+ - "iojs"
diff --git a/node_modules/fetch-jsonp/HISTORY.md b/node_modules/fetch-jsonp/HISTORY.md
new file mode 100644
index 0000000..ad36ba0
--- /dev/null
+++ b/node_modules/fetch-jsonp/HISTORY.md
@@ -0,0 +1,38 @@
+1.0.6 / 2017-2-3
+==================
+* update typescript config
+
+1.0.5 / 2016-12-29
+==================
+* update typescript support
+
+1.0.4 / 2016-12-23
+==================
+* add typescript support
+
+1.0.3 / 2016-12-04
+==================
+* add examples index-ie8.html
+* remove `es6-promise` dependent
+
+1.0.2 / 2016-09-26
+==================
+* Use original url when Request error
+
+1.0.1 / 2016-08-14
+==================
+* Format code
+* Update Readme
+
+1.0.0 / 2015-11-19
+==================
+* Remove Bower support
+* Add jsonpCallback and jsonpCallbackFunction as options
+
+0.9.2 / 2015-08-11
+==================
+* Remove global export of fetchJsonp
+
+0.9.1 / 2015-08-11
+==================
+* Update removeScript fix legacy IE
diff --git a/node_modules/fetch-jsonp/MAINTAINING.md b/node_modules/fetch-jsonp/MAINTAINING.md
new file mode 100644
index 0000000..77129ca
--- /dev/null
+++ b/node_modules/fetch-jsonp/MAINTAINING.md
@@ -0,0 +1,26 @@
+# Maintaining
+
+## Releasing a new version
+
+This project follows [semver](http://semver.org/). So if you are making a bug
+fix, only increment the patch level "1.0.x". If any new files are added, a
+minor version "1.x.x" bump is in order.
+
+### Make a release commit
+
+To prepare the release commit:
+
+1. Change the npm [package.json](https://github.com/camsong/fetch-jsonp/blob/master/package.json)
+`version` value to match.
+2. Make a single commit with the description as "Fetch JSONP 1.x.x".
+3. Finally, tag the commit with `v1.x.x`.
+
+```
+$ git pull
+$ vim package.json
+$ git add package.json
+$ git commit -m "Fetch JSONP 1.x.x"
+$ git tag v1.x.x
+$ git push
+$ git push --tags
+```
diff --git a/node_modules/fetch-jsonp/README.md b/node_modules/fetch-jsonp/README.md
new file mode 100644
index 0000000..42d4802
--- /dev/null
+++ b/node_modules/fetch-jsonp/README.md
@@ -0,0 +1,91 @@
+# Fetch JSONP [](https://travis-ci.org/camsong/fetch-jsonp) [](http://badge.fury.io/js/fetch-jsonp) [](https://www.npmjs.com/package/fetch-jsonp)
+
+JSONP is NOT supported in standard Fetch API, https://fetch.spec.whatwg.org.
+fetch-jsonp provides you same API to fetch JSONP like naive Fetch, also comes
+with global `fetchJsonp` function.
+
+If you need a `fetch` polyfill for old browsers, try [github/fetch](http://github.com/github/fetch).
+
+## Installation
+
+You can install with `npm`.
+
+```
+npm install fetch-jsonp
+```
+
+## Promise Polyfill for IE
+
+IE8/9/10/11 does not support [ES6 Promise](https://tc39.github.io/ecma262/#sec-promise-constructor), run this to polyfill the global environment at the beginning of your application.
+
+```js
+require('es6-promise').polyfill();
+```
+
+## Usage
+
+The `fetch-jsonp` function supports any HTTP method. We'll focus on GET and POST
+example requests.
+
+### Fetch JSONP in simple way
+
+```javascript
+fetchJsonp('/users.jsonp')
+ .then(function(response) {
+ return response.json()
+ }).then(function(json) {
+ console.log('parsed json', json)
+ }).catch(function(ex) {
+ console.log('parsing failed', ex)
+ })
+```
+
+### Set JSONP callback name, default is 'callback'
+
+```javascript
+fetchJsonp('/users.jsonp', {
+ jsonpCallback: 'custom_callback'
+ })
+ .then(function(response) {
+ return response.json()
+ }).then(function(json) {
+ console.log('parsed json', json)
+ }).catch(function(ex) {
+ console.log('parsing failed', ex)
+ })
+```
+
+### Set JSONP request timeout, default is 5000ms
+
+```javascript
+fetchJsonp('/users.jsonp', {
+ timeout: 3000,
+ jsonpCallback: 'custom_callback'
+ })
+ .then(function(response) {
+ return response.json()
+ }).then(function(json) {
+ console.log('parsed json', json)
+ }).catch(function(ex) {
+ console.log('parsing failed', ex)
+ })
+```
+
+### Caveats
+
+You need to call `.then(function(response) { return response.json(); })` in order
+to keep consistent with Fetch API.
+
+## Browser Support
+
+ |  |  |  | 
+--- | --- | --- | --- | --- |
+Latest ✔ | Latest ✔ | 8+ ✔ | Latest ✔ | 6.1+ ✔ |
+
+# License
+
+MIT
+
+# Acknowledgement
+
+Thanks to [github/fetch](https://github.com/github/fetch) for bring Fetch to old browsers.
diff --git a/node_modules/fetch-jsonp/build/fetch-jsonp.js b/node_modules/fetch-jsonp/build/fetch-jsonp.js
new file mode 100644
index 0000000..0581787
--- /dev/null
+++ b/node_modules/fetch-jsonp/build/fetch-jsonp.js
@@ -0,0 +1,108 @@
+(function (global, factory) {
+ if (typeof define === 'function' && define.amd) {
+ define(['exports', 'module'], factory);
+ } else if (typeof exports !== 'undefined' && typeof module !== 'undefined') {
+ factory(exports, module);
+ } else {
+ var mod = {
+ exports: {}
+ };
+ factory(mod.exports, mod);
+ global.fetchJsonp = mod.exports;
+ }
+})(this, function (exports, module) {
+ 'use strict';
+
+ var defaultOptions = {
+ timeout: 5000,
+ jsonpCallback: 'callback',
+ jsonpCallbackFunction: null
+ };
+
+ function generateCallbackFunction() {
+ return 'jsonp_' + Date.now() + '_' + Math.ceil(Math.random() * 100000);
+ }
+
+ // Known issue: Will throw 'Uncaught ReferenceError: callback_*** is not defined'
+ // error if request timeout
+ function clearFunction(functionName) {
+ // IE8 throws an exception when you try to delete a property on window
+ // http://stackoverflow.com/a/1824228/751089
+ try {
+ delete window[functionName];
+ } catch (e) {
+ window[functionName] = undefined;
+ }
+ }
+
+ function removeScript(scriptId) {
+ var script = document.getElementById(scriptId);
+ document.getElementsByTagName('head')[0].removeChild(script);
+ }
+
+ function fetchJsonp(_url) {
+ var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
+
+ // to avoid param reassign
+ var url = _url;
+ var timeout = options.timeout || defaultOptions.timeout;
+ var jsonpCallback = options.jsonpCallback || defaultOptions.jsonpCallback;
+
+ var timeoutId = undefined;
+
+ return new Promise(function (resolve, reject) {
+ var callbackFunction = options.jsonpCallbackFunction || generateCallbackFunction();
+ var scriptId = jsonpCallback + '_' + callbackFunction;
+
+ window[callbackFunction] = function (response) {
+ resolve({
+ ok: true,
+ // keep consistent with fetch API
+ json: function json() {
+ return Promise.resolve(response);
+ }
+ });
+
+ if (timeoutId) clearTimeout(timeoutId);
+
+ removeScript(scriptId);
+
+ clearFunction(callbackFunction);
+ };
+
+ // Check if the user set their own params, and if not add a ? to start a list of params
+ url += url.indexOf('?') === -1 ? '?' : '&';
+
+ var jsonpScript = document.createElement('script');
+ jsonpScript.setAttribute('src', '' + url + jsonpCallback + '=' + callbackFunction);
+ jsonpScript.id = scriptId;
+ document.getElementsByTagName('head')[0].appendChild(jsonpScript);
+
+ timeoutId = setTimeout(function () {
+ reject(new Error('JSONP request to ' + _url + ' timed out'));
+
+ clearFunction(callbackFunction);
+ removeScript(scriptId);
+ }, timeout);
+ });
+ }
+
+ // export as global function
+ /*
+ let local;
+ if (typeof global !== 'undefined') {
+ local = global;
+ } else if (typeof self !== 'undefined') {
+ local = self;
+ } else {
+ try {
+ local = Function('return this')();
+ } catch (e) {
+ throw new Error('polyfill failed because global object is unavailable in this environment');
+ }
+ }
+ local.fetchJsonp = fetchJsonp;
+ */
+
+ module.exports = fetchJsonp;
+});
\ No newline at end of file
diff --git a/node_modules/fetch-jsonp/index.d.ts b/node_modules/fetch-jsonp/index.d.ts
new file mode 100644
index 0000000..aac476e
--- /dev/null
+++ b/node_modules/fetch-jsonp/index.d.ts
@@ -0,0 +1,17 @@
+declare function fetchJsonp(url: string, options?: fetchJsonp.Options): Promise<fetchJsonp.Response>;
+
+declare namespace fetchJsonp {
+ interface Options {
+ timeout?: number;
+ jsonpCallback?: string;
+ jsonpCallbackFunction?: string;
+ }
+
+ interface Response {
+ json(): Promise<any>;
+ json<T>(): Promise<T>;
+ ok: boolean;
+ }
+}
+
+export = fetchJsonp;
diff --git a/node_modules/fetch-jsonp/package.json b/node_modules/fetch-jsonp/package.json
new file mode 100644
index 0000000..46f14f7
--- /dev/null
+++ b/node_modules/fetch-jsonp/package.json
@@ -0,0 +1,93 @@
+{
+ "_args": [
+ [
+ "fetch-jsonp",
+ "D:\\work\\McuClient"
+ ]
+ ],
+ "_from": "fetch-jsonp@latest",
+ "_id": "fetch-jsonp@1.0.6",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/fetch-jsonp",
+ "_nodeVersion": "5.7.1",
+ "_npmOperationalInternal": {
+ "host": "packages-12-west.internal.npmjs.com",
+ "tmp": "tmp/fetch-jsonp-1.0.6.tgz_1486087842804_0.46444737794809043"
+ },
+ "_npmUser": {
+ "email": "neosoyn@gmail.com",
+ "name": "camsong"
+ },
+ "_npmVersion": "3.6.0",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "fetch-jsonp",
+ "raw": "fetch-jsonp",
+ "rawSpec": "",
+ "scope": null,
+ "spec": "latest",
+ "type": "tag"
+ },
+ "_requiredBy": [
+ "#USER"
+ ],
+ "_resolved": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz",
+ "_shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
+ "_shrinkwrap": null,
+ "_spec": "fetch-jsonp",
+ "_where": "D:\\work\\McuClient",
+ "author": {
+ "name": "Cam Song"
+ },
+ "bugs": {
+ "url": "https://github.com/camsong/fetch-jsonp/issues"
+ },
+ "dependencies": {},
+ "description": "Fetch JSONP like a boss using Fetch API",
+ "devDependencies": {
+ "babel": "^5.8.21",
+ "babel-core": "^5.8.21",
+ "babel-eslint": "^4.0.5",
+ "chai": "^3.2.0",
+ "eslint": "^1.1.0",
+ "eslint-config-airbnb": "^0.0.7",
+ "eslint-plugin-react": "^3.2.1",
+ "mocha": "^2.2.5"
+ },
+ "directories": {},
+ "dist": {
+ "shasum": "8d2ae174ed14108292f025f43fa07d2078de6736",
+ "tarball": "https://registry.npmjs.org/fetch-jsonp/-/fetch-jsonp-1.0.6.tgz"
+ },
+ "gitHead": "3b1be53776fa36a548fbf2aa16063c27ca318661",
+ "homepage": "https://github.com/camsong/fetch-jsonp#readme",
+ "keywords": [
+ "fetch",
+ "jsonp",
+ "github fetch",
+ "ajax"
+ ],
+ "license": "MIT",
+ "main": "build/fetch-jsonp.js",
+ "maintainers": [
+ {
+ "email": "neosoyn@gmail.com",
+ "name": "camsong"
+ }
+ ],
+ "name": "fetch-jsonp",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/camsong/fetch-jsonp.git"
+ },
+ "scripts": {
+ "build": "babel src/ --modules umd --out-dir build",
+ "clean": "rm -rf build",
+ "lint": "eslint src/ test/",
+ "test": "mocha --compilers js:babel/register --recursive --ui bdd --reporter spec"
+ },
+ "version": "1.0.6"
+}
diff --git a/node_modules/iphunter/.npmignore b/node_modules/iphunter/.npmignore
new file mode 100644
index 0000000..f1fd89a
--- /dev/null
+++ b/node_modules/iphunter/.npmignore
@@ -0,0 +1,16 @@
+# exclude all
+/*
+
+# project structure
+!/src/
+!/etc/
+!/doc/
+!/test/
+!/dist/
+
+# project files
+!.gitignore
+!README.md
+!package.json
+!LICENSE
+!webpack.config.umd.js
diff --git a/node_modules/iphunter/README.md b/node_modules/iphunter/README.md
new file mode 100644
index 0000000..d6a3e65
--- /dev/null
+++ b/node_modules/iphunter/README.md
@@ -0,0 +1,28 @@
+iphunter
+
+to hunt a fatest http response.
+
+# usage
+
+iphunter(iplist,check_call_back[,timeout]);
+
+```javascript
+
+import iphunter from 'iphunter';
+
+iphunter([
+ '192.168.99.199',
+ 'baidu.com',
+ 'aliyun.com',
+ 'qq.com',
+ '192.168.99.100',
+ '127.0.0.0:8080',
+ '192.168.1.48:8080',
+ 'localhost:8080'
+], function (fatest_ip_response) {
+ if(!fatest_ip_response) return console.error('nothing!');
+
+ console.log('done -> ', fatest_ip_response);
+},3000)
+
+```
diff --git a/node_modules/iphunter/dist/main.html b/node_modules/iphunter/dist/main.html
new file mode 100644
index 0000000..cf939fb
--- /dev/null
+++ b/node_modules/iphunter/dist/main.html
@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><meta charset="UTF-8"><title>UMD PLAYGROUND</title></head><body><div id="stage"></div><script type="text/javascript" src="main.js"></script></body></html>
\ No newline at end of file
diff --git a/node_modules/iphunter/dist/main.js b/node_modules/iphunter/dist/main.js
new file mode 100644
index 0000000..fd0ef89
--- /dev/null
+++ b/node_modules/iphunter/dist/main.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function i(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new o(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var r=function(){function e(e,t){for(var n=0;n<t.length;n++){var i=t[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(e,i.key,i)}}return function(t,n,i){return n&&e(t.prototype,n),i&&e(t,i),t}}();t.default=i;var o=function(){function e(t,i,r){n(this,e),this.ip="",this.ipcallback=i,this.timeoutId=null,this.reqsCache=[];for(var o=0;o<t.length;o++)this.reqsCache.push(this.send(t[o],r-10));this.timeoutId=setTimeout(this.notify.bind(this),r)}return r(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,i=new XMLHttpRequest;return i.open("HEAD","//"+e+"/?_="+Date.now()),i.timeout=t,i.onload=function(){n.ip=e,n.clearReq(i),i.onload=null,n.notify()},i.ontimeout=function(){n.clearReq(i),i.ontimeout=null},i.onerror=function(){n.clearReq(i),i.onerror=null},i.onabort=function(){n.clearReq(i),i.onabort=null},i.send(),i}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(o,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(i,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()}])});
\ No newline at end of file
diff --git a/node_modules/iphunter/dist/test.html b/node_modules/iphunter/dist/test.html
new file mode 100644
index 0000000..7b00d78
--- /dev/null
+++ b/node_modules/iphunter/dist/test.html
@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><meta charset="UTF-8"><title>UMD PLAYGROUND</title></head><body><div id="stage"></div><script type="text/javascript" src="test.js"></script></body></html>
\ No newline at end of file
diff --git a/node_modules/iphunter/dist/test.js b/node_modules/iphunter/dist/test.js
new file mode 100644
index 0000000..4ebe57f
--- /dev/null
+++ b/node_modules/iphunter/dist/test.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.iphunter=t():e.iphunter=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(2)},function(e,t){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:3e3;if(!(e&&e.length&&t))throw new Error("ips and callback are required.");new r(e,t,n)}Object.defineProperty(t,"__esModule",{value:!0});var i=function(){function e(e,t){for(var n=0;n<t.length;n++){var o=t[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,n,o){return n&&e(t.prototype,n),o&&e(t,o),t}}();t.default=o;var r=function(){function e(t,o,i){n(this,e),this.ip="",this.ipcallback=o,this.timeoutId=null,this.reqsCache=[];for(var r=0;r<t.length;r++)this.reqsCache.push(this.send(t[r],i-10));this.timeoutId=setTimeout(this.notify.bind(this),i)}return i(e,[{key:"clearAll",value:function(){this.reqsCache&&this.reqsCache.length&&this.reqsCache.forEach(function(e){e.abort()}),clearTimeout(this.timeoutId),this.ip="",this.ipcallback=null,this.timeoutId=null,this.reqsCache=[]}},{key:"clearReq",value:function(e){this.reqsCache.splice(this.reqsCache.indexOf(e),1)}},{key:"notify",value:function(){this.ipcallback(this.ip),this.clearAll()}},{key:"send",value:function(e,t){var n=this,o=new XMLHttpRequest;return o.open("HEAD","//"+e+"/?_="+Date.now()),o.timeout=t,o.onload=function(){n.ip=e,n.clearReq(o),o.onload=null,n.notify()},o.ontimeout=function(){n.clearReq(o),o.ontimeout=null},o.onerror=function(){n.clearReq(o),o.onerror=null},o.onabort=function(){n.clearReq(o),o.onabort=null},o.send(),o}}]),e}();(function(){"undefined"!=typeof __REACT_HOT_LOADER__&&(__REACT_HOT_LOADER__.register(r,"IpHunter","/Users/AlexWang/ws/iphunter/src/main.js"),__REACT_HOT_LOADER__.register(o,"check","/Users/AlexWang/ws/iphunter/src/main.js"))})()},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}var i=n(1),r=o(i);(0,r.default)(["192.168.99.199","baidu.com","aliyun.com","qq.com","192.168.99.100","127.0.0.0:8080","192.168.1.48:8080","localhost:8080"],function(e){console.log("done -> ",e)});(function(){"undefined"==typeof __REACT_HOT_LOADER__})()}])});
\ No newline at end of file
diff --git a/node_modules/iphunter/etc/umd.template.html b/node_modules/iphunter/etc/umd.template.html
new file mode 100644
index 0000000..74748e9
--- /dev/null
+++ b/node_modules/iphunter/etc/umd.template.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>UMD PLAYGROUND</title>
+</head>
+
+<body>
+ <div id="stage"></div>
+</body>
+
+</html>
diff --git a/node_modules/iphunter/package.json b/node_modules/iphunter/package.json
new file mode 100644
index 0000000..7e81a36
--- /dev/null
+++ b/node_modules/iphunter/package.json
@@ -0,0 +1,82 @@
+{
+ "_args": [
+ [
+ "iphunter",
+ "D:\\work\\McuClient"
+ ]
+ ],
+ "_from": "iphunter@latest",
+ "_id": "iphunter@1.0.6",
+ "_inCache": true,
+ "_installable": true,
+ "_location": "/iphunter",
+ "_nodeVersion": "6.9.1",
+ "_npmOperationalInternal": {
+ "host": "packages-12-west.internal.npmjs.com",
+ "tmp": "tmp/iphunter-1.0.6.tgz_1488779370023_0.8911087329033762"
+ },
+ "_npmUser": {
+ "email": "1669499355@qq.com",
+ "name": "xinwangwang"
+ },
+ "_npmVersion": "3.10.8",
+ "_phantomChildren": {},
+ "_requested": {
+ "name": "iphunter",
+ "raw": "iphunter",
+ "rawSpec": "",
+ "scope": null,
+ "spec": "latest",
+ "type": "tag"
+ },
+ "_requiredBy": [
+ "#USER"
+ ],
+ "_resolved": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz",
+ "_shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
+ "_shrinkwrap": null,
+ "_spec": "iphunter",
+ "_where": "D:\\work\\McuClient",
+ "author": {
+ "name": "AlexWang"
+ },
+ "dependencies": {},
+ "description": "to hunt a fatest http response.",
+ "devDependencies": {},
+ "directories": {
+ "doc": "doc",
+ "test": "test"
+ },
+ "dist": {
+ "shasum": "6b7559d73002bd8cc93d558a604d64518d180840",
+ "tarball": "https://registry.npmjs.org/iphunter/-/iphunter-1.0.6.tgz"
+ },
+ "gitHead": "c9958f825f514736bd0451f632c227db4bf0a7b7",
+ "keywords": [
+ "ipcheck"
+ ],
+ "license": "MIT",
+ "main": "dist/main.js",
+ "maintainers": [
+ {
+ "email": "1669499355@qq.com",
+ "name": "xinwangwang"
+ }
+ ],
+ "name": "iphunter",
+ "optionalDependencies": {},
+ "readme": "ERROR: No README data found!",
+ "scripts": {
+ "test": "test/index.js"
+ },
+ "version": "1.0.6",
+ "wbp": {
+ "build": "dist/",
+ "entries": {
+ "main": "./src/main.js",
+ "test": "./test/test.js"
+ },
+ "project": "umd",
+ "source": "src/"
+ }
+}
diff --git a/node_modules/iphunter/src/main.js b/node_modules/iphunter/src/main.js
new file mode 100644
index 0000000..0399baf
--- /dev/null
+++ b/node_modules/iphunter/src/main.js
@@ -0,0 +1,73 @@
+class IpHunter {
+ constructor(ips, callback, timeout) {
+ this.ip = '';
+ this.ipcallback = callback;
+ this.timeoutId = null;
+ this.reqsCache = [];
+
+ for (let i = 0; i < ips.length; i++) {
+ this.reqsCache.push(this.send(ips[i], timeout - 10));
+ }
+ this.timeoutId = setTimeout(this.notify.bind(this), timeout);
+ }
+
+ clearAll() {
+ if (this.reqsCache && this.reqsCache.length) {
+ this.reqsCache.forEach((req) => {
+ req.abort();
+ })
+ }
+ clearTimeout(this.timeoutId);
+ this.ip = '';
+ this.ipcallback = null;
+ this.timeoutId = null;
+ this.reqsCache = [];
+ }
+
+ clearReq(req) {
+ this.reqsCache.splice(this.reqsCache.indexOf(req), 1);
+ }
+
+ notify() {
+ this.ipcallback(this.ip);
+ this.clearAll();
+ }
+
+ send(pip, timeout) {
+ const req = new XMLHttpRequest();
+ req.open('HEAD', `//${pip}/?_=${Date.now()}`);
+ req.timeout = timeout;
+ req.onload = () => {
+ this.ip = pip;
+ this.clearReq(req);
+ req.onload = null;
+ this.notify();
+ }
+ req.ontimeout = () => {
+ this.clearReq(req);
+ req.ontimeout = null;
+ }
+ req.onerror = () => {
+ this.clearReq(req);
+ req.onerror = null;
+ }
+ req.onabort = () => {
+ this.clearReq(req);
+ req.onabort = null;
+ }
+ req.send();
+ return req
+ }
+}
+
+/**
+ * ips check
+ * @param {array} ips
+ * @param {number} callback
+ * @return {null}
+ */
+export default function check(ips, callback, timeout = 3000) {
+ if (!(ips && ips.length && callback)) throw new Error('ips and callback are required.');
+ new IpHunter(ips, callback, timeout);
+}
+
diff --git a/node_modules/iphunter/test/test.js b/node_modules/iphunter/test/test.js
new file mode 100644
index 0000000..77311f3
--- /dev/null
+++ b/node_modules/iphunter/test/test.js
@@ -0,0 +1,15 @@
+import check from 'main.js';
+
+check([
+ '192.168.99.199',
+ 'baidu.com',
+ 'aliyun.com',
+ 'qq.com',
+ '192.168.99.100',
+ '127.0.0.0:8080',
+ '192.168.1.48:8080',
+ 'localhost:8080'
+], function (ip) {
+ console.log('done -> ', ip);
+})
+
diff --git a/node_modules/iphunter/webpack.config.umd.js b/node_modules/iphunter/webpack.config.umd.js
new file mode 100644
index 0000000..5d0d21a
--- /dev/null
+++ b/node_modules/iphunter/webpack.config.umd.js
@@ -0,0 +1,15 @@
+module.exports = function (umdConf) {
+ umdConf.devServer.host = '0.0.0.0';
+ umdConf.webpackFeatures.enableEntryHTML();
+ umdConf.output.publicPath = '';
+
+ if (umdConf.devMode) {
+ umdConf.webpackFeatures.enableEntryHot('test');
+ } else {
+ umdConf.webpackFeatures.enableUglifyJs({
+ comments: false
+ });
+ }
+ // console.log(umdConf);
+};
+
diff --git a/src/EngineEntrance.js b/src/EngineEntrance.js
index c624338..39b8ac6 100644
--- a/src/EngineEntrance.js
+++ b/src/EngineEntrance.js
@@ -5,6 +5,7 @@ require('string.fromcodepoint');
import Emiter from './Emiter';
import Sass from 'Sass';
+import ServerCheck from 'ServerCheck';
import Mcu from 'mcu';
import MessageTypes from 'MessageTypes';
import Loger from 'Loger';
@@ -26,6 +27,7 @@ let _sdkInfo={"version":"v.1.0.1","author":"www.3mang.com"};
//APE
let _sass;
+let _serverCheck;
let _mcu ;
let _confer_ape;
let _chat_ape;
@@ -34,6 +36,7 @@ let _audio_ape;
let _doc_ape;
let _whiteboard_ape;
+
//MCUClient 外部实例化主类
export default class MessageEntrance extends Emiter {
constructor() {
@@ -53,12 +56,18 @@ export default class MessageEntrance extends Emiter {
_sass.on('*', (type, data) => this._emit(type, data));
_sass.on(_sass.SUCCESS, this._sassJoinSuccessHandler.bind(this));//通过SASS平台验证(密码和MD5)
_sass.on(_sass.CLASS_INIT_SUCCESS, this._sassInitSuccessHandler.bind(this));//获取会议初始化信息
- _sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息
+ //_sass.on(_sass.CLASS_GET_CLASS_DETAIL, this._sassGetClassDetailSuccessHandler.bind(this));//获取会议的基本信息
_sass.on(_sass.CLASS_GET_CLASS_PARAM, this._sassGetClassParamSuccessHandler.bind(this));//获取会议的最全信息和历史保存的数据
+
_sass.on(_sass.CLASS_SAVE_STATUS_INFO_SUCCESS, this._sassSaveClassStatusInfoSuccessHandler.bind(this));//保存会议状态信息
_sass.on(_sass.CLASS_SAVE_RECORD_INFO_SUCCESS, this._sassSaveClassRecordInfoSuccessHandler.bind(this));//保存会议录制信息
_sass.on(_sass.DELETE_DOCUMENT_SUCCESS, this._sassDeleteDocumentSuccess.bind(this));//sass删除文档成功
+ //ServerCheck ip
+ _serverCheck=ServerCheck;
+ _serverCheck.on(_serverCheck.SEVER_CHECK_BEST_IP_SUCCESS, this._serverCheckBestIpSuccessHandler.bind(this));//ip选点,获取最佳ip完成
+
+
// 底层MCU消息层
_mcu = Mcu;
_mcu.on('*', (type, data) => this._emit(type, data));
@@ -295,6 +304,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.password = _param.password || "";
GlobalConfig.hasCamera=(typeof _param.hasCamera=="boolean")? _param.hasCamera:false;
GlobalConfig.hasMicrophone=(typeof _param.hasMicrophone=="boolean")? _param.hasMicrophone:false;
+
//debugger;
//开始校验
if (_sass) {
@@ -355,107 +365,12 @@ export default class MessageEntrance extends Emiter {
mcu 字符串 Mcu列表
rs 字符串 Rs列表
doc 字符串 Doc列表*/
-
- /* {
- "record": "112.126.80.182:80",
- "flag": "true",
- "h5Module": 1,
- "maxVideoChannels": 1,
- "mcu": "123.56.73.119:7000;123.56.69.230:7000;112.126.80.182:7000",
- "ms": "pubms.3mang.com:1935",
- "doc": "101.200.150.192:80",
- "rs": "pubms.3mang.com:1935",
- "type": 1,
- "maxAudioChannels": 1,
- "h5_mcu_list": "123.56.73.119:7001;123.56.69.230:7001;112.126.80.182:7001"
- }*/
-
- /*
- if (_data.h5_mcu_list) {
- //MCU地址默认使用第一个
- let server = _data.h5_mcu_list.split(";")[0];
- GlobalConfig.MCUServerIP = server.split(":")[0];
- GlobalConfig.MCUServerPort = server.split(":")[1];
- }
-
- //视频推流播流地址
- if (_data.ms) {
- //MS地址默认使用第一个
- let server = _data.ms.split(";")[0];
- GlobalConfig.MSServerIP = server.split(":")[0];
- GlobalConfig.MSServerPort = server.split(":")[1];
- }
-
- //m3u8播流地址
- if(_data.rs){
- //RS地址默认使用第一个
- let server = _data.rs.split(";")[0];
- GlobalConfig.RSServerIP = server.split(":")[0];
- GlobalConfig.RSServerPort = server.split(":")[1];
- }
-
- GlobalConfig.docServer = _data.doc;
- GlobalConfig.h5_mcu_list = _data.h5_mcu_list;
- GlobalConfig.h5Module = _data.h5Module;
- GlobalConfig.mcu = _data.mcu;
- GlobalConfig.ms = _data.ms;
- GlobalConfig.record = _data.record;
- GlobalConfig.rs = _data.rs;
- GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
- GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
-
- */
-
-
- /*
- //这个接口获取的数据在getClassParam接口的数据中都有,内容重复,这个接口废弃
- //获取会议基本信息
- if (_sass) {
- _sass.getClassDetail();
- }
- */
-
//获取会议最完整的数据
if (_sass) {
_sass.getClassParam();
}
}
- //获取会议基本信息getClassH5
- _sassGetClassDetailSuccessHandler(_data) {
- loger.log('获取getClassDetail完成.');
- /* {
- "cycle": 0,
- "repeatmonthweekweek": 0,
- "status": 1,
- "repeatmonthday": 0,
- "repeatmode": 0,
- "beginTime": "2017-02-03 09:00:00",
- "frequency": 1,
- "endmode": 0,
- "meetingContent": "",
- "endTime": "2017-03-31 11:00:00",
- "repeatweek": "",
- "category": "",
- "finalenddate": "",
- "repeatday": 0,
- "meetingName": "mcu1",
- "errorCode": 0,
- "monthType": 0,
- "repeatmonthweekday": 0,
- "endcount": 1
- }*/
- GlobalConfig.classDetail = _data;
- GlobalConfig.className = _data.meetingName || "";
- GlobalConfig.classBeginTime = _data.beginTime || "";
- GlobalConfig.classEndTime = _data.endTime || "";
-
- //获取会议所有信息和以前保存的会议状态信息(最全的信息)
- if (_sass) {
- _sass.getClassParam();
- }
- }
-
//获取会议所有参数 api/meeting/detail.do? flash中的接口文件是 getClassParam.do
_sassGetClassParamSuccessHandler(_data) {
//console.log(GlobalConfig.classStatusInfo)
@@ -467,6 +382,7 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.className = _data.meetingName || "";
GlobalConfig.classBeginTime = _data.beginTime || "";
GlobalConfig.classEndTime = _data.endTime || "";
+ GlobalConfig.userIp=_data.userIp||"";
GlobalConfig.maxVideoChannels = _data.maxVideoChannels;
GlobalConfig.maxAudioChannels = _data.maxAudioChannels;
@@ -526,7 +442,18 @@ export default class MessageEntrance extends Emiter {
loger.log("还没有保存过会议状信息");
}
- //所有Sass流程完成,开始MCU连接
+ //根据用户的userIp获取信息
+ this.getUserIpInfo();
+ }
+ //根据UserIp获取ip信息
+ getUserIpInfo(){
+ if(_serverCheck){
+ _serverCheck.getUserIpInfo("",GlobalConfig.userIp);
+ }
+ }
+ //MCU MS ip选点完成,开加入MCU
+ _serverCheckBestIpSuccessHandler(_data){
+ loger .log("_serverCheckBestIpSuccessHandler,IP选点结束");
this._joinMCU();
}
@@ -569,49 +496,50 @@ export default class MessageEntrance extends Emiter {
GlobalConfig.setCurrentStatus(GlobalConfig.statusCode_2);
//返回给客户端初始化成功的数据
- let initSuccessCallBackData = {};
-
- initSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;
- initSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;
-
- initSuccessCallBackData.classId = GlobalConfig.classId;
- initSuccessCallBackData.className = GlobalConfig.className;
- initSuccessCallBackData.h5Module = GlobalConfig.h5Module;
- initSuccessCallBackData.isHost = GlobalConfig.isHost;
- initSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
- initSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
- initSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
-
- initSuccessCallBackData.msType = GlobalConfig.msType;
- initSuccessCallBackData.nodeId = GlobalConfig.nodeId;
- initSuccessCallBackData.password = GlobalConfig.password;
- initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
+ let joinClassSuccessCallBackData = {};
+
+ joinClassSuccessCallBackData.DOCServerIP =GlobalConfig.DOCServerIP;
+ joinClassSuccessCallBackData.DOCServerPort =GlobalConfig.DOCServerPort;
+
+ joinClassSuccessCallBackData.classId = GlobalConfig.classId;
+ joinClassSuccessCallBackData.className = GlobalConfig.className;
+ joinClassSuccessCallBackData.h5Module = GlobalConfig.h5Module;
+ joinClassSuccessCallBackData.isHost = GlobalConfig.isHost;
+ joinClassSuccessCallBackData.maxAudioChannels = GlobalConfig.maxAudioChannels;
+ joinClassSuccessCallBackData.maxVideoChannels = GlobalConfig.maxVideoChannels;
+ joinClassSuccessCallBackData.mcuDelay = GlobalConfig.mcuDelay;
+
+ joinClassSuccessCallBackData.msType = GlobalConfig.msType;
+ joinClassSuccessCallBackData.nodeId = GlobalConfig.nodeId;
+ joinClassSuccessCallBackData.password = GlobalConfig.password;
+ joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;// 老师的默认是true
//GlobalConfig.passwordRequired 老师的默认是true
//GlobalConfig.portal=_data.portal;
- initSuccessCallBackData.role = GlobalConfig.role;
- initSuccessCallBackData.siteId = GlobalConfig.siteId;
- initSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
- initSuccessCallBackData.userId = GlobalConfig.userId;
- initSuccessCallBackData.userName = GlobalConfig.userName;
- initSuccessCallBackData.userRole = GlobalConfig.userRole;
- initSuccessCallBackData.userType = GlobalConfig.userType;
+ joinClassSuccessCallBackData.role = GlobalConfig.role;
+ joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
+ joinClassSuccessCallBackData.topNodeID = GlobalConfig.topNodeID;
+ joinClassSuccessCallBackData.userId = GlobalConfig.userId;
+ joinClassSuccessCallBackData.userName = GlobalConfig.userName;
+ joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
+ joinClassSuccessCallBackData.userType = GlobalConfig.userType;
+
+ joinClassSuccessCallBackData.siteId = GlobalConfig.siteId;
+ joinClassSuccessCallBackData.classId = GlobalConfig.classId;
+ joinClassSuccessCallBackData.userRole = GlobalConfig.userRole;
+ joinClassSuccessCallBackData.userId = GlobalConfig.userId;
+ joinClassSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
+ joinClassSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
+
+ joinClassSuccessCallBackData.country = GlobalConfig.country;//国家
+ joinClassSuccessCallBackData.city = GlobalConfig.city;//城市
+ joinClassSuccessCallBackData.province = GlobalConfig.province;//服务商
+ joinClassSuccessCallBackData.isp = GlobalConfig.isp;//服务商
- initSuccessCallBackData.siteId = GlobalConfig.siteId;
- initSuccessCallBackData.classId = GlobalConfig.classId;
- initSuccessCallBackData.userRole = GlobalConfig.userRole;
- initSuccessCallBackData.userId = GlobalConfig.userId;
- initSuccessCallBackData.passwordRequired = GlobalConfig.passwordRequired;
- initSuccessCallBackData.classType = GlobalConfig.classType || ApeConsts.CLASS_TYPE_INTERACT;
loger.log('加入会议成功');
- console.log(initSuccessCallBackData);
+ console.log(joinClassSuccessCallBackData);
//加入会议成功,广播消息
- this._emit(MessageTypes.CLASS_JOIN_SUCCESS,initSuccessCallBackData);
-
-/* //返回给客户数据
- if (_joinClassSuccessCallBackFun) {
- _joinClassSuccessCallBackFun(initSuccessCallBackData);
- }*/
+ this._emit(MessageTypes.CLASS_JOIN_SUCCESS,joinClassSuccessCallBackData);
}
//Sass删除文档数据
@@ -746,6 +674,11 @@ export default class MessageEntrance extends Emiter {
}
_getVideoPublishPath(_param){
+ if(!_mcu.connected){
+ loger.warn(GlobalConfig.getCurrentStatus());
+ return;
+ }
+
if(_video_ape){
return _video_ape.getPublishVideoPath(_param);
}
@@ -801,6 +734,10 @@ export default class MessageEntrance extends Emiter {
}
_getPublishAudioPath(_param){
+ if(!_mcu.connected){
+ loger.warn(GlobalConfig.getCurrentStatus());
+ return;
+ }
if(_audio_ape){
return _audio_ape.getAudioPublishPath(_param);
}
diff --git a/src/GlobalConfig.js b/src/GlobalConfig.js
index d1e3028..cac9c54 100644
--- a/src/GlobalConfig.js
+++ b/src/GlobalConfig.js
@@ -272,7 +272,7 @@ GlobalConfig.hasCamera=false;//摄像头是否可用
GlobalConfig.hasMicrophone=false;//麦克风是否可用
GlobalConfig.deviceType=0; //设备类型 0:电脑 1:安卓 2:ios
-GlobalConfig.userIP="";//用户当前IP
+GlobalConfig.userIp="";//用户当前IP
GlobalConfig.userId=0;
GlobalConfig.userName="";
@@ -326,4 +326,9 @@ GlobalConfig.musicListPrepare=[];//提提前上传的music集合
GlobalConfig.rsList=[];
+GlobalConfig.country ="";//国家
+GlobalConfig.city ="";//城市
+GlobalConfig.province = "";//服务商
+GlobalConfig.isp ="";//服务商
+
export default GlobalConfig;
diff --git a/src/Sass.js b/src/Sass.js
index 2b2c985..a148de6 100644
--- a/src/Sass.js
+++ b/src/Sass.js
@@ -4,6 +4,9 @@ import MessageTypes from 'MessageTypes';
import GlobalConfig from 'GlobalConfig';
import MD5 from "md5";
import ApeConsts from 'apes/ApeConsts';
+import iphunter from 'iphunter';
+
+import fetchJsonp from 'fetch-jsonp';
// 日志对象
const loger = Loger.getLoger('Sass');
@@ -384,23 +387,23 @@ class Sass extends Emiter {
//保存录制的信息,主要是录制文件的名称,必须和MCU录制的文件名相同
saveClassRecordContrlInfo(_param) {
loger.log('保存开始录制信息');
- let key = "3mang123A";
- let siteID = GlobalConfig.siteId;
+ let key = "3mang123A";
+ let siteID = GlobalConfig.siteId;
let meetingID = GlobalConfig.classId;
- let userID = GlobalConfig.userId;
- let userName = GlobalConfig.userName;
+ let userID = GlobalConfig.userId;
+ let userName = GlobalConfig.userName;
let meetingName = GlobalConfig.className;
- let startTime =GlobalConfig.classBeginTime;
- let endTime = GlobalConfig.classEndTime;
- let playUrl = "";
- let streamName = GlobalConfig.recordFileName;
- let confRecordFileName=GlobalConfig.recordFileName;
- let downloadUrl = "";
- let recordStatus = GlobalConfig.classStatus;
- let recordTimestamp =GlobalConfig.classTimestamp;
+ let startTime = GlobalConfig.classBeginTime;
+ let endTime = GlobalConfig.classEndTime;
+ let playUrl = "";
+ let streamName = GlobalConfig.recordFileName;
+ let confRecordFileName = GlobalConfig.recordFileName;
+ let downloadUrl = "";
+ let recordStatus = GlobalConfig.classStatus;
+ let recordTimestamp = GlobalConfig.classTimestamp;
- let timestamp = new Date().getTime();;
- let authId = MD5(key + siteID + meetingID + timestamp);
+ let timestamp = new Date().getTime();
+ let authId = MD5(key + siteID + meetingID + timestamp);
let url = `http://${confInfo.portal}/3m/recordingMeeting/insertRecordingMeeting.do?siteID=${siteID}&meetingID=${meetingID}&userID=${userID}&userName=${userName}&meetingName=${meetingName}&startTime=${startTime}&endTime=${endTime}&playUrl=${playUrl}&streamName=${streamName}&downloadUrl=${downloadUrl}&configFile=${confRecordFileName}×tamp=${timestamp}&recordTimestamp=${recordTimestamp}&authId=${authId}`;
loger.log('saveClassRecordContrlInfo', url);
@@ -420,7 +423,7 @@ class Sass extends Emiter {
loger.log('保存开始录制信息 完成');
this._emit(Sass.CLASS_SAVE_RECORD_INFO_SUCCESS, _param);
} else {
- loger.warn('保存开始录制信息 失败.',ret);
+ loger.warn('保存开始录制信息 失败.', ret);
}
})
.catch(err => {
@@ -428,7 +431,6 @@ class Sass extends Emiter {
});
}
-
}
Sass.prototype.SUCCESS = Sass.SUCCESS = 'Sass_success';
diff --git a/src/ServerCheck.js b/src/ServerCheck.js
new file mode 100644
index 0000000..1a491d9
--- /dev/null
+++ b/src/ServerCheck.js
@@ -0,0 +1,276 @@
+import Emiter from 'Emiter';
+import Loger from 'Loger';
+import MessageTypes from 'MessageTypes';
+import GlobalConfig from 'GlobalConfig';
+import MD5 from "md5";
+import ApeConsts from 'apes/ApeConsts';
+import iphunter from 'iphunter';
+import Server from "config/Server";
+import fetchJsonp from 'fetch-jsonp';
+
+// 日志对象
+const loger = Loger.getLoger('ServerCheck');
+
+//ip选点流程的状态
+let isRequestMcuCallback = false;//是否获取最佳mcu返回
+let isRequestMsCallback = false;//是否获取ms最佳返回
+let isTestFromSass=false;
+let isTestFromServer=false;
+
+let tempMcuIp="";
+let tempMcuPort="";
+let tempMsIp="";
+let tempMsPort="";
+class ServerCheck extends Emiter {
+ constructor() {
+ super();
+
+ }
+
+ //根据userIp获取ip相关的信息,参数是userIp
+ getUserIpInfo(token, userIp) {
+ //重置ip选点流程状态
+ isRequestMcuCallback = false;
+ isRequestMsCallback = false;
+ isTestFromSass=false;
+ isTestFromServer=false;
+
+ let userIpInfo = new Object;
+ userIpInfo.ret = -1;
+
+ let ip = userIp;
+ let md5Str = MD5("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3");//("addr=" + ip + "&token=b657c3507b324353e09c1958ee956a98efceb3e3"),转成MD5
+ let timestamp = new Date().getTime();
+ let location = `http://ipapi.ipip.net/find?addr=${ip}&sid=14&uid=5237&sig=${md5Str}&_=${timestamp}`;
+ loger.log('获取IP信息 ', userIp, location);
+
+ fetchJsonp(location, {
+ timeout: 3000,
+ }).then(function (response) {
+ return response.json()
+ }).then(function (json) {
+ loger.log('获取IP信息返回', json)
+ if (json) {
+ userIpInfo.ret = json.ret;
+ userIpInfo.country = json.data[0];//国家
+ userIpInfo.province = json.data[1];//省份
+ userIpInfo.city = json.data[2];//城市
+ userIpInfo.isp = json.data[4];//运营商
+ }
+ this.serverGetUserIpInfoCallback(userIpInfo);
+ }.bind(this)).catch(function (ex) {
+ loger.log('获取IP信息失败', ex.message)
+ this.serverGetUserIpInfoCallback(userIpInfo);
+ }.bind(this));
+ }
+
+ //获取ip信息返回
+ serverGetUserIpInfoCallback(userIpInfo) {
+ loger.log("获取IP详情,开始处理", userIpInfo);
+ if (userIpInfo.ret == "ok") {
+ GlobalConfig.country = userIpInfo.country;//国家
+ GlobalConfig.city = userIpInfo.city;//城市
+ GlobalConfig.province = userIpInfo.province;//服务商
+ GlobalConfig.isp = userIpInfo.isp;//服务商
+ loger.log("获取ip详情成功,country:" + GlobalConfig.country + ",city:" + GlobalConfig.city + ",isp:" + GlobalConfig.isp);
+ this._chooseBestIpFromServer();
+ }
+ else {
+ loger.log("获取ip详情失败");
+ this._chooseBestIpFromSassParam();
+ }
+ }
+
+ //从IPIP服务列表中选择最快的IP
+ _chooseBestIpFromServer() {
+ loger.log("从IPIP服务列表中选择最快的IP");
+ isRequestMcuCallback=false;
+ isRequestMsCallback=false;
+ isTestFromServer=true;
+ isTestFromSass=false;
+
+ let mcuIpGroup =this._returnServerMS();
+ let msIpGroup = this._returnServerMCU();
+ this.getBestMcuServer(mcuIpGroup);
+ this.getBestMsServer(msIpGroup);
+ }
+ //从Sass返回的msList mcuList中选点
+ _chooseBestIpFromSassParam() {
+ loger.log("从Sass服务列表中选择最快的IP");
+ isRequestMcuCallback=false;
+ isRequestMsCallback=false;
+ isTestFromServer=true;
+ isTestFromSass=true;
+ //MCU
+ let mcuIpGroup = [];
+ let speedTestPort = ':8080';//测速端口统一
+ for (let i = 0; i < GlobalConfig.mcuList.length; i++) {
+ let ipPort = GlobalConfig.mcuList[i].ip+speedTestPort;
+ mcuIpGroup.push(ipPort)
+ }
+ this.getBestMcuServer(mcuIpGroup);
+
+
+ //MS
+ let msIpGroup = [];
+ for (let i = 0; i < GlobalConfig.msList.length; i++) {
+ let ipPort = GlobalConfig.msList[i].ip+speedTestPort;
+ msIpGroup.push(ipPort)
+ }
+ this.getBestMsServer(msIpGroup);
+ }
+
+
+ //获取最快的MCU服务器地址,参数是一个ip数组
+ getBestMcuServer(_param) {
+ loger.log('getBestMcuServer ', _param);
+ if(_param==null||_param.length<1){
+ this._getBestMcuServerCallbackHandler("")
+ return;
+ }
+ iphunter(_param, function (fatest_ip_response) {
+ if (!fatest_ip_response) {
+ loger.warn('getBestMcuServer -> nothing!');
+ this._getBestMcuServerCallbackHandler("")
+ } else {
+ loger.log('getBestMcuServer done -> ', fatest_ip_response);
+ this._getBestMcuServerCallbackHandler(fatest_ip_response)
+ }
+ }.bind(this), 3000);
+ }
+
+ //获取最快的MS服务器地址,参数是一个ip数组
+ getBestMsServer(_param) {
+ loger.log('getBestMsServer ', _param);
+ if(_param==null||_param.length<1){
+ this._getBestMsServerCallbackHandler("")
+ return;
+ }
+ iphunter(_param, function (fatest_ip_response) {
+ if (!fatest_ip_response) {
+ loger.warn('getBestMsServer -> nothing!');
+ this._getBestMsServerCallbackHandler("");
+ } else {
+ loger.log('getBestMsServer done -> ', fatest_ip_response);
+ this._getBestMsServerCallbackHandler(fatest_ip_response);
+ }
+ }.bind(this), 3000);
+ }
+
+ _getBestMcuServerCallbackHandler(_data) {
+ loger.log("_getBestMcuServerCallbackHandler", _data);
+ if (isRequestMcuCallback) {
+ loger.log("_getBestMcuServerCallbackHandler,已经有返回");
+ return;
+ }
+ isRequestMcuCallback = true;
+ if (_data) {
+ let server = _data.split(":");
+ if (server[0]) {
+ tempMcuIp= server[0];
+ }
+ if (server[1]) {
+ tempMcuPort = server[1];
+ }
+ }
+ //loger.log("_getBestMcuServerCallbackHandler",tempMcuIp,tempMcuPort);
+ this._startConnectMcu();
+ }
+
+ _getBestMsServerCallbackHandler(_data) {
+ loger.log("_getBestMsServerCallbackHandler", _data);
+ if (isRequestMsCallback) {
+ loger.log("_getBestMsServerCallbackHandler,已经有返回");
+ return;
+ }
+ isRequestMsCallback = true;
+ if (_data) {
+ let server = _data.split(":");
+ if (server[0]) {
+ tempMsIp= server[0];
+ }
+ if (server[1]) {
+ tempMsPort= server[1];
+ }
+ }
+ //loger.log("_getBestMsServerCallbackHandler", tempMsIp,tempMsPort);
+ this._startConnectMcu();
+ }
+
+ //ip选点结束,开始连接MCU
+ _startConnectMcu() {
+ if (isRequestMcuCallback && isRequestMsCallback) {
+ if (isTestFromServer && !isTestFromSass) {
+ //从Server服务列表中选点结束,如果没有选到合适的,从Sass的列表中获取
+ if(!tempMcuIp||!tempMsIp){
+ this._chooseBestIpFromSassParam();
+ }else {
+ this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
+ }
+ } else {
+ //从Sass返回的服务列表中选点结束
+ this._emit(ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS);
+ }
+ } else {
+ loger.warn("_startConnectMcu 正在选点", isRequestMcuCallback, isRequestMsCallback);
+ }
+ }
+
+ //检测MCU连接地址
+ _returnServerMCU(country, province, ctiy, isp, jsona) {
+ let arr=[];
+ return arr;
+ }
+ //检测MS连接地址
+ //Config.ipInfo
+ _returnServerMS(country, province, ctiy, isp, jsona) {
+ let arr = [];
+ /* let acquire = false;
+ if (isp != "") {
+ for (let obja in jsona.MS.isp) {
+ if (isp.indexOf(obja.idc) != -1) {
+ arr = obja.mslist;
+ acquire = true;
+ break;
+ }
+ }
+ }
+ if (country == "中国" && !acquire) {
+ for (let obja in jsona.MS.china) {
+ if (obja.province.indexOf(province) != -1 && province != "") {
+ arr = obja.mslist;
+ acquire = true;
+ break;
+ }
+ }
+ if (!acquire) {
+ arr = jsona.MS.china[jsona.MS.china.length - 1].mslist;
+ acquire = true;
+ }
+ }
+
+ if (country != "中国" && country != "") {
+ for (let obja:Object in jsona.MS.international) {
+ if (obja.country.indexOf(country) != -1) {
+ arr = obja.mslist;
+ acquire = true;
+ break;
+ }
+ }
+ if (!acquire) {
+ arr = jsona.MS.international[jsona.MS.international.length - 1].mslist;
+ acquire = true;
+ }
+ }
+ else if (!acquire) {
+ arr = jsona.MS.Default;
+ }
+
+ loger.info("ms匹配结束;" + arr.length);*/
+ return arr;
+ }
+}
+
+ServerCheck.prototype.SEVER_CHECK_BEST_IP_SUCCESS = ServerCheck.SEVER_CHECK_BEST_IP_SUCCESS = 'severCheck_checkBestIpSuccess_message';//获取最快的MS地址
+export default new ServerCheck;
+
diff --git a/src/config/Server.js b/src/config/Server.js
new file mode 100644
index 0000000..0380d19
--- /dev/null
+++ b/src/config/Server.js
@@ -0,0 +1,610 @@
+/*
+ * 全局数据管理
+ * */
+import Loger from 'Loger';
+import ApeConsts from "apes/ApeConsts";
+
+let loger = Loger.getLoger('Server');
+import EngineUtils from 'EngineUtils';
+
+class Server {
+ constructor() {
+
+ }
+ static get serverList(){
+ return {
+ "共享地址": [
+ {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "221.228.109.123",
+ "name": "无锡"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ },
+ {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ },
+ {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ },
+ {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ },
+ {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }
+ ],
+ "局域网": [
+ {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "221.228.109.123",
+ "name": "无锡"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ },
+ {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ },
+ {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ },
+ {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ },
+ {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }
+ ],
+ "中国": {
+ "province": {
+ "香港": [
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ],
+ "台湾": [
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ]
+ },
+ "isp": {
+ "鹏博士": [
+ {
+ "ip": "124.192.148.139",
+ "name": "鹏博士"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ],
+ "长城": [
+ {
+ "ip": "124.192.148.139",
+ "name": "鹏博士"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ],
+ "移动": [
+ {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ },
+ {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ],
+ "电信": [
+ {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ },
+ {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ },
+ {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ],
+ "联通": [
+ {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ },
+ {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ },
+ {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ }
+ ]
+ },
+ "default": [
+ {
+ "ip": "106.3.130.98",
+ "name": "BGP多线3"
+ },
+ {
+ "ip": "221.228.109.123",
+ "name": "无锡"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ },
+ {
+ "ip": "liantong.ms.3mang.com",
+ "name": "联通专线"
+ },
+ {
+ "ip": "yidong.ms.3mang.com",
+ "name": "移动专线"
+ },
+ {
+ "ip": "dianxin.ms.3mang.com",
+ "name": "电信专线"
+ },
+ {
+ "ip": "lanxms.3mang.com",
+ "name": "国内专线"
+ },
+ {
+ "ip": "123.56.75.60",
+ "name": "BGP多线4"
+ },
+ {
+ "ip": "103.235.232.128",
+ "name": "BGP多线2"
+ },
+ {
+ "ip": "116.213.102.217",
+ "name": "BGP多线1"
+ }
+ ]
+ },
+ "美国": [
+ {
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ },
+ {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ },
+ {
+ "ip": "185.114.76.243",
+ "name": "全球通阿什本"
+ },
+ {
+ "ip": "159.100.196.217",
+ "name": "全球通迈阿密"
+ },
+ {
+ "ip": "185.114.77.84",
+ "name": "全球通圣何塞"
+ },
+ {
+ "ip": "159.100.195.230",
+ "name": "全球通洛杉矶"
+ },
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }
+ ],
+ "加拿大": [
+ {
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ },
+ {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ },
+ {
+ "ip": "185.114.76.243",
+ "name": "全球通阿什本"
+ },
+ {
+ "ip": "159.100.196.217",
+ "name": "全球通迈阿密"
+ },
+ {
+ "ip": "185.114.77.84",
+ "name": "全球通圣何塞"
+ },
+ {
+ "ip": "159.100.195.230",
+ "name": "全球通洛杉矶"
+ },
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }
+ ],
+ "墨西哥": [
+ {
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ },
+ {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ },
+ {
+ "ip": "185.114.76.243",
+ "name": "全球通阿什本"
+ },
+ {
+ "ip": "159.100.196.217",
+ "name": "全球通迈阿密"
+ },
+ {
+ "ip": "185.114.77.84",
+ "name": "全球通圣何塞"
+ },
+ {
+ "ip": "159.100.195.230",
+ "name": "全球通洛杉矶"
+ },
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ }
+ ],
+ "菲律宾": [
+ {
+ "ip": "223.255.248.122",
+ "name": "香港"
+ },
+ {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ },
+ {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ },
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ },
+ {
+ "ip": "185.114.78.179",
+ "name": "全球通新加坡"
+ },
+ {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ },
+ {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ },
+ {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ },
+ {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }
+ ],
+ "越南": [
+ {
+ "ip": "223.255.248.122",
+ "name": "香港"
+ },
+ {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ },
+ {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ },
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ },
+ {
+ "ip": "185.114.78.179",
+ "name": "全球通新加坡"
+ },
+ {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ },
+ {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ },
+ {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ },
+ {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }
+ ],
+ "泰国": [
+ {
+ "ip": "223.255.248.122",
+ "name": "香港"
+ },
+ {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ },
+ {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ },
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ },
+ {
+ "ip": "185.114.78.179",
+ "name": "全球通新加坡"
+ },
+ {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ },
+ {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ },
+ {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ },
+ {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ }
+ ],
+ "default": [
+ {
+ "ip": "bjms1.3mang.com",
+ "name": "全球通"
+ },
+ {
+ "ip": "qims.3mang.com",
+ "name": "全球通-备"
+ },
+ {
+ "ip": "38.83.109.142",
+ "name": "达拉斯"
+ },
+ {
+ "ip": "118.193.20.130",
+ "name": "日本"
+ },
+ {
+ "ip": "38.123.107.18",
+ "name": "德国"
+ },
+ {
+ "ip": "223.255.248.122",
+ "name": "香港"
+ },
+ {
+ "ip": "148.153.8.22",
+ "port": "1935",
+ "name": "纽约"
+ },
+ {
+ "ip": "38.121.61.242",
+ "port": "1935",
+ "name": "洛杉矶"
+ },
+ {
+ "ip": "118.193.24.38",
+ "name": "新加坡"
+ },
+ {
+ "ip": "159.100.194.120",
+ "name": "全球通日本"
+ },
+ {
+ "ip": "159.100.192.188",
+ "name": "全球通芝加哥"
+ },
+ {
+ "ip": "45.126.244.41",
+ "name": "全球通达拉斯"
+ },
+ {
+ "ip": "45.126.246.148",
+ "name": "全球通德国"
+ },
+ {
+ "ip": "192.158.245.185",
+ "name": "全球通韩国"
+ },
+ {
+ "ip": "103.29.35.63",
+ "name": "全球通印度"
+ },
+ {
+ "ip": "202.127.74.126",
+ "name": "全球通新加坡"
+ },
+ {
+ "ip": "199.59.231.234",
+ "name": "全球通香港"
+ },
+ {
+ "ip": "159.100.205.129",
+ "name": "全球通台湾"
+ }
+ ]
+ }
+ }
+}
+
+export default Server;
\ No newline at end of file