Greasy Fork is available in English.

Hook all ajax

it can hook all ajax

Ovu skriptu ne treba izravno instalirati. To je biblioteka za druge skripte koje se uključuju u meta direktivu // @require https://update.greasyfork.org/scripts/372706/1437261/Hook%20all%20ajax.js

  1. // ==UserScript==
  2. // @name Hook all ajax
  3. // @namespace https://gitee.com/HGJing/everthing-hook/
  4. // @version 0.1.018
  5. // @description it can hook all ajax
  6. // @include *
  7. // @author Cangshi
  8. // @match *://*/*
  9. // @run-at document-start
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function webpackUniversalModuleDefinition(root, factory) {
  14. if(typeof exports === 'object' && typeof module === 'object')
  15. module.exports = factory();
  16. else if(typeof define === 'function' && define.amd)
  17. define([], factory);
  18. else {
  19. var a = factory();
  20. for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
  21. }
  22. })(typeof self !== 'undefined' ? self : this, function() {
  23. return /******/ (() => { // webpackBootstrap
  24. /******/ var __webpack_modules__ = ([
  25. /* 0 */
  26. /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
  27.  
  28. "use strict";
  29. /**
  30. * ---------------------------
  31. * Time: 2017/9/20 18:33.
  32. * Author: Cangshi
  33. * View: http://palerock.cn
  34. * ---------------------------
  35. */
  36.  
  37.  
  38. const eUtils = __webpack_require__(1);
  39.  
  40. ~(function (global, factory) {
  41.  
  42. "use strict";
  43.  
  44. if ( true && typeof module.exports === "object") {
  45. var results = factory.bind(global)(global, eUtils, true) || [];
  46. var HookJS = {};
  47. results.forEach(function (part) {
  48. HookJS[part.name] = part.module;
  49. });
  50. module.exports = HookJS;
  51. } else {
  52. factory.bind(global)(global, eUtils);
  53. }
  54.  
  55. }(typeof window !== "undefined" ? window : this, function (_global, utils, noGlobal) {
  56. /**
  57. * @namespace EHook
  58. * @author Cangshi
  59. * @constructor
  60. * @see {@link https://palerock.cn/projects/006HDUuOhBj}
  61. * @license Apache License 2.0
  62. */
  63. var EHook = function () {
  64. var _autoId = 1;
  65. var _hookedMap = {};
  66. var _hookedContextMap = {};
  67. this._getHookedMap = function () {
  68. return _hookedMap;
  69. };
  70. this._getHookedContextMap = function () {
  71. return _hookedContextMap;
  72. };
  73. this._getAutoStrId = function () {
  74. return '__auto__' + _autoId++;
  75. };
  76. this._getAutoId = function () {
  77. return _autoId++;
  78. };
  79. };
  80. EHook.prototype = {
  81. /**
  82. * 获取一个对象的劫持id,若没有则创建一个
  83. * @param context
  84. * @return {*}
  85. * @private
  86. */
  87. _getHookedId: function (context) {
  88. var contextMap = this._getHookedContextMap();
  89. var hookedId = null;
  90. Object.keys(contextMap).forEach(key => {
  91. if (context === contextMap[key]) {
  92. hookedId = key;
  93. }
  94. });
  95. if (hookedId == null) {
  96. hookedId = this._getAutoStrId();
  97. contextMap[hookedId] = context;
  98. }
  99. return hookedId;
  100. },
  101. /**
  102. * 获取一个对象的劫持方法映射,若没有则创建一个
  103. * @param context
  104. * @return {*}
  105. * @private
  106. */
  107. _getHookedMethodMap: function (context) {
  108. var hookedId = this._getHookedId(context);
  109. var hookedMap = this._getHookedMap();
  110. var thisTask = hookedMap[hookedId];
  111. if (!utils.isExistObject(thisTask)) {
  112. thisTask = hookedMap[hookedId] = {};
  113. }
  114. return thisTask;
  115. },
  116. /**
  117. * 获取对应方法的hook原型任务对象,若没有则初始化一个。
  118. * @param context
  119. * @param methodName
  120. * @private
  121. */
  122. _getHookedMethodTask: function (context, methodName) {
  123. var thisMethodMap = this._getHookedMethodMap(context);
  124. var thisMethod = thisMethodMap[methodName];
  125. if (!utils.isExistObject(thisMethod)) {
  126. thisMethod = thisMethodMap[methodName] = {
  127. original: undefined,
  128. replace: undefined,
  129. task: {
  130. before: [],
  131. current: undefined,
  132. after: []
  133. }
  134. };
  135. }
  136. return thisMethod;
  137. },
  138. /**
  139. * 执行多个方法并注入一个方法和参数集合
  140. * @param context
  141. * @param methods
  142. * @param args
  143. * @return result 最后一次执行方法的有效返回值
  144. * @private
  145. */
  146. _invokeMethods: function (context, methods, args) {
  147. if (!utils.isArray(methods)) {
  148. return;
  149. }
  150. var result = null;
  151. utils.ergodicArrayObject(context, methods, function (_method) {
  152. if (!utils.isFunction(_method.method)) {
  153. return;
  154. }
  155. var r = _method.method.apply(this, args);
  156. if (r != null) {
  157. result = r;
  158. }
  159. });
  160. return result;
  161. },
  162. /**
  163. * 生成和替换劫持方法
  164. * @param parent
  165. * @param context
  166. * @param methodName {string}
  167. * @private
  168. */
  169. _hook: function (parent, methodName, context) {
  170. if (context === undefined) {
  171. context = parent;
  172. }
  173. var method = parent[methodName];
  174. var methodTask = this._getHookedMethodTask(parent, methodName);
  175. if (!methodTask.original) {
  176. methodTask.original = method;
  177. }
  178. if (utils.isExistObject(methodTask.replace) && utils.isFunction(methodTask.replace.method)) {
  179. parent[methodName] = methodTask.replace.method(methodTask.original);
  180. return;
  181. }
  182. var invokeMethods = this._invokeMethods;
  183. // 组装劫持函数
  184. var builder = new utils.FunctionBuilder(function (v) {
  185. return {
  186. result: undefined
  187. };
  188. });
  189. if (methodTask.task.before.length > 0) {
  190. builder.push(function (v) {
  191. invokeMethods(context || v.this, methodTask.task.before, [methodTask.original, v.arguments]);
  192. });
  193. }
  194. if (utils.isExistObject(methodTask.task.current) && utils.isFunction(methodTask.task.current.method)) {
  195. builder.push(function (v) {
  196. return {
  197. result: methodTask.task.current.method.call(context || v.this, parent, methodTask.original, v.arguments)
  198. }
  199. });
  200. } else {
  201. builder.push(function (v) {
  202. return {
  203. result: methodTask.original.apply(context || v.this, v.arguments)
  204. }
  205. });
  206. }
  207. if (methodTask.task.after.length > 0) {
  208. builder.push(function (v) {
  209. var args = [];
  210. args.push(methodTask.original);
  211. args.push(v.arguments);
  212. args.push(v.result);
  213. var r = invokeMethods(context || v.this, methodTask.task.after, args);
  214. return {
  215. result: (r != null ? r : v.result)
  216. };
  217. });
  218. }
  219. builder.push(function (v) {
  220. return {
  221. returnValue: v.result
  222. };
  223. });
  224. // var methodStr = '(function(){\n';
  225. // methodStr = methodStr + 'var result = undefined;\n';
  226. // if (methodTask.task.before.length > 0) {
  227. // methodStr = methodStr + 'invokeMethods(context, methodTask.task.before,[methodTask.original, arguments]);\n';
  228. // }
  229. // if (utils.isExistObject(methodTask.task.current) && utils.isFunction(methodTask.task.current.method)) {
  230. // methodStr = methodStr + 'result = methodTask.task.current.method.call(context, parent, methodTask.original, arguments);\n';
  231. // } else {
  232. // methodStr = methodStr + 'result = methodTask.original.apply(context, arguments);\n';
  233. // }
  234. // if (methodTask.task.after.length > 0) {
  235. // methodStr = methodStr + 'var args = [];args.push(methodTask.original);args.push(arguments);args.push(result);\n';
  236. // methodStr = methodStr + 'var r = invokeMethods(context, methodTask.task.after, args);result = (r!=null?r:result);\n';
  237. // }
  238. // methodStr = methodStr + 'return result;\n})';
  239. // 绑定劫持函数
  240. var resultFunc = builder.result();
  241. for (var proxyName in methodTask.original) {
  242. Object.defineProperty(resultFunc, proxyName, {
  243. get: function () {
  244. return methodTask.original[proxyName];
  245. },
  246. set: function (v) {
  247. methodTask.original[proxyName] = v;
  248. }
  249. })
  250. }
  251. resultFunc.prototype = methodTask.original.prototype;
  252. parent[methodName] = resultFunc;
  253. },
  254. /**
  255. * 劫持一个方法
  256. * @inner
  257. * @memberOf EHook
  258. * @param parent{Object} 指定方法所在的对象
  259. * @param methodName{String} 指定方法的名称
  260. * @param config{Object} 劫持的配置对象
  261. */
  262. hook: function (parent, methodName, config) {
  263. var hookedFailure = -1;
  264. // 调用方法的上下文
  265. var context = config.context !== undefined ? config.context : parent;
  266. if (parent[methodName] == null) {
  267. parent[methodName] = function () {
  268. }
  269. }
  270. if (!utils.isFunction(parent[methodName])) {
  271. return hookedFailure;
  272. }
  273. var methodTask = this._getHookedMethodTask(parent, methodName);
  274. var id = this._getAutoId();
  275. if (utils.isFunction(config.replace)) {
  276. methodTask.replace = {
  277. id: id,
  278. method: config.replace
  279. };
  280. hookedFailure = 0;
  281. }
  282. if (utils.isFunction(config.before)) {
  283. methodTask.task.before.push({
  284. id: id,
  285. method: config.before
  286. });
  287. hookedFailure = 0;
  288. }
  289. if (utils.isFunction(config.current)) {
  290. methodTask.task.current = {
  291. id: id,
  292. method: config.current
  293. };
  294. hookedFailure = 0;
  295. }
  296. if (utils.isFunction(config.after)) {
  297. methodTask.task.after.push({
  298. id: id,
  299. method: config.after
  300. });
  301. hookedFailure = 0;
  302. }
  303. if (hookedFailure === 0) {
  304. this._hook(parent, methodName, context);
  305. return id;
  306. } else {
  307. return hookedFailure;
  308. }
  309.  
  310. },
  311. /**
  312. * 劫持替换一个方法
  313. * @see 注意:该方法会覆盖指定劫持方法在之前所进行的一切劫持,也不能重复使用,并且不和hookAfter,hookCurrent,hookBefore共存,在同时使用的情况下,优先使用hookReplace而不是其他的方法
  314. * @inner
  315. * @memberOf EHook
  316. * @param parent{Object} 指定方法所在的对象
  317. * @param context{Object=} 回调方法的上下文
  318. * @param methodName{String} 指定方法的名称
  319. * @param replace {function} 回调方法,该方法的返回值便是替换的方法 回调参数及返回值:[ method:指定的原方法,类型:function return:规定被替换的方法内容,类型:function ]
  320. * @return {number} 该次劫持的id
  321. */
  322. hookReplace: function (parent, methodName, replace, context) {
  323. return this.hook(parent, methodName, {
  324. replace: replace,
  325. context: context
  326. });
  327. },
  328. /**
  329. * 在指定方法前执行
  330. * @inner
  331. * @memberOf EHook
  332. * @param parent{Object} 指定方法所在的对象
  333. * @param methodName{String} 指定方法的名称
  334. * @param before{function} 回调方法,该方法在指定方法运行前执行 回调参数:[ method:指定的原方法 args:原方法运行的参数(在此改变参数值会影响后续指定方法的参数值) ]
  335. * @param context{Object=} 回调方法的上下文
  336. * @returns {number} 劫持id(用于解除劫持)
  337. */
  338. hookBefore: function (parent, methodName, before, context) {
  339. return this.hook(parent, methodName, {
  340. before: before,
  341. context: context
  342. });
  343. },
  344. /**
  345. * 劫持方法的运行,在对制定方法进行该劫持的时候,指定方法不会主动执行,替换为执行参数中的current方法
  346. * @see 注意:该方法只能对指定方法进行一次劫持,若再次使用该方法劫持就会覆盖之前的劫持[可以和hookBefore,hookAfter共存,且hookBefore和hookAfter可以对同个指定方法多次劫持]
  347. * @inner
  348. * @memberOf EHook
  349. * @param parent{Object} 指定方法所在的对象
  350. * @param methodName{String} 指定方法的名称
  351. * @param current{function} 回调方法,该方法在指定方法被调用时执行 回调参数及返回值:[ parent:指定方法所在的对象,类型:object method:指定的原方法,类型:function args:原方法的参数,类型:array return:规定被劫持方法的返回值,类型:* ]
  352. * @param context{Object=} 回调方法的上下文
  353. * @returns {number} 劫持id(用于解除劫持)
  354. */
  355. hookCurrent: function (parent, methodName, current, context) {
  356. return this.hook(parent, methodName, {
  357. current: current,
  358. context: context
  359. });
  360. },
  361. /**
  362. * 在指定方法后执行
  363. * @inner
  364. * @memberOf EHook
  365. * @param parent{Object} 指定方法所在的对象
  366. * @param methodName{String} 指定方法的名称
  367. * @param after{function} 回调方法,该方法在指定方法运行后执行 回调参数及返回值:[ method:指定的原方法,类型:function args:原方法的参数,类型:array result:原方法的返回值,类型:* return:规定被劫持方法的返回值,类型:* ]
  368. * @param context{Object=} 回调方法的上下文
  369. * @returns {number} 劫持id(用于解除劫持)
  370. */
  371. hookAfter: function (parent, methodName, after, context) {
  372. return this.hook(parent, methodName, {
  373. after: after,
  374. context: context
  375. });
  376. },
  377. hookClass: function (parent, className, replace, innerName, excludeProperties) {
  378. var _this = this;
  379. var originFunc = parent[className];
  380. if (!excludeProperties) {
  381. excludeProperties = [];
  382. }
  383. excludeProperties.push('prototype');
  384. excludeProperties.push('caller');
  385. excludeProperties.push('arguments');
  386. innerName = innerName || '_innerHook';
  387. var resFunc = function () {
  388. this[innerName] = new originFunc();
  389. replace.apply(this, arguments);
  390. };
  391. this.hookedToString(originFunc, resFunc);
  392. this.hookedToProperties(originFunc, resFunc, true, excludeProperties);
  393. var prototypeProperties = Object.getOwnPropertyNames(originFunc.prototype);
  394. var prototype = resFunc.prototype = {
  395. constructor: resFunc
  396. };
  397. prototypeProperties.forEach(function (name) {
  398. if (name === 'constructor') {
  399. return;
  400. }
  401. var method = function () {
  402. if (originFunc.prototype[name] && utils.isFunction(originFunc.prototype[name])) {
  403. return originFunc.prototype[name].apply(this[innerName], arguments);
  404. }
  405. return undefined;
  406. };
  407. _this.hookedToString(originFunc.prototype[name], method);
  408. prototype[name] = method;
  409. });
  410. this.hookReplace(parent, className, function () {
  411. return resFunc;
  412. }, parent)
  413. },
  414. hookedToProperties: function (originObject, resultObject, isDefined, excludeProperties) {
  415. var objectProperties = Object.getOwnPropertyNames(originObject);
  416. objectProperties.forEach(function (property) {
  417. if (utils.contains(excludeProperties, property)) {
  418. return;
  419. }
  420. if (!isDefined) {
  421. resultObject[property] = originObject[property];
  422. } else {
  423. Object.defineProperty(resultObject, property, {
  424. configurable: false,
  425. enumerable: false,
  426. value: originObject[property],
  427. writable: false
  428. });
  429. }
  430. });
  431. },
  432. hookedToString: function (originObject, resultObject) {
  433. Object.defineProperties(resultObject, {
  434. toString: {
  435. configurable: false,
  436. enumerable: false,
  437. value: originObject.toString.bind(originObject),
  438. writable: false
  439. },
  440. toLocaleString: {
  441. configurable: false,
  442. enumerable: false,
  443. value: originObject.toLocaleString.bind(originObject),
  444. writable: false
  445. }
  446. })
  447. },
  448. /**
  449. * 劫持全局ajax
  450. * @inner
  451. * @memberOf EHook
  452. * @param methods {object} 劫持的方法
  453. * @return {*|number} 劫持的id
  454. */
  455. hookAjax: function (methods) {
  456. if (this.isHooked(_global, 'XMLHttpRequest')) {
  457. return;
  458. }
  459. var _this = this;
  460. var hookMethod = function (methodName) {
  461. if (utils.isFunction(methods[methodName])) {
  462. // 在执行方法之前hook原方法
  463. _this.hookBefore(this.xhr, methodName, methods[methodName]);
  464. }
  465. // 返回方法调用内部的xhr
  466. return this.xhr[methodName].bind(this.xhr);
  467. };
  468. var getProperty = function (attr) {
  469. return function () {
  470. return this.hasOwnProperty(attr + "_") ? this[attr + "_"] : this.xhr[attr];
  471. };
  472. };
  473. var setProperty = function (attr) {
  474. return function (f) {
  475. var xhr = this.xhr;
  476. var that = this;
  477. if (attr.indexOf("on") !== 0) {
  478. this[attr + "_"] = f;
  479. return;
  480. }
  481. if (methods[attr]) {
  482. xhr[attr] = function () {
  483. f.apply(xhr, arguments);
  484. };
  485. // on方法在set时劫持
  486. _this.hookBefore(xhr, attr, methods[attr]);
  487. // console.log(1,attr);
  488. // xhr[attr] = function () {
  489. // methods[attr](that) || f.apply(xhr, arguments);
  490. // }
  491. } else {
  492. xhr[attr] = f;
  493. }
  494. };
  495. };
  496. return this.hookReplace(_global, 'XMLHttpRequest', function (XMLHttpRequest) {
  497. var resFunc = function () {
  498. this.xhr = new XMLHttpRequest();
  499. for (var propertyName in this.xhr) {
  500. var property = this.xhr[propertyName];
  501. if (utils.isFunction(property)) {
  502. // hook 原方法
  503. this[propertyName] = hookMethod.bind(this)(propertyName);
  504. } else {
  505. Object.defineProperty(this, propertyName, {
  506. get: getProperty(propertyName),
  507. set: setProperty(propertyName)
  508. });
  509. }
  510. }
  511. // 定义外部xhr可以在内部访问
  512. this.xhr.xhr = this;
  513. };
  514. _this.hookedToProperties(XMLHttpRequest, resFunc, true);
  515. _this.hookedToString(XMLHttpRequest, resFunc);
  516. return resFunc
  517. });
  518. },
  519. /**
  520. * 劫持全局ajax
  521. * @param methods {object} 劫持的方法
  522. * @return {*|number} 劫持的id
  523. */
  524. hookAjaxV2: function (methods) {
  525. this.hookClass(window, 'XMLHttpRequest', function () {
  526.  
  527. });
  528. utils.ergodicObject(this, methods, function (method) {
  529.  
  530. });
  531. },
  532. /**
  533. * 解除劫持
  534. * @inner
  535. * @memberOf EHook
  536. * @param context 上下文
  537. * @param methodName 方法名
  538. * @param isDeeply {boolean=} 是否深度解除[默认为false]
  539. * @param eqId {number=} 解除指定id的劫持[可选]
  540. */
  541. unHook: function (context, methodName, isDeeply, eqId) {
  542. if (!context[methodName] || !utils.isFunction(context[methodName])) {
  543. return;
  544. }
  545. var methodTask = this._getHookedMethodTask(context, methodName);
  546. if (eqId) {
  547. if (this.unHookById(eqId)) {
  548. return;
  549. }
  550. }
  551. if (!methodTask.original) {
  552. delete this._getHookedMethodMap(context)[methodName];
  553. return;
  554. }
  555. context[methodName] = methodTask.original;
  556. if (isDeeply) {
  557. delete this._getHookedMethodMap(context)[methodName];
  558. }
  559. },
  560. /**
  561. * 通过Id解除劫持
  562. * @inner
  563. * @memberOf EHook
  564. * @param eqId
  565. * @returns {boolean}
  566. */
  567. unHookById: function (eqId) {
  568. var hasEq = false;
  569. if (eqId) {
  570. var hookedMap = this._getHookedMap();
  571. utils.ergodicObject(this, hookedMap, function (contextMap) {
  572. utils.ergodicObject(this, contextMap, function (methodTask) {
  573. methodTask.task.before = methodTask.task.before.filter(function (before) {
  574. hasEq = hasEq || before.id === eqId;
  575. return before.id !== eqId;
  576. });
  577. methodTask.task.after = methodTask.task.after.filter(function (after) {
  578. hasEq = hasEq || after.id === eqId;
  579. return after.id !== eqId;
  580. });
  581. if (methodTask.task.current && methodTask.task.current.id === eqId) {
  582. methodTask.task.current = undefined;
  583. hasEq = true;
  584. }
  585. if (methodTask.replace && methodTask.replace.id === eqId) {
  586. methodTask.replace = undefined;
  587. hasEq = true;
  588. }
  589. })
  590. });
  591. }
  592. return hasEq;
  593. },
  594. /**
  595. * 移除所有劫持相关的方法
  596. * @inner
  597. * @memberOf EHook
  598. * @param context 上下文
  599. * @param methodName 方法名
  600. */
  601. removeHookMethod: function (context, methodName) {
  602. if (!context[methodName] || !utils.isFunction(context[methodName])) {
  603. return;
  604. }
  605. this._getHookedMethodMap(context)[methodName] = {
  606. original: undefined,
  607. replace: undefined,
  608. task: {
  609. before: [],
  610. current: undefined,
  611. after: []
  612. }
  613. };
  614. },
  615. /**
  616. * 判断一个方法是否被劫持过
  617. * @inner
  618. * @memberOf EHook
  619. * @param context
  620. * @param methodName
  621. */
  622. isHooked: function (context, methodName) {
  623. var hookMap = this._getHookedMethodMap(context);
  624. return hookMap[methodName] !== undefined ? (hookMap[methodName].original !== undefined) : false;
  625. },
  626. /**
  627. * 保护一个对象使之不会被篡改
  628. * @inner
  629. * @memberOf EHook
  630. * @param parent
  631. * @param methodName
  632. */
  633. protect: function (parent, methodName) {
  634. Object.defineProperty(parent, methodName, {
  635. configurable: false,
  636. writable: false
  637. });
  638. },
  639. preventError: function (parent, methodName, returnValue, context) {
  640. this.hookCurrent(parent, methodName, function (m, args) {
  641. var value = returnValue;
  642. try {
  643. value = m.apply(this, args);
  644. } catch (e) {
  645. console.log('Error Prevented from method ' + methodName, e);
  646. }
  647. return value;
  648. }, context)
  649. },
  650. /**
  651. * 装载插件
  652. * @inner
  653. * @memberOf EHook
  654. * @param option
  655. */
  656. plugins: function (option) {
  657. if (utils.isFunction(option.mount)) {
  658. var result = option.mount.call(this, utils);
  659. if (typeof option.name === 'string') {
  660. _global[option.name] = result;
  661. }
  662. }
  663. }
  664. };
  665. if (_global.eHook && (_global.eHook instanceof EHook)) {
  666. return;
  667. }
  668. var eHook = new EHook();
  669. /**
  670. * @namespace AHook
  671. * @author Cangshi
  672. * @constructor
  673. * @see {@link https://palerock.cn/projects/006HDUuOhBj}
  674. * @license Apache License 2.0
  675. */
  676. var AHook = function () {
  677. this.isHooked = false;
  678. var autoId = 1;
  679. this._urlDispatcherList = [];
  680. this._getAutoId = function () {
  681. return autoId++;
  682. };
  683. };
  684. AHook.prototype = {
  685. /**
  686. * 执行配置列表中的指定方法组
  687. * @param xhr
  688. * @param methodName
  689. * @param args
  690. * @private
  691. */
  692. _invokeAimMethods: function (xhr, methodName, args) {
  693. var configs = utils.parseArrayByProperty(xhr.patcherList, 'config');
  694. var methods = [];
  695. utils.ergodicArrayObject(xhr, configs, function (config) {
  696. if (utils.isFunction(config[methodName])) {
  697. methods.push(config[methodName]);
  698. }
  699. });
  700. return utils.invokeMethods(xhr, methods, args);
  701. },
  702. /**
  703. * 根据url获取配置列表
  704. * @param url
  705. * @return {Array}
  706. * @private
  707. */
  708. _urlPatcher: function (url) {
  709. var patcherList = [];
  710. utils.ergodicArrayObject(this, this._urlDispatcherList, function (patcherMap, i) {
  711. if (utils.UrlUtils.urlMatching(url, patcherMap.patcher)) {
  712. patcherList.push(patcherMap);
  713. }
  714. });
  715. return patcherList;
  716. },
  717. /**
  718. * 根据xhr对象分发回调请求
  719. * @param xhr
  720. * @param fullUrl
  721. * @private
  722. */
  723. _xhrDispatcher: function (xhr, fullUrl) {
  724. var url = utils.UrlUtils.getUrlWithoutParam(fullUrl);
  725. xhr.patcherList = this._urlPatcher(url);
  726. },
  727. /**
  728. * 转换响应事件
  729. * @param e
  730. * @param xhr
  731. * @private
  732. */
  733. _parseEvent: function (e, xhr) {
  734. try {
  735. Object.defineProperties(e, {
  736. target: {
  737. get: function () {
  738. return xhr;
  739. }
  740. },
  741. srcElement: {
  742. get: function () {
  743. return xhr;
  744. }
  745. }
  746. });
  747. } catch (error) {
  748. console.warn('重定义返回事件失败,劫持响应可能失败');
  749. }
  750. return e;
  751. },
  752. /**
  753. * 解析open方法的参数
  754. * @param args
  755. * @private
  756. */
  757. _parseOpenArgs: function (args) {
  758. return {
  759. method: args[0],
  760. fullUrl: args[1],
  761. url: utils.UrlUtils.getUrlWithoutParam(args[1]),
  762. params: utils.UrlUtils.getParamFromUrl(args[1]),
  763. async: args[2]
  764. };
  765. },
  766. /**
  767. * 劫持ajax 请求参数
  768. * @param argsObject
  769. * @param argsArray
  770. * @private
  771. */
  772. _rebuildOpenArgs: function (argsObject, argsArray) {
  773. argsArray[0] = argsObject.method;
  774. argsArray[1] = utils.UrlUtils.margeUrlAndParams(argsObject.url, argsObject.params);
  775. argsArray[2] = argsObject.async;
  776. },
  777. /**
  778. * 获取劫持方法的参数 [原方法,原方法参数,原方法返回值],剔除原方法参数
  779. * @param args
  780. * @return {*|Array.<T>}
  781. * @private
  782. */
  783. _getHookedArgs: function (args) {
  784. // 将参数中'原方法'剔除
  785. return Array.prototype.slice.call(args, 0).splice(1);
  786. },
  787. /**
  788. * 响应被触发时调用的方法
  789. * @param outerXhr
  790. * @param funcArgs
  791. * @private
  792. */
  793. _onResponse: function (outerXhr, funcArgs) {
  794. // 因为参数是被劫持的参数为[method(原方法),args(参数)],该方法直接获取参数并转换为数组
  795. var args = this._getHookedArgs(funcArgs);
  796. args[0][0] = this._parseEvent(args[0][0], outerXhr.xhr); // 强制事件指向外部xhr
  797. // 执行所有的名为hookResponse的方法组
  798. var results = this._invokeAimMethods(outerXhr, 'hookResponse', args);
  799. // 遍历结果数组并获取最后返回的有效的值作为响应值
  800. var resultIndex = -1;
  801. utils.ergodicArrayObject(outerXhr, results, function (res, i) {
  802. if (res != null) {
  803. resultIndex = i;
  804. }
  805. });
  806. if (resultIndex !== -1) {
  807. outerXhr.xhr.responseText_ = outerXhr.xhr.response_ = results[resultIndex];
  808. }
  809. },
  810. /**
  811. * 手动开始劫持
  812. * @inner
  813. * @memberOf AHook
  814. */
  815. startHook: function () {
  816. var _this = this;
  817. var normalMethods = {
  818. // 方法中的this指向内部xhr
  819. // 拦截响应
  820. onreadystatechange: function () {
  821. if (this.readyState == 4 && this.status == 200 || this.status == 304) {
  822. _this._onResponse(this, arguments);
  823. }
  824. },
  825. onload: function () {
  826. _this._onResponse(this, arguments);
  827. },
  828. onloadend: function () {
  829. if (this.readyState == 4) {
  830. _this._onResponse(this, arguments);
  831. }
  832. },
  833. // 拦截请求
  834. open: function () {
  835. var args = _this._getHookedArgs(arguments);
  836. var fullUrl = args[0][1];
  837. _this._xhrDispatcher(this, fullUrl);
  838. var argsObject = _this._parseOpenArgs(args[0]);
  839. this.openArgs = argsObject;
  840. _this._invokeAimMethods(this, 'hookRequest', [argsObject]);
  841. _this._rebuildOpenArgs(argsObject, args[0]);
  842. },
  843. send: function () {
  844. var args = _this._getHookedArgs(arguments);
  845. this.sendArgs = args;
  846. _this._invokeAimMethods(this, 'hookSend', args);
  847. }
  848. };
  849. // 设置总的hookId
  850. this.___hookedId = _global.eHook.hookAjax(normalMethods);
  851. this.isHooked = true;
  852. },
  853. /**
  854. * 注册ajaxUrl拦截
  855. * @inner
  856. * @memberOf AHook
  857. * @param urlPatcher
  858. * @param configOrRequest
  859. * @param response
  860. * @return {number}
  861. */
  862. register: function (urlPatcher, configOrRequest, response) {
  863. if (!urlPatcher) {
  864. return -1;
  865. }
  866. if (!utils.isExistObject(configOrRequest) && !utils.isFunction(response)) {
  867. return -1;
  868. }
  869. var config = {};
  870. if (utils.isFunction(configOrRequest)) {
  871. config.hookRequest = configOrRequest;
  872. }
  873. if (utils.isFunction(response)) {
  874. config.hookResponse = response;
  875. }
  876. if (utils.isExistObject(configOrRequest)) {
  877. config = configOrRequest;
  878. }
  879. var id = this._getAutoId();
  880. this._urlDispatcherList.push({
  881. // 指定id便于后续取消
  882. id: id,
  883. patcher: urlPatcher,
  884. config: config
  885. });
  886. // 当注册一个register时,自动开始运行劫持
  887. if (!this.isHooked) {
  888. this.startHook();
  889. }
  890. return id;
  891. }
  892. // todo 注销 cancellation: function (registerId){};
  893. };
  894.  
  895. _global['eHook'] = eHook;
  896. _global['aHook'] = new AHook();
  897.  
  898. return [{
  899. name: 'eHook',
  900. module: eHook
  901. }, {
  902. name: 'aHook',
  903. module: _global['aHook']
  904. }]
  905.  
  906. }));
  907.  
  908. /***/ }),
  909. /* 1 */
  910. /***/ (function(module) {
  911.  
  912. (function (global, factory) {
  913.  
  914. "use strict";
  915.  
  916. if ( true && typeof module.exports === "object") {
  917. module.exports = factory(global, true);
  918. } else {
  919. factory(global);
  920. }
  921.  
  922. }(typeof window !== "undefined" ? window : this, function (_global, noGlobal) {
  923.  
  924. var map = Array.prototype.map;
  925. var forEach = Array.prototype.forEach;
  926. var reduce = Array.prototype.reduce;
  927.  
  928. var BaseUtils = {
  929. /**
  930. * 对象是否为数组
  931. * @param arr
  932. */
  933. isArray: function (arr) {
  934. return Array.isArray(arr) || Object.prototype.toString.call(arr) === "[object Array]";
  935. },
  936. /**
  937. * 判断是否为方法
  938. * @param func
  939. * @return {boolean}
  940. */
  941. isFunction: function (func) {
  942. if (!func) {
  943. return false;
  944. }
  945. return typeof func === 'function';
  946. },
  947. /**
  948. * 判断是否是一个有效的对象
  949. * @param obj
  950. * @return {*|boolean}
  951. */
  952. isExistObject: function (obj) {
  953. return obj && (typeof obj === 'object');
  954. },
  955. isString: function (str) {
  956. if (str === null) {
  957. return false;
  958. }
  959. return typeof str === 'string';
  960. },
  961. uniqueNum: 1000,
  962. /**
  963. * 根据当前时间戳生产一个随机id
  964. * @returns {string}
  965. */
  966. buildUniqueId: function () {
  967. var prefix = new Date().getTime().toString();
  968. var suffix = this.uniqueNum.toString();
  969. this.uniqueNum++;
  970. return prefix + suffix;
  971. }
  972. };
  973.  
  974. //
  975. var serviceProvider = {
  976. _parseDepends: function (depends) {
  977. var dependsArr = [];
  978. if (!BaseUtils.isArray(depends)) {
  979. return;
  980. }
  981. forEach.call(depends, function (depend) {
  982. if (BaseUtils.isString(depend)) {
  983. dependsArr.push(serviceProvider[depend.toLowerCase()]);
  984. }
  985. });
  986. return dependsArr;
  987. }
  988. };
  989.  
  990. var factory = function (name, depends, construction) {
  991. if (!BaseUtils.isFunction(construction)) {
  992. return;
  993. }
  994. serviceProvider[name.toLowerCase()] = construction.apply(this, serviceProvider._parseDepends(depends));
  995. };
  996.  
  997. var depend = function (depends, construction) {
  998. if (!BaseUtils.isFunction(construction)) {
  999. return;
  1000. }
  1001. construction.apply(this, serviceProvider._parseDepends(depends));
  1002. };
  1003.  
  1004. factory('BaseUtils', [], function () {
  1005. return BaseUtils;
  1006. });
  1007.  
  1008. // logger
  1009. factory('logger', [], function () {
  1010. return console;
  1011. });
  1012.  
  1013. // DateTimeUtils
  1014. factory('DateTimeUtils', ['logger'], function (logger) {
  1015. return {
  1016. /**
  1017. * 打印当前时间
  1018. */
  1019. printNowTime: function () {
  1020. var date = new Date();
  1021. console.log(this.pattern(date, 'hh:mm:ss:S'));
  1022. },
  1023. /**
  1024. * 格式化日期
  1025. * @param date
  1026. * @param fmt
  1027. * @returns {*}
  1028. */
  1029. pattern: function (date, fmt) {
  1030. var o = {
  1031. "M+": date.getMonth() + 1, //月份
  1032. "d+": date.getDate(), //日
  1033. "h+": date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, //小时
  1034. "H+": date.getHours(), //小时
  1035. "m+": date.getMinutes(), //分
  1036. "s+": date.getSeconds(), //秒
  1037. "q+": Math.floor((date.getMonth() + 3) / 3), //季度
  1038. "S": date.getMilliseconds() //毫秒
  1039. };
  1040. var week = {
  1041. "0": "/u65e5",
  1042. "1": "/u4e00",
  1043. "2": "/u4e8c",
  1044. "3": "/u4e09",
  1045. "4": "/u56db",
  1046. "5": "/u4e94",
  1047. "6": "/u516d"
  1048. };
  1049. if (/(y+)/.test(fmt)) {
  1050. fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  1051. }
  1052. if (/(E+)/.test(fmt)) {
  1053. fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[date.getDay() + ""]);
  1054. }
  1055. for (var k in o) {
  1056. if (new RegExp("(" + k + ")").test(fmt)) {
  1057. fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  1058. }
  1059. }
  1060. return fmt;
  1061. },
  1062. /**
  1063. * 以当前时间获取id
  1064. * @returns {number}
  1065. */
  1066. getCurrentId: function () {
  1067. var date = new Date();
  1068. return date.getTime();
  1069. },
  1070. /**
  1071. * 获取指定时间距离现在相差多久
  1072. * @param date {number|Date}
  1073. * @param isCeil{boolean=} 是否对结果向上取整,默认[false]
  1074. * @param type {string=} 单位可取值['day','month','year']默认'day'
  1075. * @returns {number}
  1076. */
  1077. getNowBetweenADay: function (date, isCeil, type) {
  1078. if (!type) {
  1079. type = 'day'
  1080. }
  1081. if (typeof date === 'number') {
  1082. date = new Date(date);
  1083. }
  1084. if (!(date instanceof Date)) {
  1085. throw new TypeError('该参数类型必须是Date')
  1086. }
  1087. var time = date.getTime();
  1088. var now = new Date();
  1089. var nowTime = now.getTime();
  1090. if (nowTime - time < 0) {
  1091. logger.warn('需要计算的时间必须在当前时间之前');
  1092. }
  1093. var result = 0;
  1094. switch (type) {
  1095. default:
  1096. case 'day':
  1097. result = (nowTime - time) / (1000 * 60 * 60 * 24);
  1098. break;
  1099. case 'month':
  1100. var yearDifference = now.getFullYear() - date.getFullYear();
  1101. if (yearDifference > 0) {
  1102. result += yearDifference * 12;
  1103. }
  1104. result += now.getMonth() - date.getMonth();
  1105. break;
  1106. case 'year':
  1107. result += now.getFullYear() - date.getFullYear();
  1108. break;
  1109. }
  1110. if (!isCeil) {
  1111. return Math.floor(result);
  1112. } else {
  1113. if (result === 0 && isCeil) {
  1114. result = 1;
  1115. }
  1116. return Math.ceil(result);
  1117. }
  1118. }
  1119. }
  1120. });
  1121.  
  1122. // ArrayUtils
  1123. factory('ArrayUtils', ['BaseUtils'], function (BaseUtils) {
  1124. return {
  1125. isArrayObject: function (arr) {
  1126. return BaseUtils.isArray(arr);
  1127. },
  1128. /**
  1129. * 遍历数组
  1130. * @param context {Object}
  1131. * @param arr {Array}
  1132. * @param cb {Function} 回调函数
  1133. */
  1134. ergodicArrayObject: function (context, arr, cb) {
  1135. if (!context) {
  1136. context = _global;
  1137. }
  1138. if (!BaseUtils.isArray(arr) || !BaseUtils.isFunction(cb)) {
  1139. return;
  1140. }
  1141. for (var i = 0; i < arr.length; i++) {
  1142. var result = cb.call(context, arr[i], i);
  1143. if (result && result === -1) {
  1144. break;
  1145. }
  1146. }
  1147. },
  1148. /**
  1149. * 获取数组对象的一个属性发起动作
  1150. * @param context {Object}
  1151. * @param arr {Array}
  1152. * @param propertyName {String}
  1153. * @param cb {Function}
  1154. * @param checkProperty {boolean} 是否排除不拥有该属性的对象[default:true]
  1155. */
  1156. getPropertyDo: function (context, arr, propertyName, cb, checkProperty) {
  1157. if (checkProperty === null) {
  1158. checkProperty = true;
  1159. }
  1160. this.ergodicArrayObject(context, arr, function (ele) {
  1161. if (!checkProperty || ele.hasOwnProperty(propertyName)) {
  1162. cb.call(context, ele[propertyName], ele);
  1163. }
  1164. })
  1165. },
  1166. /**
  1167. * [私有方法]将多个键值对对象转换为map
  1168. * @param arr {Array}
  1169. * @returns {{}}
  1170. */
  1171. parseKeyValue: function (arr) {
  1172. var map = {};
  1173. if (!(BaseUtils.isArray(arr))) {
  1174. return map;
  1175. }
  1176. this.ergodicArrayObject(this, arr, function (ele) {
  1177. if (ele.key === null) {
  1178. return;
  1179. }
  1180. if (!map.hasOwnProperty(ele.key)) {
  1181. map[ele.key] = ele.value;
  1182. }
  1183. });
  1184. return map;
  1185. },
  1186. /**
  1187. * 获取数组的哈希码
  1188. * @param arr {Array}
  1189. * @returns {number}
  1190. */
  1191. getHashCode: function (arr) {
  1192. var str = arr.toString();
  1193. var hash = 31;
  1194. if (str.length === 0) return hash;
  1195. for (var i = 0; i < str.length; i++) {
  1196. var char = str.charCodeAt(i);
  1197. hash = ((hash << 5) - hash) + char;
  1198. hash = hash & hash; // Convert to 32bit integer
  1199. }
  1200. return hash;
  1201. },
  1202. /**
  1203. * 通过数组中每个对象的指定属性生成一个新数组
  1204. * @param arr {Array}
  1205. * @param propertyName {String}
  1206. */
  1207. parseArrayByProperty: function (arr, propertyName) {
  1208. var result = [];
  1209. if (!this.isArrayObject(arr)) {
  1210. return result;
  1211. }
  1212. this.getPropertyDo(this, arr, propertyName, function (value) {
  1213. result.push(value);
  1214. }, true);
  1215. return result;
  1216. },
  1217. /**
  1218. * 数组对象是否包含一个对象
  1219. * @param arr {Array}
  1220. * @param obj
  1221. * @param cb {function=}
  1222. * @returns {boolean}
  1223. */
  1224. isContainsObject: function (arr, obj, cb) {
  1225. var isContainsObject = false;
  1226. this.ergodicArrayObject(this, arr, function (value, i) {
  1227. if (obj === value) {
  1228. isContainsObject = true;
  1229. if (BaseUtils.isFunction(cb)) {
  1230. cb.call(_global, i);
  1231. }
  1232. return -1;
  1233. }
  1234. });
  1235. return isContainsObject;
  1236. },
  1237. /**
  1238. * 获取数组中的最大值
  1239. * @param arr 若数组中的对象还是数组,则按里面数组的每个对象进行多级比较
  1240. * @param cb
  1241. * @returns {*}
  1242. */
  1243. getMaxInArray: function (arr, cb) {
  1244. var maxObject = null;
  1245. var maxIndex = -1;
  1246. while (maxObject === null && maxIndex < arr.length) {
  1247. maxObject = arr[++maxIndex]
  1248. }
  1249. for (var i = maxIndex + 1; i < arr.length; i++) {
  1250. // 若是比较对象都是数组,则对每个数组的第一个元素进行比较,若相同,则比较第二个元素
  1251. if (maxObject !== null && this.isArrayObject(maxObject) && this.isArrayObject(arr[i])) {
  1252. var classLength = maxObject.length;
  1253. var classLevel = 0;
  1254. // console.log(maxObject[classLevel],arr[i][classLevel]);
  1255. while (maxObject[classLevel] === arr[i][classLevel] && classLevel < classLength) {
  1256. classLevel++
  1257. }
  1258. if (maxObject[classLevel] !== null && maxObject[classLevel] < arr[i][classLevel]) {
  1259. maxObject = arr[i];
  1260. maxIndex = i;
  1261. }
  1262. continue;
  1263. }
  1264. if (maxObject !== null && maxObject < arr[i]) {
  1265. maxObject = arr[i];
  1266. maxIndex = i;
  1267. }
  1268. }
  1269. if (BaseUtils.isFunction(cb)) {
  1270. cb.call(this, maxObject, maxIndex);
  1271. }
  1272. return maxObject;
  1273. },
  1274. /**
  1275. * 获取数组中的总值
  1276. * @param arr{Array<number>}
  1277. * @param cb {function=}
  1278. */
  1279. getSumInArray: function (arr, cb) {
  1280. if (!this.isArrayObject(arr)) {
  1281. return;
  1282. }
  1283. var sum = 0;
  1284. var count = 0;
  1285. this.ergodicArrayObject(this, arr, function (value) {
  1286. if (typeof value === 'number' && !Number.isNaN(value)) {
  1287. sum += value;
  1288. count += 1;
  1289. }
  1290. });
  1291. if (BaseUtils.isFunction(cb)) {
  1292. cb.call(_global, sum, count);
  1293. }
  1294. return sum;
  1295. },
  1296. /**
  1297. * 获取数组中的平均值
  1298. * @param arr{Array<number>}
  1299. */
  1300. getAverageInArray: function (arr) {
  1301. var average = 0;
  1302. this.getSumInArray(arr, function (sum, i) {
  1303. i === 0 || (average = sum / i);
  1304. });
  1305. return average;
  1306. },
  1307. /**
  1308. * 为数组排序
  1309. * @param arr
  1310. * @param order
  1311. * @param sortSetting {object=}
  1312. */
  1313. sortingArrays: function (arr, order, sortSetting) {
  1314. if (!this.isArrayObject(arr)) {
  1315. return;
  1316. }
  1317. var DESC = 0;
  1318. var ASC = 1;
  1319. var thisArr = arr.slice(0);
  1320. var _thisAction = null;
  1321. // 解析配置
  1322. var isSetting = sortSetting && sortSetting.getComparedProperty &&
  1323. BaseUtils.isFunction(sortSetting.getComparedProperty);
  1324. if (isSetting) {
  1325. thisArr = sortSetting.getComparedProperty(arr);
  1326. }
  1327. switch (order) {
  1328. default :
  1329. case DESC:
  1330. _thisAction = thisArr.push;
  1331. break;
  1332. case ASC:
  1333. _thisAction = thisArr.unshift;
  1334. break;
  1335. }
  1336. var resultArr = [];
  1337. for (var j = 0; j < thisArr.length; j++) {
  1338. this.getMaxInArray(thisArr, function (max, i) {
  1339. delete thisArr[i];
  1340. _thisAction.call(resultArr, arr[i]);
  1341. });
  1342. }
  1343. if (sortSetting && sortSetting.createNewData) {
  1344. return resultArr.slice(0);
  1345. }
  1346. return resultArr;
  1347. },
  1348. /**
  1349. * 将类数组转化为数组
  1350. * @param arrLike 类数组对象
  1351. */
  1352. toArray: function (arrLike) {
  1353. if (!arrLike || arrLike.length === 0) {
  1354. return [];
  1355. }
  1356. // 非伪类对象,直接返回最好
  1357. if (!arrLike.length) {
  1358. return arrLike;
  1359. }
  1360. // 针对IE8以前 DOM的COM实现
  1361. try {
  1362. return [].slice.call(arrLike);
  1363. } catch (e) {
  1364. var i = 0,
  1365. j = arrLike.length,
  1366. res = [];
  1367. for (; i < j; i++) {
  1368. res.push(arrLike[i]);
  1369. }
  1370. return res;
  1371. }
  1372. },
  1373. /**
  1374. * 判断是否为类数组
  1375. * @param o
  1376. * @returns {boolean}
  1377. */
  1378. isArrayLick: function (o) {
  1379. if (o && // o is not null, undefined, etc.
  1380. typeof o === 'object' && // o is an object
  1381. isFinite(o.length) && // o.length is a finite number
  1382. o.length >= 0 && // o.length is non-negative
  1383. o.length === Math.floor(o.length) && // o.length is an integer
  1384. o.length < 4294967296) // o.length < 2^32
  1385. return true; // Then o is array-like
  1386. else
  1387. return false; // Otherwise it is not
  1388.  
  1389. },
  1390. /**
  1391. * 判断数组是否包含对象
  1392. * @param arr
  1393. * @param obj
  1394. */
  1395. contains: function (arr, obj) {
  1396. var contains = false;
  1397. this.ergodicArrayObject(this, arr, function (a) {
  1398. if (a === obj) {
  1399. contains = true;
  1400. return -1;
  1401. }
  1402. });
  1403. return contains;
  1404. }
  1405. }
  1406. });
  1407.  
  1408. // ObjectUtils
  1409. factory('ObjectUtils', ['ArrayUtils', 'BaseUtils'], function (ArrayUtils, BaseUtils) {
  1410. return {
  1411. /**
  1412. * 获取对象属性[支持链式表达式,如获取学生所在班级所在的学校(student.class.school):'class.school']
  1413. * @param obj
  1414. * @param linkProperty {string|Array} 属性表达式,获取多个属性则用数组
  1415. * @param cb {function=}
  1416. * @return 对象属性
  1417. */
  1418. readLinkProperty: function (obj, linkProperty, cb) {
  1419. var callback = null;
  1420. if (BaseUtils.isFunction(cb)) {
  1421. callback = cb;
  1422. }
  1423. if (typeof linkProperty === 'string') {
  1424. // 除去所有的空格
  1425. linkProperty = linkProperty.replace(/ /g, '');
  1426. // 不判断为空的值
  1427. if (linkProperty === '') {
  1428. return null;
  1429. }
  1430. // 若是以','隔开的伪数组,则转化为数组再进行操作
  1431. if (linkProperty.indexOf(',') !== -1) {
  1432. var propertyNameArr = linkProperty.split(',');
  1433. return this.readLinkProperty(obj, propertyNameArr, callback);
  1434. }
  1435. if (linkProperty.indexOf('.') !== -1) {
  1436. var names = linkProperty.split('.');
  1437. var iterationObj = obj;
  1438. var result = null;
  1439. ArrayUtils.ergodicArrayObject(this, names, function (name, i) {
  1440. iterationObj = this.readLinkProperty(iterationObj, name);
  1441. if (names[names.length - 1] === name && names.length - 1 === i) {
  1442. result = iterationObj;
  1443. if (callback) {
  1444. callback.call(_global, result, linkProperty);
  1445. }
  1446. }
  1447. // 终止对接下来的属性的遍历
  1448. if (typeof iterationObj === 'undefined') {
  1449. return -1;
  1450. }
  1451. });
  1452. return result;
  1453. }
  1454. var normalResult = null;
  1455. if (linkProperty.slice(linkProperty.length - 2) === '()') {
  1456. var func = linkProperty.slice(0, linkProperty.length - 2);
  1457. normalResult = obj[func]();
  1458. } else {
  1459. normalResult = obj[linkProperty];
  1460. }
  1461. if (normalResult === null) {
  1462. console.warn(obj, '的属性[\'' + linkProperty + '\']值未找到');
  1463. }
  1464. if (callback) {
  1465. callback.call(_global, normalResult, linkProperty);
  1466. }
  1467. return normalResult;
  1468. }
  1469. if (BaseUtils.isArray(linkProperty)) {
  1470. var results = [];
  1471. ArrayUtils.ergodicArrayObject(this, linkProperty, function (name) {
  1472. var value = this.readLinkProperty(obj, name);
  1473. results.push(value);
  1474. if (callback && name !== '') {
  1475. return callback.call(_global, value, name);
  1476. }
  1477. });
  1478. results.isMultipleResults = true;
  1479. return results;
  1480. }
  1481. },
  1482. /**
  1483. * 为对象属性赋值
  1484. * (同一个对象中不能够既有数字开头的属性名和普通属性名)
  1485. * @param obj
  1486. * @param linkProperty {string|Array} 属性表达式,多个属性则用数组
  1487. * @param value
  1488. */
  1489. createLinkProperty: function (obj, linkProperty, value) {
  1490. if (obj === null) {
  1491. obj = {};
  1492. }
  1493. if (typeof linkProperty === 'string') {
  1494. // 除去所有的空格
  1495. linkProperty = linkProperty.replace(/ /g, '');
  1496. // 不判断为空的值
  1497. if (linkProperty === '') {
  1498. throw new TypeError('对象属性名不能为空')
  1499. }
  1500. if (linkProperty.indexOf(',') !== -1) {
  1501. var propertyNameArr = linkProperty.split(',');
  1502. this.createLinkProperty(obj, propertyNameArr, value);
  1503. return obj;
  1504. }
  1505. if (linkProperty.indexOf('.') !== -1) {
  1506. var names = linkProperty.split('.');
  1507. if (!obj.hasOwnProperty(names[0])) {
  1508. obj[names[0]] = {}
  1509. }
  1510. // 判断属性名是否以数字开头(若是代表是一个数组)
  1511. if (!Number.isNaN(parseInt(names[0]))) {
  1512. if (!ArrayUtils.isArrayObject(obj)) {
  1513. obj = [];
  1514. }
  1515. }
  1516. var propertyObj = obj[names[0]];
  1517. var newProperties = names.slice(1, names.length);
  1518. var newLinkProperty = '';
  1519. ArrayUtils.ergodicArrayObject(this, newProperties, function (property, i) {
  1520. if (i < newProperties.length - 1) {
  1521. newLinkProperty = newLinkProperty + property + '.'
  1522. } else {
  1523. newLinkProperty = newLinkProperty + property;
  1524. }
  1525. });
  1526. obj[names[0]] = this.createLinkProperty(propertyObj, newLinkProperty, value);
  1527. return obj;
  1528. }
  1529. // 判断属性名是否以数字开头(若是代表是一个数组)
  1530. if (!Number.isNaN(parseInt(linkProperty))) {
  1531. if (!ArrayUtils.isArrayObject(obj)) {
  1532. obj = [];
  1533. }
  1534. }
  1535. obj[linkProperty] = value;
  1536. return obj;
  1537. } else if (BaseUtils.isArray(linkProperty)) {
  1538. ArrayUtils.ergodicArrayObject(this, linkProperty, function (link) {
  1539. obj = this.createLinkProperty(obj, link, value);
  1540. });
  1541. return obj;
  1542. }
  1543. },
  1544. /**
  1545. * 遍历对象属性
  1546. * @param context {object} 上下文
  1547. * @param obj {object} 遍历对象
  1548. * @param cb {function} 回调函数
  1549. * @param isReadInnerObject {boolean=} 是否遍历内部对象的属性
  1550. */
  1551. ergodicObject: function (context, obj, cb, isReadInnerObject) {
  1552. var keys = Object.keys(obj);
  1553. ArrayUtils.ergodicArrayObject(this, keys, function (propertyName) {
  1554. // 若内部对象需要遍历
  1555. var _propertyName = propertyName;
  1556. if (isReadInnerObject && obj[propertyName] !== null && typeof obj[propertyName] === 'object') {
  1557. this.ergodicObject(this, obj[propertyName], function (value, key) {
  1558. return cb.call(context, value, _propertyName + '.' + key);
  1559. }, true)
  1560. } else {
  1561. return cb.call(context, obj[propertyName], propertyName);
  1562. }
  1563. })
  1564. },
  1565. /**
  1566. * 当指定属性为空或不存在时执行回到函数;
  1567. * @param context {object} 上下文
  1568. * @param obj {object} 检测对象
  1569. * @param propertyNames{Array|string} 需要检测的属性名
  1570. * 可以检查多级属性如:'a.b.c.e',
  1571. * 多个属性使用数组,支持纯字符串多个属性用','隔开
  1572. * @param cb {function} 回调函数[参数:为空或不存在的属性名,返回值为'-1'时,跳过之后的回调函数]
  1573. */
  1574. whileEmptyObjectProperty: function (context, obj, propertyNames, cb) {
  1575. // 解析单个属性名
  1576. if (typeof propertyNames === 'string') {
  1577. // 除去所有的空格
  1578. propertyNames = propertyNames.replace(/ /g, '');
  1579. // 不判断为空的值
  1580. if (propertyNames === '') {
  1581. return;
  1582. }
  1583. // 若是以','隔开的伪数组,则转化为数组再进行操作
  1584. if (propertyNames.indexOf(',') !== -1) {
  1585. var propertyNameArr = propertyNames.split(',');
  1586. return this.whileEmptyObjectProperty(context, obj, propertyNameArr, cb);
  1587. }
  1588. // 若指定级联属性
  1589. if (propertyNames.indexOf('.') !== -1) {
  1590. var names = propertyNames.split('.');
  1591. var iterationObj = obj;
  1592. var result = null;
  1593. ArrayUtils.ergodicArrayObject(this, names, function (name) {
  1594. if (iterationObj && iterationObj.hasOwnProperty(name)) {
  1595. iterationObj = iterationObj[name];
  1596. } else {
  1597. result = cb.call(_global, propertyNames);
  1598. // 终止对接下来的属性的遍历
  1599. return -1;
  1600. }
  1601. });
  1602. return result;
  1603. }
  1604. // 正常流程
  1605. if (!obj.hasOwnProperty(propertyNames)) {
  1606. return cb.call(context, propertyNames);
  1607. }
  1608. if (obj[propertyNames] === null || obj[propertyNames] === '') {
  1609. return cb.call(context, propertyNames);
  1610. }
  1611. } else if (BaseUtils.isArray(propertyNames)) {
  1612. // 解析数组
  1613. var _this = this;
  1614. ArrayUtils.ergodicArrayObject(this, propertyNames, function (propertyName) {
  1615. // 递归调用
  1616. return _this.whileEmptyObjectProperty(context, obj, propertyName, cb);
  1617. })
  1618. }
  1619. },
  1620. whileEmptyObjectPropertyV2: function (context, obj, propertyNames, cb) {
  1621. this.readLinkProperty(obj, propertyNames, function (value, propertyName) {
  1622. if (value === null || value === '' || parseInt(value) < 0) {
  1623. return cb.call(context, propertyName);
  1624. }
  1625. })
  1626. },
  1627. /**
  1628. * 克隆对象[只克隆属性,不克隆原型链]
  1629. * @param obj {*}
  1630. */
  1631. cloneObject: function (obj) {
  1632. var newObj = {};
  1633. // 判断是否为基本数据类型,若是则直接返回
  1634. if (typeof obj === 'string' ||
  1635. typeof obj === 'number' ||
  1636. typeof obj === 'undefined' ||
  1637. typeof obj === 'function' ||
  1638. typeof obj === 'boolean') {
  1639. return obj;
  1640. }
  1641. // 判断是否是数组
  1642. if (BaseUtils.isArray(obj)) {
  1643. newObj = [];
  1644. // 遍历数组并递归调用该方法获取数组内部对象的克隆对象并push到新数组
  1645. ArrayUtils.ergodicArrayObject(this, obj, function (arrObjValue) {
  1646. newObj.push(this.cloneObject(arrObjValue));
  1647. })
  1648. } else if (typeof obj === 'object') {
  1649. // 当目标为一般对象时即 typeof 为 object
  1650. if (obj === null) {
  1651. // 当克隆对象为空时,返回空
  1652. return null;
  1653. }
  1654. // 遍历对象的属性并调用递归方法获得该属性对应的对象的克隆对象并将其重新赋值到该属性
  1655. this.ergodicObject(this, obj, function (value, key) {
  1656. newObj[key] = this.cloneObject(value);
  1657. });
  1658. }
  1659. return newObj;
  1660. },
  1661. /**
  1662. * 获取对象的哈希码
  1663. * @param obj {Object}
  1664. * @returns {number}
  1665. */
  1666. getObjHashCode: function (obj) {
  1667. var str = JSON.stringify(obj);
  1668. var hash = 0, i, chr, len;
  1669. console.log(str)
  1670. console.log(hash)
  1671. if (str.length === 0) return hash;
  1672. for (i = 0, len = str.length; i < len; i++) {
  1673. chr = str.charCodeAt(i);
  1674. hash = ((hash << 5) - hash) + chr;
  1675. hash |= 0; // Convert to 32bit integer
  1676. }
  1677. console.log(str)
  1678. console.log(hash)
  1679. return hash;
  1680. },
  1681. /**
  1682. * 扩展对象属性
  1683. * @param obj 原对象
  1684. * @param extendedObj 被扩展的对象
  1685. * @param isCover {boolean=} 扩展的属性和原来属性冲突时是否覆盖 默认[false]
  1686. * @param isClone {boolean=} 是否返回一个新的对象,默认[false]返回扩展后的原对象
  1687. */
  1688. expandObject: function (obj, extendedObj, isCover, isClone) {
  1689. var resultObj = obj;
  1690. if (isClone) {
  1691. resultObj = this.cloneObject(obj);
  1692. }
  1693. this.ergodicObject(this, extendedObj, function (value, key) {
  1694. if (isCover && this.readLinkProperty(resultObj, key) !== null) {
  1695. return;
  1696. }
  1697. resultObj = this.createLinkProperty(resultObj, key, value);
  1698. }, true);
  1699. return resultObj;
  1700. },
  1701. /**
  1702. * 为数组排序,当数组中的元素为对象时,根据指定对象的属性名进行排序
  1703. * @param arr 数组
  1704. * @param propertyName 属性名(当有多个属性名时,为多级排序)
  1705. * @param order 升降序
  1706. * @returns {*}
  1707. */
  1708. sortingArrayByProperty: function (arr, propertyName, order) {
  1709. var _this = this;
  1710. var sortSetting = {
  1711. // 是否创建新数据
  1712. createNewData: false,
  1713. // 通过该方法获取数组中每个对象中用来比较的属性
  1714. getComparedProperty: function (arr) {
  1715. var compareArr = [];
  1716. ArrayUtils.ergodicArrayObject(_this, arr, function (obj, i) {
  1717. if (typeof obj !== 'object') {
  1718. compareArr.push(obj);
  1719. } else {
  1720. var compareValue = this.readLinkProperty(obj, propertyName);
  1721. if (compareValue !== null) {
  1722. compareArr.push(compareValue);
  1723. } else {
  1724. compareArr.push(obj);
  1725. }
  1726. }
  1727. });
  1728. return compareArr.slice(0);
  1729. }
  1730. };
  1731. return ArrayUtils.sortingArrays(arr, order, sortSetting);
  1732. },
  1733. /**
  1734. * 转话为目标的实例
  1735. * @param constructor {function} 构造函数
  1736. * @param obj {object|Array}判断的对象
  1737. * @param defaultProperty {object=}
  1738. */
  1739. toAimObject: function (obj, constructor, defaultProperty) {
  1740. if (BaseUtils.isArray(obj)) {
  1741. var originArr = [];
  1742. ArrayUtils.ergodicArrayObject(this, obj, function (value) {
  1743. originArr.push(this.toAimObject(value, constructor, defaultProperty));
  1744. });
  1745. return originArr;
  1746. } else if (typeof obj === 'object') {
  1747. if (defaultProperty) {
  1748. this.ergodicObject(this, defaultProperty, function (value, key) {
  1749. if (obj[key] === null) {
  1750. obj[key] = value;
  1751. }
  1752. });
  1753. }
  1754. if (obj instanceof constructor) {
  1755. return obj;
  1756. }
  1757. var originObj = obj;
  1758. while (originObj.__proto__ !== null && originObj.__proto__ !== Object.prototype) {
  1759. originObj = originObj.__proto__;
  1760. }
  1761. originObj.__proto__ = constructor.prototype;
  1762. return originObj;
  1763. }
  1764. },
  1765. /**
  1766. * 将数组中结构类似对象指定属性融合为一个数组
  1767. * @param arr {Array}
  1768. * @param propertyNames
  1769. */
  1770. parseTheSameObjectPropertyInArray: function (arr, propertyNames) {
  1771. var result = {};
  1772. var temp = {};
  1773. ArrayUtils.ergodicArrayObject(this, arr, function (obj) {
  1774. // 获取想要得到的所有属性,以属性名为键值存储到temp中
  1775. this.readLinkProperty(obj, propertyNames, function (value, property) {
  1776. if (!temp.hasOwnProperty(property) || !(BaseUtils.isArray(temp[property]))) {
  1777. temp[property] = [];
  1778. }
  1779. temp[property].push(value);
  1780. });
  1781. });
  1782. // 遍历temp获取每个键值中的值,并单独取出
  1783. this.ergodicObject(this, temp, function (value, key) {
  1784. result = this.createLinkProperty(result, key, value);
  1785. });
  1786. return this.cloneObject(result);
  1787. },
  1788. /**
  1789. * 将数组中结构类似对象指定属性融合为一个数组
  1790. * @param arr {Array}
  1791. */
  1792. parseTheSameObjectAllPropertyInArray: function (arr) {
  1793. if (!ArrayUtils.isArrayObject(arr) || arr.length < 1) {
  1794. return;
  1795. }
  1796. // 获取一个对象的所有属性,包括内部对象的属性
  1797. var propertyNames = [];
  1798. this.ergodicObject(this, arr[0], function (v, k) {
  1799. propertyNames.push(k);
  1800. }, true);
  1801. return this.parseTheSameObjectPropertyInArray(arr, propertyNames);
  1802. },
  1803. /**
  1804. * 获取对象属性,若为数组则计算其中数字的平均值或其它
  1805. * @param obj
  1806. * @param propertyNames{Array<string>|string}
  1807. * @param type
  1808. */
  1809. getCalculationInArrayByLinkPropertyNames: function (obj, propertyNames, type) {
  1810. var resultObject = {};
  1811. var _this = this;
  1812. switch (type) {
  1813. default:
  1814. case 'sum':
  1815. this.readLinkProperty(obj, propertyNames, function (value, key) {
  1816. if (ArrayUtils.isArrayObject(value)) {
  1817. resultObject = _this.createLinkProperty(resultObject, key, ArrayUtils.getSumInArray(value));
  1818. }
  1819. });
  1820. break;
  1821. case 'average':
  1822. this.readLinkProperty(obj, propertyNames, function (value, key) {
  1823. if (ArrayUtils.isArrayObject(value)) {
  1824. resultObject = _this.createLinkProperty(resultObject, key, ArrayUtils.getAverageInArray(value));
  1825. }
  1826. });
  1827. break;
  1828. }
  1829. return resultObject;
  1830. }
  1831. }
  1832. });
  1833.  
  1834. // ColorUtils
  1835. factory('ColorUtils', [], function () {
  1836. return {
  1837. /**
  1838. * 转换颜色rgb为16进制
  1839. * @param r
  1840. * @param g
  1841. * @param b
  1842. * @return {string}
  1843. */
  1844. rgbToHex: function (r, g, b) {
  1845. var hex = ((r << 16) | (g << 8) | b).toString(16);
  1846. return "#" + new Array(Math.abs(hex.length - 7)).join("0") + hex;
  1847. },
  1848. /**
  1849. * 转换颜色16进制为rgb
  1850. * @param hex
  1851. * @return {Array}
  1852. */
  1853. hexToRgb: function (hex) {
  1854. hex = hex.replace(/ /g, '');
  1855. var length = hex.length;
  1856. var rgb = [];
  1857. switch (length) {
  1858. case 4:
  1859. rgb.push(parseInt(hex[1] + hex[1], 16));
  1860. rgb.push(parseInt(hex[2] + hex[2], 16));
  1861. rgb.push(parseInt(hex[3] + hex[3], 16));
  1862. return rgb;
  1863. case 7:
  1864. for (var i = 1; i < 7; i += 2) {
  1865. rgb.push(parseInt("0x" + hex.slice(i, i + 2)));
  1866. }
  1867. return rgb;
  1868. default:
  1869. break
  1870. }
  1871. },
  1872. /**
  1873. * 根据两个颜色以及之间的百分比获取渐进色
  1874. * @param start
  1875. * @param end
  1876. * @param percentage
  1877. * @return {*}
  1878. */
  1879. gradientColorsPercentage: function (start, end, percentage) {
  1880. var resultRgb = [];
  1881. var startRgb = this.hexToRgb(start);
  1882. if (end == null) {
  1883. return start;
  1884. }
  1885. var endRgb = this.hexToRgb(end);
  1886. var totalR = endRgb[0] - startRgb[0];
  1887. var totalG = endRgb[1] - startRgb[1];
  1888. var totalB = endRgb[2] - startRgb[2];
  1889. resultRgb.push(startRgb[0] + totalR * percentage);
  1890. resultRgb.push(startRgb[1] + totalG * percentage);
  1891. resultRgb.push(startRgb[2] + totalB * percentage);
  1892. return this.rgbToHex(resultRgb[0], resultRgb[1], resultRgb[2])
  1893. }
  1894. }
  1895. });
  1896.  
  1897. factory('FunctionUtils', [], function () {
  1898. return {
  1899. /**
  1900. * 获取方法的名字
  1901. * @param func
  1902. * @returns {*}
  1903. */
  1904. getFunctionName: function (func) {
  1905. if (typeof func === 'function' || typeof func === 'object') {
  1906. var name = ('' + func).match(/function\s*([\w\$]*)\s*\(/);
  1907. }
  1908. return func.name || name[1];
  1909. },
  1910. /**
  1911. * 获取方法的参数名
  1912. * @param func
  1913. * @returns {*}
  1914. */
  1915. getFunctionParams: function (func) {
  1916. if (typeof func === 'function' || typeof func === 'object') {
  1917. var name = ('' + func).match(/function.*\(([^)]*)\)/);
  1918. return name[1].replace(/( )|(\n)/g, '').split(',');
  1919. }
  1920. },
  1921. /**
  1922. * 通过方法的arguments获取调用该方法的函数
  1923. * @param func_arguments
  1924. * @returns {string}
  1925. */
  1926. getCallerName: function (func_arguments) {
  1927. var caller = func_arguments.callee.caller;
  1928. var callerName = '';
  1929. if (caller) {
  1930. callerName = this.getFunctionName(caller);
  1931. }
  1932. return callerName;
  1933. },
  1934. FunctionBuilder: function (func) {
  1935. var _this = this;
  1936. var fs = [];
  1937. fs.push(func);
  1938. var properties = ['push', 'unshift', 'slice', 'map', 'forEach', 'keys', 'find', 'concat', 'fill', 'shift', 'values'];
  1939. map.call(properties, function (property) {
  1940. if (typeof Array.prototype[property] === 'function') {
  1941. Object.defineProperty(_this, property, {
  1942. get: function () {
  1943. return function () {
  1944. fs[property].apply(fs, arguments);
  1945. return this;
  1946. }
  1947. }
  1948. });
  1949. }
  1950. });
  1951. this.result = function (context) {
  1952. var rfs = [];
  1953. map.call(fs, function (f, index) {
  1954. if (typeof f === 'function') {
  1955. rfs.push(f);
  1956. }
  1957. });
  1958. return function () {
  1959. var declareVar = {
  1960. arguments: arguments,
  1961. this: this
  1962. };
  1963. map.call(rfs, function (f) {
  1964. var dv = f.apply(context || this, [declareVar]);
  1965. if (dv) {
  1966. map.call(Object.keys(dv), function (key) {
  1967. declareVar[key] = dv[key];
  1968. });
  1969. }
  1970. });
  1971. return declareVar.returnValue;
  1972. }
  1973. }
  1974. },
  1975. invokeMethods: function (context, methods, args) {
  1976. if (!this.isArray(methods)) {
  1977. return;
  1978. }
  1979. var results = [];
  1980. var _this = this;
  1981. this.ergodicArrayObject(context, methods, function (method) {
  1982. if (!_this.isFunction(method)) {
  1983. return;
  1984. }
  1985. results.push(
  1986. method.apply(context, args)
  1987. );
  1988. });
  1989. return results;
  1990. }
  1991. }
  1992. });
  1993.  
  1994. factory('UrlUtils', [], function () {
  1995. return {
  1996. urlMatching: function (url, matchUrl) {
  1997. var pattern = new RegExp(matchUrl);
  1998. return pattern.test(url);
  1999. },
  2000. getUrlWithoutParam: function (url) {
  2001. return url.split('?')[0];
  2002. },
  2003. getParamFromUrl: function (url) {
  2004. var params = [];
  2005. var parts = url.split('?');
  2006. if (parts.length < 2) {
  2007. return params;
  2008. }
  2009. var paramsStr = parts[1].split('&');
  2010. for (var i = 0; i < paramsStr.length; i++) {
  2011. var index = paramsStr[i].indexOf('=');
  2012. var ps = new Array(2);
  2013. if (index !== -1) {
  2014. ps = [
  2015. paramsStr[i].substring(0, index),
  2016. paramsStr[i].substring(index + 1),
  2017. ];
  2018. } else {
  2019. ps[0] = paramsStr[i];
  2020. }
  2021. params.push({
  2022. key: ps[0],
  2023. value: ps[1]
  2024. });
  2025. }
  2026. return params;
  2027. },
  2028. margeUrlAndParams: function (url, params) {
  2029. if (url.indexOf('?') !== -1 || !(params instanceof Array)) {
  2030. return url;
  2031. }
  2032. var paramsStr = [];
  2033. for (var i = 0; i < params.length; i++) {
  2034. if (params[i].key !== null && params[i].value !== null) {
  2035. paramsStr.push(params[i].key + '=' + params[i].value);
  2036. }
  2037. }
  2038. return url + '?' + paramsStr.join('&');
  2039. }
  2040. }
  2041. });
  2042.  
  2043. factory('PointUtils', [], function () {
  2044. var Point2D = function (x, y) {
  2045. this.x = x || 0;
  2046. this.y = y || 0;
  2047. };
  2048. Point2D.prototype = {
  2049. constructor: Point2D,
  2050. /**
  2051. * 获取指定距离和角度对应的平面点
  2052. * @param distance
  2053. * @param deg
  2054. */
  2055. getOtherPointFromDistanceAndDeg: function (distance, deg) {
  2056. var radian = Math.PI / 180 * deg;
  2057. var point = new this.constructor();
  2058. point.x = distance * Math.sin(radian) + this.x;
  2059. point.y = this.y - distance * Math.cos(radian);
  2060. return point;
  2061. },
  2062. /**
  2063. * 获取当前平面点与另一个平面点之间的距离
  2064. * @param p
  2065. * @returns {number}
  2066. */
  2067. getDistanceFromAnotherPoint: function (p) {
  2068. return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
  2069. },
  2070. /**
  2071. * 获取当前平面点与另一个平面点之间的角度
  2072. * @param p
  2073. * @returns {number}
  2074. */
  2075. getDegFromAnotherPoint: function (p) {
  2076. var usedPoint = new Point2D(p.x * 1000000 - this.x * 1000000, p.y * 1000000 - this.y * 1000000);
  2077. var radian = Math.atan2(usedPoint.x * 1000000, usedPoint.y * 1000000);
  2078. var deg = radian * 180 / Math.PI;
  2079. return 180 - deg;
  2080. },
  2081. /**
  2082. * 判断该点是否位于一矩形内部
  2083. * @param x 矩形开始坐标x
  2084. * @param y 矩形开始坐标y
  2085. * @param width 矩形宽
  2086. * @param height 矩形长
  2087. * @returns {boolean}
  2088. */
  2089. isInRect: function (x, y, width, height) {
  2090. var px = this.x;
  2091. var py = this.y;
  2092. if (px < x || px > x + width) {
  2093. return false;
  2094. }
  2095. return !(py < y || py > y + height);
  2096. }
  2097. };
  2098. return {
  2099. Point2D: Point2D
  2100. }
  2101. });
  2102.  
  2103.  
  2104. factory('PropExpand', ['BaseUtils', 'ObjectUtils', 'ArrayUtils', 'UrlUtils'],
  2105. function (BaseUtils, ObjectUtils, ArrayUtils, UrlUtils) {
  2106. return {
  2107. Object: {
  2108. getProperty: function (_self, propertyLink) {
  2109. return ObjectUtils.readLinkProperty(_self, propertyLink);
  2110. },
  2111. setProperty: function (_self, propertyLink, value) {
  2112. ObjectUtils.createLinkProperty(_self, propertyLink, value);
  2113. },
  2114. mapConvert: function (_self, mapper) {
  2115.  
  2116. },
  2117. keyMap: function (_self, cb) {
  2118. },
  2119. keyValues: function (_self, cb) {
  2120. },
  2121. keyFilter: function (_self, cb) {
  2122. },
  2123. },
  2124. Array: {
  2125. map: function () {
  2126. },
  2127. forEach: function () {
  2128. },
  2129. filter: function () {
  2130. },
  2131. reduce: function () {
  2132. },
  2133. keep: function () {
  2134. },
  2135. remove: function () {
  2136. }
  2137. },
  2138. String: {
  2139. join: function (_self, arr) {
  2140. },
  2141. }
  2142. }
  2143. });
  2144.  
  2145. _global.everyUtils = function () {
  2146. if (BaseUtils.isArray(arguments[0])) {
  2147. depend.call(arguments[2] || this, arguments[0], arguments[1]);
  2148. } else if (BaseUtils.isFunction(arguments[0])) {
  2149. var args = arguments;
  2150. depend.call(arguments[1] || this, ['FunctionUtils'], function (FunctionUtils) {
  2151. var depends = FunctionUtils.getFunctionParams(args[0]);
  2152. depend(depends, args[0]);
  2153. })
  2154. }
  2155. };
  2156.  
  2157. _global.eUtils = (function () {
  2158. var utils = {};
  2159. if (_global.everyUtils) {
  2160. _global.everyUtils([
  2161. 'ArrayUtils', 'ObjectUtils', 'BaseUtils', 'FunctionUtils', 'ColorUtils', 'PointUtils', 'UrlUtils'
  2162. ], function (
  2163. ArrayUtils,
  2164. ObjectUtils,
  2165. BaseUtils,
  2166. FunctionUtils,
  2167. ColorUtils,
  2168. PointUtils,
  2169. UrlUtils) {
  2170. utils = {
  2171. ArrayUtils: ArrayUtils,
  2172. ObjectUtils: ObjectUtils,
  2173. BaseUtils: BaseUtils,
  2174. ColorUtils: ColorUtils,
  2175. UrlUtils: UrlUtils,
  2176. urlUtils: UrlUtils,
  2177. PointUtils: PointUtils,
  2178. FunctionUtils: FunctionUtils
  2179. };
  2180. });
  2181. }
  2182. var proxy = {};
  2183. forEach.call(Object.keys(utils), function (utilName) {
  2184. if (!utilName) {
  2185. return;
  2186. }
  2187. Object.defineProperty(proxy, utilName, {
  2188. get: function () {
  2189. return utils[utilName];
  2190. }
  2191. });
  2192. forEach.call(Object.keys(utils[utilName]), function (key) {
  2193. if (!key) {
  2194. return;
  2195. }
  2196. if (proxy[key]) {
  2197. return;
  2198. }
  2199. Object.defineProperty(proxy, key, {
  2200. get: function () {
  2201. return utils[utilName][key];
  2202. }
  2203. })
  2204. })
  2205. });
  2206. return proxy;
  2207. })();
  2208.  
  2209. return _global.eUtils;
  2210. }));
  2211.  
  2212. /***/ })
  2213. /******/ ]);
  2214. /************************************************************************/
  2215. /******/ // The module cache
  2216. /******/ var __webpack_module_cache__ = {};
  2217. /******/
  2218. /******/ // The require function
  2219. /******/ function __webpack_require__(moduleId) {
  2220. /******/ // Check if module is in cache
  2221. /******/ if(__webpack_module_cache__[moduleId]) {
  2222. /******/ return __webpack_module_cache__[moduleId].exports;
  2223. /******/ }
  2224. /******/ // Create a new module (and put it into the cache)
  2225. /******/ var module = __webpack_module_cache__[moduleId] = {
  2226. /******/ // no module.id needed
  2227. /******/ // no module.loaded needed
  2228. /******/ exports: {}
  2229. /******/ };
  2230. /******/
  2231. /******/ // Execute the module function
  2232. /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  2233. /******/
  2234. /******/ // Return the exports of the module
  2235. /******/ return module.exports;
  2236. /******/ }
  2237. /******/
  2238. /************************************************************************/
  2239. /******/ // module exports must be returned from runtime so entry inlining is disabled
  2240. /******/ // startup
  2241. /******/ // Load entry module and return exports
  2242. /******/ return __webpack_require__(0);
  2243. /******/ })()
  2244. ;
  2245. });
  2246.  
  2247. (function (global) {
  2248. 'use strict';
  2249. if (global.eHook) {
  2250. global.eHook.plugins({
  2251. name: 'NetHook',
  2252. /**
  2253. * 插件装载
  2254. * @param util
  2255. */
  2256. mount: function (util) {
  2257. console.log('NetHook is mounted');
  2258. var cbObject = {
  2259. resp: {},
  2260. parseScript: function (m, args) {
  2261. if (args[0].localName !== 'script') {
  2262. return;
  2263. }
  2264. var src = decodeURI(args[0].src);
  2265. var isPass = true;
  2266. if (ajaxObject.filterPatten) {
  2267. isPass = util.urlUtils.urlMatching(src, ajaxObject.filterPatten);
  2268. }
  2269. if (!isPass || !ajaxChange.cb.req) {
  2270. return;
  2271. }
  2272. var urls = src.split(',');
  2273. if (urls.length > 1) {
  2274. return;
  2275. }
  2276. args[0].requestParams = util.urlUtils.getParamFromUrl(src);
  2277. args[0].requestUrl = util.urlUtils.getUrlWithoutParam(src);
  2278. ajaxChange.cb.req.call(this, args[0], util);
  2279. var aimedUrl = util.urlUtils.margeUrlAndParams(args[0].requestUrl, args[0].requestParams);
  2280. if (aimedUrl !== src) {
  2281. args[0].src = aimedUrl;
  2282. }
  2283. var cbName = undefined;
  2284. args[0].requestParams.map(function (kv) {
  2285. if (kv.key.toLowerCase() === 'cb' || kv.key.toLowerCase() === 'callback') {
  2286. cbName = kv.value;
  2287. }
  2288. });
  2289. if (!cbName || !ajaxChange.cb.resp) {
  2290. return;
  2291. }
  2292. if (window[cbName]) {
  2293. global.eHook.removeHookMethod(window, cbName);
  2294. global.eHook.hookBefore(window, cbName, function (m, args) {
  2295. ajaxChange.cb.resp.call(window, args, util);
  2296. // console.log('Hooking call back: ' + cbName + ' success.')
  2297. }, false);
  2298. } else {
  2299. var isDelete = false;
  2300. try {
  2301. isDelete = delete window[cbName]
  2302. } catch (e) {
  2303. isDelete = false;
  2304. }
  2305. if (isDelete) {
  2306. Object.defineProperty(window, cbName, {
  2307. set: function (v) {
  2308. global.eHook.unHook(cbObject.resp, cbName, true);
  2309. cbObject.resp[cbName] = v;
  2310. global.eHook.hookBefore(cbObject.resp,
  2311. cbName, function (m, args) {
  2312. ajaxChange.cb.resp.call(this, args, util);
  2313. });
  2314. },
  2315. get: function () {
  2316. return cbObject.resp[cbName];
  2317. }
  2318. });
  2319. console.log('Hooking(proxy) call back: ' + cbName + ' success.')
  2320. } else {
  2321. console.log('Hooking call back: ' + cbName + ' failed.')
  2322. }
  2323. }
  2324.  
  2325. }
  2326. };
  2327. var isAutoInit = localStorage.getItem('__hook_all_auto_init');
  2328. if (!isAutoInit) {
  2329. localStorage.setItem('__hook_all_auto_init', JSON.stringify(true));
  2330. isAutoInit = localStorage.getItem('__hook_all_auto_init');
  2331. }
  2332. var ajaxObject = {
  2333. filterPatten: '',
  2334. isAutoInit: isAutoInit && isAutoInit !== 'false'
  2335. };
  2336. var ajaxChange = {
  2337. filter: function (pattern) {
  2338. ajaxObject.filterPatten = pattern;
  2339. return this;
  2340. },
  2341. ajax: {
  2342. req: undefined,
  2343. resp: undefined,
  2344. send: undefined
  2345. },
  2346. cb: {
  2347. req: undefined,
  2348. resp: undefined
  2349. },
  2350. setting: {
  2351. autoInit: function (b) {
  2352. ajaxObject.isAutoInit = b;
  2353. localStorage.setItem('__hook_all_auto_init', JSON.stringify(b));
  2354. }
  2355. },
  2356. init: function () {
  2357. // hook jsonp
  2358. global.eHook.hookBefore(Node.prototype, 'appendChild', function (m, args) {
  2359. cbObject.parseScript(m, args);
  2360. }, false);
  2361. global.eHook.hookBefore(Node.prototype, 'insertBefore', function (m, args) {
  2362. cbObject.parseScript(m, args);
  2363. }, false);
  2364.  
  2365. global.aHook.register('.*', {
  2366. hookResponse: function () {
  2367. var isPass = true;
  2368. if (ajaxObject.filterPatten) {
  2369. isPass = util.urlUtils.urlMatching(this.responseURL, ajaxObject.filterPatten);
  2370. }
  2371. return !isPass ? undefined : ajaxChange.ajax.resp && ajaxChange.ajax.resp.call(this, arguments, util);
  2372. },
  2373. hookSend: function (args) {
  2374. var isPass = true;
  2375. if (ajaxObject.filterPatten) {
  2376. isPass = util.urlUtils.urlMatching(this.requestURL, ajaxObject.filterPatten);
  2377. }
  2378. return !isPass ? undefined : ajaxChange.ajax.send && ajaxChange.ajax.send.call(this, arguments, util);
  2379. },
  2380. hookRequest: function (args) {
  2381. window.util = util;
  2382. var isPass = true;
  2383. if (ajaxObject.filterPatten) {
  2384. isPass = util.urlUtils.urlMatching(args.fullUrl, ajaxObject.filterPatten);
  2385. }
  2386. this.requestURL = args.fullUrl;
  2387. return !isPass ? undefined : ajaxChange.ajax.req && ajaxChange.ajax.req.call(this, arguments, util);
  2388. }
  2389. }
  2390. );
  2391. },
  2392. onInit: function () {
  2393. }
  2394. };
  2395. ajaxChange.onInit();
  2396. // if (ajaxObject.isAutoInit) {
  2397. ajaxChange.init();
  2398. // }
  2399.  
  2400. return ajaxChange;
  2401. }
  2402. });
  2403. }
  2404. })(window);