├── .babelrc ├── .eslintrc ├── .gitignore ├── .travis.yml ├── README.md ├── package.json ├── src ├── animation │ └── index.js ├── apply │ └── index.js ├── decorators │ ├── Bind.js │ ├── Debounce.js │ ├── Delay.js │ ├── Inject.js │ ├── README.md │ ├── Throttle.js │ ├── __tests__ │ │ ├── test-decorators.js │ │ └── use-case.js │ └── index.js ├── deferred │ └── index.js ├── dynamic-export │ └── index.js ├── event-bus │ ├── __tests__ │ │ └── test-event-bus.js │ └── index.js ├── factory-creator │ ├── README.md │ ├── __tests__ │ │ ├── test-factory-creator.js │ │ └── use-case.js │ └── index.js ├── index.js ├── injector │ ├── __tests__ │ │ └── test-injector.js │ └── index.js ├── mappers │ └── FieldsMapper.js ├── mock │ └── db.json ├── module-helper │ └── index.js ├── rs-generator │ ├── README.md │ ├── __tests__ │ │ └── test-rs-generator.js │ ├── index.d.ts │ └── index.js └── type-auth │ ├── __tests__ │ └── test-type-auth.js │ └── index.js ├── test ├── karma.base.conf.js ├── karma.cover.conf.js ├── karma.unit.conf.js └── test.index.js └── typings ├── angularjs ├── angular-resource.d.ts └── angular.d.ts └── jquery └── jquery.d.ts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "stage-0"], 3 | "plugins": ["transform-decorators-legacy"] 4 | } 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "modules": true, 4 | "experimentalObjectRestSpread": true 5 | }, 6 | 7 | "env": { 8 | "browser": true, 9 | "es6": true, 10 | "node": true, 11 | "mocha": true 12 | }, 13 | "plugins": [ 14 | "standard" 15 | ], 16 | 17 | "globals": { 18 | "angular": true, 19 | "document": true, 20 | "navigator": true, 21 | "window": true, 22 | "inject": true, 23 | "module": true 24 | }, 25 | 26 | "parser": "babel-eslint", 27 | 28 | "rules": { 29 | //在定义对象的时候,getter/setter需要同时出现 30 | "accessor-pairs": 2, 31 | //箭头函数中的箭头前后需要留空格 32 | "arrow-spacing": [2, { "before": true, "after": true }], 33 | // 箭头函数中,在需要的时候,在参数外使用小括号(只有一个参数时,可以不适用括号,其它情况下都需要使用括号) 34 | "arrow-parens": [2, "as-needed"], 35 | //如果代码块是单行的时候,代码块内部前后需要留一个空格 36 | "block-spacing": [2, "always"], 37 | //大括号语法采用『1tbs』,允许单行样式 38 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 39 | //在定义对象或数组时,最后一项不能加逗号 40 | "comma-dangle": [2, "never"], 41 | //在写逗号时,逗号前面不需要加空格,而逗号后面需要添加空格 42 | "comma-spacing": [2, { "before": false, "after": true }], 43 | //如果逗号可以放在行首或行尾时,那么请放在行尾 44 | "comma-style": [2, "last"], 45 | //在constructor函数中,如果classes是继承其他class,那么请使用super。否者不使用super 46 | "constructor-super": 2, 47 | //在if-else语句中,如果if或else语句后面是多行,那么必须加大括号。如果是单行就应该省略大括号。 48 | "curly": [2, "multi-line"], 49 | //该规则规定了.应该放置的位置, 50 | "dot-location": [2, "property"], 51 | //该规则要求代码最后面需要留一空行,(仅需要留一空行) 52 | "eol-last": 2, 53 | //使用=== !== 代替== != . 54 | "eqeqeq": [2, "allow-null"], 55 | //该规则规定了generator函数中星号两边的空白。 56 | "generator-star-spacing": [2, { "before": true, "after": true }], 57 | // 规定callback 如果有err参数,只能写出err 或者 error . 58 | "handle-callback-err": [2, "^(err|error)$" ], 59 | //这个就是关于用什么来缩进了,规定使用tab 来进行缩进,switch中case也需要一个tab . 60 | "indent": [2, "tab", { "SwitchCase": 1 }], 61 | //该规则规定了在对象字面量语法中,key和value之间的空白,冒号前不要空格,冒号后面需要一个空格 62 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 63 | //构造函数首字母大写 64 | // "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 65 | //在使用构造函数时候,函数调用的圆括号不能够省略 66 | "new-parens": 2, 67 | //禁止使用Array构造函数 68 | "no-array-constructor": 2, 69 | //禁止使用arguments.caller和arguments.callee 70 | "no-caller": 2, 71 | //禁止覆盖class命名,也就是说变量名不要和class名重名 72 | "no-class-assign": 2, 73 | //在条件语句中不要使用赋值语句 74 | "no-cond-assign": 2, 75 | //const申明的变量禁止修改 76 | "no-const-assign": 2, 77 | //在正则表达式中禁止使用控制符(详见官网) 78 | "no-control-regex": 2, 79 | //禁止使用debugger语句 80 | "no-debugger": 2, 81 | //禁止使用delete删除var申明的变量 82 | "no-delete-var": 2, 83 | //函数参数禁止重名 84 | "no-dupe-args": 2, 85 | //class中的成员禁止重名 86 | "no-dupe-class-members": 2, 87 | //在对象字面量中,禁止使用重复的key 88 | "no-dupe-keys": 2, 89 | //在switch语句中禁止重复的case 90 | "no-duplicate-case": 2, 91 | //禁止使用不匹配任何字符串的正则表达式 92 | "no-empty-character-class": 2, 93 | //label 没有和迭代语句或者switch语句一起使用,将会报错 94 | "no-empty-label": 2, 95 | //禁止使用eval函数 96 | "no-eval": 2, 97 | //禁止对catch语句中的参数进行赋值 98 | "no-ex-assign": 2, 99 | //禁止扩展原生对象 100 | "no-extend-native": 2, 101 | //禁止在不必要的时候使用bind函数 102 | "no-extra-bind": 2, 103 | //在一个本来就会自动转化为布尔值的上下文中就没必要再使用!! 进行强制转化了。 104 | "no-extra-boolean-cast": 2, 105 | //禁止使用多余的圆括号 106 | "no-extra-parens": [2, "functions"], 107 | //这条规则,简单来说就是在case语句中尽量加break,避免不必要的fallthrough错误,如果需要fall through,那么看官网。 108 | "no-fallthrough": 2, 109 | //简单来说不要写这样的数字.2 2.。应该写全,2.2 2.0 . 110 | "no-floating-decimal": 2, 111 | //禁止对函数名重新赋值 112 | "no-func-assign": 2, 113 | //禁止使用类eval的函数。 114 | "no-implied-eval": 2, 115 | //禁止在代码块中定义函数(下面的规则仅限制函数) 116 | "no-inner-declarations": [2, "functions"], 117 | //RegExp构造函数中禁止使用非法正则语句 118 | "no-invalid-regexp": 2, 119 | //禁止使用不规则的空白符 120 | "no-irregular-whitespace": 2, 121 | //禁止使用__iterator__属性 122 | "no-iterator": 2, 123 | //label和var申明的变量不能重名 124 | "no-label-var": 2, 125 | //禁止使用label语句 126 | "no-labels": 2, 127 | //禁止使用没有必要的嵌套代码块 128 | "no-lone-blocks": 2, 129 | //不要把空格和tab混用 130 | "no-mixed-spaces-and-tabs": 2, 131 | //顾名思义,该规则保证了在逻辑表达式、条件表达式、 132 | //申明语句、数组元素、对象属性、sequences、函数参数中不使用超过一个的空白符。 133 | "no-multi-spaces": 2, 134 | //该规则保证了字符串不分两行书写。 135 | "no-multi-str": 2, 136 | //空行不能够超过2行 137 | "no-multiple-empty-lines": [2, { "max": 2 }], 138 | //该规则保证了不重写原生对象。 139 | "no-native-reassign": 2, 140 | //在in操作符左边的操作项不能用! 例如这样写不对的:if ( !a in b) { //dosomething } 141 | "no-negated-in-lhs": 2, 142 | //当我们使用new操作符去调用构造函数时,需要把调用结果赋值给一个变量。 143 | "no-new": 2, 144 | //该规则保证了不使用new Function(); 语句。 145 | "no-new-func": 2, 146 | //不要通过new Object(),来定义对象 147 | "no-new-object": 2, 148 | //禁止把require方法和new操作符一起使用。 149 | "no-new-require": 2, 150 | //当定义字符串、数字、布尔值就不要使用构造函数了,String、Number、Boolean 151 | "no-new-wrappers": 2, 152 | //禁止无意得把全局对象当函数调用了,比如下面写法错误的:Math(), JSON() 153 | "no-obj-calls": 2, 154 | //不要使用八进制的语法。 155 | "no-octal": 2, 156 | //用的少,见官网。http://eslint.org/docs/rules/ 157 | "no-octal-escape": 2, 158 | //不要使用__proto__ 159 | "no-proto": 2, 160 | //不要重复申明一个变量 161 | "no-redeclare": 2, 162 | //正则表达式中不要使用空格 163 | "no-regex-spaces": 2, 164 | //return语句中不要写赋值语句 165 | "no-return-assign": 2, 166 | //不要和自身作比较 167 | "no-self-compare": 2, 168 | //不要使用逗号操作符,详见官网 169 | "no-sequences": 2, 170 | //禁止对一些关键字或者保留字进行赋值操作,比如NaN、Infinity、undefined、eval、arguments等。 171 | "no-shadow-restricted-names": 2, 172 | //函数调用时,圆括号前面不能有空格 173 | "no-spaced-func": 2, 174 | //禁止使用稀疏数组 175 | "no-sparse-arrays": 2, 176 | //在调用super之前不能使用this对象 177 | "no-this-before-super": 2, 178 | //严格限制了抛出错误的类型,简单来说只能够抛出Error生成的错误。但是这条规则并不能够保证你只能够 179 | //抛出Error错误。详细见官网 180 | "no-throw-literal": 2, 181 | //行末禁止加空格 182 | "no-trailing-spaces": 2, 183 | //禁止使用没有定义的变量,除非在/*global*/已经申明 184 | "no-undef": 2, 185 | //禁止把undefined赋值给一个变量 186 | "no-undef-init": 2, 187 | //禁止在不需要分行的时候使用了分行 188 | "no-unexpected-multiline": 2, 189 | //禁止使用没有必要的三元操作符,因为用些三元操作符可以使用其他语句替换 190 | "no-unneeded-ternary": [2, { "defaultAssignment": false }], 191 | //没有执行不到的代码 192 | "no-unreachable": 2, 193 | //没有定义了没有被使用到的变量 194 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 195 | //禁止在不需要使用call()或者apply()的时候使用了这两个方法 196 | "no-useless-call": 2, 197 | //不要使用with语句 198 | "no-with": 2, 199 | //在某些场景只能使用一个var来申明变量 200 | "one-var": [2, { "initialized": "never" }], 201 | //在进行断行时,操作符应该放在行首还是行尾。并且还可以对某些操作符进行重写。 202 | "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], 203 | //使用单引号 204 | "quotes": [2, "single", "avoid-escape"], 205 | //在使用parseInt() 方法时,需要传递第二个参数,来帮助解析,告诉方法解析成多少进制。 206 | "radix": 2, 207 | //这就是分号党和非分号党关心的了,我们还是选择加分号 208 | "semi": [2, "always"], 209 | //该规则规定了分号前后的空格,具体规定如下。 210 | "semi-spacing": [2, { "before": false, "after": true }], 211 | //关键词后面需要加空格 212 | "space-after-keywords": [2, "always"], 213 | //代码块前面需要加空格 214 | "space-before-blocks": [2, "always"], 215 | //函数圆括号前面需要加空格 216 | "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], 217 | //关键词前面需要加空格 218 | "space-before-keywords": [2, "always"], 219 | //圆括号内部不需要加空格 220 | "space-in-parens": [2, "never"], 221 | //操作符前后需要加空格 222 | "space-infix-ops": 2, 223 | //return、throw、case后面需要一个空格 224 | "space-return-throw-case": 2, 225 | //一元操作符前后是否需要加空格,单词类操作符需要加,而非单词类操作符不用加 226 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 227 | //评论符号`/*` `//`,后面需要留一个空格 228 | "spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!", ","] }], 229 | //推荐使用isNaN方法,而不要直接和NaN作比较 230 | "use-isnan": 2, 231 | //在使用typeof操作符时,作比较的字符串必须是合法字符串eg:'string' 'object' 232 | "valid-typeof": 2, 233 | //立即执行函数需要用圆括号包围 234 | "wrap-iife": [2, "any"], 235 | //yoda条件语句就是字面量应该写在比较操作符的左边,而变量应该写在比较操作符的右边。 236 | //而下面的规则要求,变量写在前面,字面量写在右边 237 | "yoda": [2, "never"], 238 | 239 | "standard/object-curly-even-spacing": [2, "either"], 240 | "standard/array-bracket-even-spacing": [2, "either"], 241 | "standard/computed-property-even-spacing": [2, "even"] 242 | } 243 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | node_modules 3 | build 4 | coverage 5 | lib 6 | .idea/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 6 4 | cache: 5 | directories: 6 | - node_modules 7 | before_install: 8 | - export DISPLAY=:99.0 9 | - sh -e /etc/init.d/xvfb start 10 | script: 11 | - npm test 12 | - cat ./test/coverage/lcov.info | ./node_modules/.bin/codecov 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## angular-es-utils 2 | 3 | [![Build Status](https://img.shields.io/travis/kuitos/angular-es-utils.svg?style=flat-square)](https://travis-ci.org/kuitos/angular-es-utils) 4 | [![npm version](https://img.shields.io/npm/v/angular-es-utils.svg?style=flat-square)](https://www.npmjs.com/package/angular-es-utils) 5 | [![npm downloads](https://img.shields.io/npm/dt/angular-es-utils.svg?style=flat-square)](https://www.npmjs.com/package/angular-es-utils) 6 | [![coverage](https://img.shields.io/codecov/c/github/kuitos/angular-es-utils.svg?style=flat-square)](https://codecov.io/gh/kuitos/angular-es-utils) 7 | 8 | The es6 version of [angular utils](https://github.com/kuitos/angular-utils) 9 | 10 | How To Use 11 | 12 | ```shell 13 | npm i angular-es-utils -D 14 | ``` 15 | 16 | ```js 17 | import {Inject} from 'angular-es-utils'; 18 | ``` 19 | 20 | #### 工具列表 21 | * animation 22 | 动画操作帮助类 23 | 24 | ```js 25 | import {Animation} from 'angular-es-utils'; 26 | import Animation from 'angular-es-utils/animation'; 27 | ``` 28 | 29 | * apply 30 | 替代`$scope.$apply()` 31 | 32 | ```js 33 | import apply from 'angular-es-utils/apply'; 34 | 35 | ... 36 | apply(); 37 | ``` 38 | 39 | 40 | * decorators 41 | 装饰器 42 | [decorators usage](src/decorators/README.md) 43 | 44 | * rs-generator 45 | resource 生成器 46 | [rs-generator usage](src/rs-generator/README.md) 47 | 48 | * deferred 49 | * factory-creator 50 | 51 | ##### Deprecated [迁移指南](src/factory-creator/README.md) 52 | 53 | 将Class转换成factory,供directive语法使用 54 | 55 | ```js 56 | .directive('editor', FactoryCreator.create(Editor)) 57 | ``` 58 | 59 | * injector 60 | 在angular环境之外获取ng-app的注入器 61 | 62 | ```js 63 | import injector from 'angular-es-utils/injector'; 64 | let scope = injector.get('$rootScope').$new(); 65 | ``` 66 | 67 | * EventBus 68 | 事件总线,环境无关的 订阅/发布 模型 69 | 70 | ```js 71 | import EventBus from 'angular-es-utils/event-bus'; 72 | // 订阅消息 73 | const deregister = EventBus.on('grid:click', (num1,num2,num3) => console.log(num1, num2, num3)); 74 | // 发布消息 75 | EventBus.dispatch('grid:click', 1, 2, 3); 76 | // 解除订阅 77 | deregister(); 78 | ``` 79 | 80 | * module-helper 81 | 82 | ```js 83 | import ModuleHelper from 'angular-es-utils/module-helper'; 84 | let module = ModuleHelper.get('app'); 85 | ``` 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-es-utils", 3 | "version": "2.1.5", 4 | "description": "es utils design for angular1.x", 5 | "main": "./index.js", 6 | "scripts": { 7 | "build": "rm -fr lib && NODE_ENV=production babel src --out-dir lib --ignore **/__tests__ && cp package.json lib/package.json && cp README.md lib/README.md", 8 | "codecheck": "NODE_EVN=test eslint src", 9 | "prepush": "npm test", 10 | "test": "npm run codecheck & npm run cover", 11 | "unit": "karma start ./test/karma.unit.conf.js --single-run", 12 | "cover": "karma start ./test/karma.cover.conf.js", 13 | "pub": "npm test && npm run build && npm publish lib && cnpm sync angular-es-utils", 14 | "start": "karma start ./test/karma.unit.conf.js" 15 | }, 16 | "author": "Kuitos", 17 | "homepage": "https://github.com/kuitos/angular-es-utils", 18 | "devDependencies": { 19 | "angular": "^1.5.3", 20 | "angular-resource": "^1.5.5", 21 | "angular-mocks": "^1.5.3", 22 | "babel-cli": "^6.7.7", 23 | "babel-core": "^6.7.4", 24 | "babel-eslint": "^4.1.3", 25 | "babel-loader": "^6.2.4", 26 | "babel-plugin-transform-decorators-legacy": "^1.3.4", 27 | "babel-polyfill": "^6.9.1", 28 | "babel-preset-es2015": "^6.6.0", 29 | "babel-preset-stage-0": "^6.5.0", 30 | "chai": "^3.5.0", 31 | "codecov": "^1.0.1", 32 | "eslint": "^1.8.0", 33 | "eslint-friendly-formatter": "^1.2.2", 34 | "eslint-loader": "^1.1.0", 35 | "eslint-plugin-standard": "^1.3.1", 36 | "husky": "^0.10.1", 37 | "istanbul-instrumenter-loader": "^0.2.0", 38 | "karma": "^0.13.22", 39 | "karma-chrome-launcher": "^0.2.3", 40 | "karma-coverage": "^0.5.5", 41 | "karma-firefox-launcher": "^1.0.0", 42 | "karma-mocha": "^0.2.2", 43 | "karma-mocha-reporter": "^2.0.2", 44 | "karma-webpack": "^1.7.0", 45 | "mocha": "^2.4.5", 46 | "sinon": "^2.0.0-pre", 47 | "webpack": "^1.13.0" 48 | }, 49 | "dependencies": { 50 | "esnext-utils": "^1.1.0" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/animation/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-03-24 5 | */ 6 | 7 | let ANIMATIONEND_EVENT, TRANSITIONEND_EVENT; 8 | 9 | if (window.onanimationend === undefined && window.onwebkitanimationend !== undefined) { 10 | ANIMATIONEND_EVENT = 'webkitAnimationEnd animationend'; 11 | } else { 12 | ANIMATIONEND_EVENT = 'animationend'; 13 | } 14 | 15 | if (window.ontransitionend === undefined && window.onwebkittransitionend !== undefined) { 16 | TRANSITIONEND_EVENT = 'webkitTransitionEnd transitionend'; 17 | } else { 18 | TRANSITIONEND_EVENT = 'transitionend'; 19 | } 20 | 21 | const EVENTS = [ANIMATIONEND_EVENT, TRANSITIONEND_EVENT].join(' ').split(' '); 22 | const noop = () => {}; 23 | 24 | export default { 25 | 26 | addClass: (element, className, doneHook = noop, autoRemove = false) => { 27 | EVENTS.forEach(event => { 28 | element.addEventListener(event, () => { 29 | 30 | if (autoRemove) { 31 | element.classList.remove(className); 32 | } 33 | 34 | doneHook(); 35 | }, false); 36 | }); 37 | 38 | element.classList.add(className); 39 | }, 40 | 41 | removeClass: (element, className, doneHook) => { 42 | EVENTS.forEach(event => { 43 | element.addEventListener(event, doneHook, false); 44 | }); 45 | 46 | element.classList.remove(className); 47 | } 48 | 49 | }; 50 | -------------------------------------------------------------------------------- /src/apply/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-07-25 5 | */ 6 | 7 | import injector from '../injector'; 8 | 9 | export default () => { 10 | 11 | const $rootScope = injector.get('$rootScope'); 12 | 13 | if (!$rootScope.$$phase) { 14 | $rootScope.$digest(); 15 | } 16 | 17 | }; 18 | -------------------------------------------------------------------------------- /src/decorators/Bind.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-06 5 | */ 6 | import Bind from 'esnext-utils/decorators/bind'; 7 | 8 | /** 9 | * bind装饰器,用于处理function bind不适用的场景 10 | */ 11 | export default Bind; 12 | -------------------------------------------------------------------------------- /src/decorators/Debounce.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-12 5 | */ 6 | import injector from '../injector'; 7 | 8 | export default (delay = 300, context, invokeApply) => (target, name, descriptor) => { 9 | 10 | if (!descriptor) { 11 | throw new Error('can not use Debounce decorator with a constructor!'); 12 | } 13 | 14 | const fn = descriptor.value || target[name]; 15 | let $timeout = null; 16 | let pendingDebounce = null; 17 | 18 | descriptor.value = function (...args) { 19 | 20 | // lazy init 21 | $timeout = $timeout || injector.get('$timeout'); 22 | 23 | $timeout.cancel(pendingDebounce); 24 | 25 | pendingDebounce = $timeout(() => { 26 | pendingDebounce = null; 27 | fn.apply(context || this, args); 28 | }, delay, invokeApply); 29 | }; 30 | 31 | return descriptor; 32 | 33 | }; 34 | -------------------------------------------------------------------------------- /src/decorators/Delay.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-07-06 5 | */ 6 | 7 | import injector from '../injector'; 8 | 9 | export default (delay = 0, invokeApply = false) => (target, name, descriptor) => { 10 | 11 | if (!descriptor) { 12 | throw new Error('can not use Delay decorator with a constructor!'); 13 | } 14 | 15 | const fn = descriptor.value || target[name]; 16 | let $timeout = null; 17 | 18 | descriptor.value = function (...args) { 19 | 20 | // lazy init 21 | $timeout = $timeout || injector.get('$timeout'); 22 | $timeout(() => { 23 | fn.apply(this, args); 24 | }, delay, invokeApply); 25 | }; 26 | 27 | return descriptor; 28 | }; 29 | 30 | -------------------------------------------------------------------------------- /src/decorators/Inject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-01-11 5 | */ 6 | 7 | // safari里调用getOwnPropertyNames会拿到 arguments 跟 caller 8 | const stupidSafariProps = ['arguments', 'caller']; 9 | // 需要过滤的构造函数的属性 10 | const propBlacklist = ['name', 'prototype', 'length'].concat(stupidSafariProps); 11 | /** 12 | * angular依赖注入器 13 | */ 14 | export default (...dependencies) => (target, name, descriptor) => { 15 | 16 | if (descriptor) { 17 | throw new Error('can not use Inject decorator with a non-constructor!'); 18 | } 19 | 20 | const OriginalConstructor = target; 21 | 22 | class Constructor { 23 | 24 | constructor(...args) { 25 | 26 | /* ----------------- 以下这一段恶心的代码都是为了兼容function跟class定义controller这两种情况 ------------------------ */ 27 | /* ----------------- 因为class定义的Constructor有时候需要直接访问this中已绑定的数据(fn.apply(instance, locals)) ---- */ 28 | 29 | // 存在通过 fn.apply(instance, locals) 的方式调用的情况,所以这里直接将依赖的服务拷贝到this里(服务以下划线作为前缀) 30 | dependencies.forEach((dependency, i) => this[`_${dependency}`] = args[i]); 31 | // 将构造器初始化时就需要访问的数据挂载到prototype上,这样即使通过new方式实例化,constructor里的this也具备完整信息 32 | Object.assign(OriginalConstructor.prototype, this); 33 | 34 | const instance = new OriginalConstructor(...args); 35 | 36 | // 初始化完毕需要从prototype上删除挂载的属性,因为有一些注入的局部服务对于每一个实例而言是隔离的,如果改变prototype会出现混乱 37 | Object.keys(this).forEach(prop => { 38 | // prototype上不可枚举的属性不能删除(比如方法/accessor等) 39 | if (OriginalConstructor.prototype.propertyIsEnumerable(prop)) { 40 | delete OriginalConstructor.prototype[prop]; 41 | } 42 | 43 | // 属性可能会被重新定义,比如 this.name = this.name + 'xx'; 44 | // 所以这里不能直接Object.assign(instance, this) 45 | // 只有this上存在但是instance上不存在的属性才复制过去 46 | if (!instance.hasOwnProperty(prop)) { 47 | instance[prop] = this[prop]; 48 | } 49 | }); 50 | 51 | return instance; 52 | } 53 | } 54 | 55 | // 将原始构造函数的属性复制到新的Constructor中,包括prototype 56 | // 因为通过static class property语法定义的静态方法是不可枚举的,所以这里不能用Object.keys API来筛选. 57 | Object.getOwnPropertyNames(target).forEach(prop => { 58 | if (propBlacklist.indexOf(prop) === -1) { 59 | Constructor[prop] = target[prop]; 60 | } 61 | }); 62 | Constructor.$inject = dependencies; 63 | 64 | return Constructor; 65 | }; 66 | -------------------------------------------------------------------------------- /src/decorators/README.md: -------------------------------------------------------------------------------- 1 | ## decorators 2 | 3 | * Inject 4 | 5 | 将指定的ng服务(包括自定义服务)注入到构造器中(Service、Controller、Filter等),同时绑定到this对象上,格式为 `this._serviceName` 6 | 7 | ```js 8 | @Inject('$q') 9 | class Service { 10 | getQ() { 11 | return this._$q; 12 | } 13 | } 14 | ``` 15 | * Bind 16 | 17 | 使用装饰器的方式实现`Function.prototype.bind` 18 | 19 | ```js 20 | class Service { 21 | 22 | constructor(name) { 23 | this.name = name; 24 | } 25 | 26 | @Bind 27 | getName() { 28 | return this.name; 29 | } 30 | } 31 | 32 | const service = new Service('kuitos'); 33 | const getName = service.getName; 34 | console.log(getName()); // kuitos 35 | ``` 36 | 37 | * Debounce 38 | 39 | `@Debounce(delay, context || this)` 40 | 41 | ```js 42 | class Service { 43 | 44 | @Debounce(100) 45 | resize() { 46 | 47 | // debounce 48 | } 49 | } 50 | 51 | ``` 52 | * Throttle 53 | 54 | `@Throttle(delay, context || this)` 55 | 56 | ```js 57 | class Service { 58 | 59 | @Throttle(100) 60 | switchButton() { 61 | // throttle 62 | } 63 | } 64 | 65 | ``` -------------------------------------------------------------------------------- /src/decorators/Throttle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-12 5 | */ 6 | 7 | export default (delay = 10, context) => (target, name, descriptor) => { 8 | 9 | if (!descriptor) { 10 | throw new Error('can not use Throttle decorator with a constructor!'); 11 | } 12 | 13 | const fn = descriptor.value || target[name]; 14 | 15 | let recent; 16 | 17 | descriptor.value = function (...args) { 18 | 19 | const now = Date.now(); 20 | 21 | if (!recent || (now - recent > delay)) { 22 | fn.apply(context || this, args); 23 | recent = now; 24 | } 25 | }; 26 | 27 | return descriptor; 28 | }; 29 | -------------------------------------------------------------------------------- /src/decorators/__tests__/test-decorators.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-07 5 | */ 6 | 7 | import useCase, {Service} from './use-case'; 8 | import Bind from '../Bind'; 9 | import {assert} from 'chai'; 10 | // import sinon from 'sinon'; 11 | // import injector from '../../injector'; 12 | // import Debounce from '../Debounce'; 13 | import Inject from '../Inject'; 14 | 15 | describe('decorators', () => { 16 | 17 | let $injector, serviceInstance, controllerInstance, componentController, $scope, bindings; 18 | 19 | beforeEach(angular.mock.module(useCase)); 20 | beforeEach(angular.mock.inject((_$injector_, _$controller_, _$rootScope_, $componentController) => { 21 | $injector = _$injector_; 22 | $scope = _$rootScope_.$new(); 23 | componentController = $componentController('component', {$scope}, bindings = {data: {name: 'component'}}); 24 | serviceInstance = $injector.get('Service'); 25 | controllerInstance = _$controller_('Controller', {$scope}); 26 | })); 27 | 28 | describe('inject', () => { 29 | 30 | it('Service Recipe: external service should be members of instance which start with underscore', () => { 31 | assert.equal(serviceInstance._$q, $injector.get('$q')); 32 | assert.equal(serviceInstance.getQ(), $injector.get('$q')); 33 | }); 34 | 35 | it('Controller Recipe: external service should be members of instance which start with underscore', () => { 36 | assert.equal(controllerInstance._$scope, $scope); 37 | }); 38 | 39 | it('Component Recipe: external service should be members of instance which start with underscore', () => { 40 | assert.equal(componentController._$scope, $scope); 41 | }); 42 | 43 | it('Component Controller Recipe: bindings data should be bind to controller instance', () => { 44 | assert.equal(componentController.data, bindings.data); 45 | assert.equal(componentController._$scope.$ctrl.data, bindings.data); 46 | assert.equal(componentController.recipe, 'componentController'); 47 | }); 48 | 49 | it('static props of Constructor should be same with original target', () => { 50 | assert.equal(Service.getStaticName(), 'kuitos'); 51 | }); 52 | 53 | it('class constructor should also hold the injected service which had bound to this when instantiate', angular.mock.inject(($controller, $rootScope) => { 54 | const user = {name: 'kuitos'}; 55 | 56 | @Inject('$rootScope', 'user') 57 | class InnerController { 58 | constructor() { 59 | assert.equal(this._$rootScope, $rootScope); 60 | this.name = 'xxx'; 61 | this._user = Object.assign({age: 20}, this._user); 62 | } 63 | 64 | getUser() { 65 | return this._user; 66 | } 67 | } 68 | 69 | const controller = $controller(InnerController, {$rootScope, user}); 70 | assert.equal(controller._$rootScope, $rootScope); 71 | assert.equal(controller.name, 'xxx'); 72 | assert.deepEqual(controller.getUser(), Object.assign({age: 20}, user)); 73 | assert.notEqual(InnerController.prototype._user, user); 74 | })); 75 | 76 | }); 77 | 78 | describe('bind', () => { 79 | 80 | it('Service Recipe: this pointer always equal service instance', () => { 81 | const getName = serviceInstance.getName; 82 | assert.equal(getName(), serviceInstance.name); 83 | }); 84 | 85 | it('Component Controller Recipe: this pointer always equal component controller instance', () => { 86 | const getRecipe = componentController.getRecipe; 87 | assert.equal(getRecipe(), componentController.recipe); 88 | }); 89 | 90 | it('this pointer should not obstruct each instance', () => { 91 | const service1GetName = new Service('l').getName; 92 | const service2GetName = new Service('k').getName; 93 | assert.notEqual(service1GetName(), service2GetName()); 94 | }); 95 | 96 | it('function should always share the same instance', () => { 97 | const service = new Service('kuitos'); 98 | const getName1 = service.getName; 99 | const getName2 = service.getName; 100 | const get2AppendedName = service.getName2; 101 | assert.equal(getName1, getName2); 102 | assert.equal(get2AppendedName(), 'kuitos2'); 103 | }); 104 | 105 | it('reassign should also worked well', () => { 106 | const service = new Service('kuitos'); 107 | const original = service.getName; 108 | service.getName = () => { 109 | return original() + '6666'; 110 | }; 111 | const getName = service.getName; 112 | assert.equal(getName(), 'kuitos6666'); 113 | }); 114 | 115 | it('worked well although use decorator without @ symbol like compiled after webpack', () => { 116 | 117 | const descriptors = [ 118 | { 119 | key: 'fn1', 120 | value: function () { 121 | return 1; 122 | } 123 | }, 124 | { 125 | key: 'fn2', 126 | value: function () { 127 | return 2; 128 | } 129 | } 130 | ]; 131 | 132 | function Klass() { 133 | } 134 | 135 | descriptors.forEach(descriptor => { 136 | const target = Klass.prototype; 137 | const name = descriptor.key; 138 | Object.defineProperty(target, name, Bind(target, name, descriptor)); 139 | }); 140 | 141 | const instance = new Klass(); 142 | 143 | assert.notEqual(instance.fn1, instance.fn2); 144 | assert.equal(instance.fn1(), 1); 145 | assert.equal(instance.fn2(), 2); 146 | }); 147 | }); 148 | 149 | describe('throttle', () => { 150 | 151 | it('service recipe: method only run once per 100 milliseconds', () => { 152 | const now = Date.now(); 153 | while (Date.now() - now < 1000) { 154 | serviceInstance.resize(); 155 | } 156 | assert.equal(serviceInstance.age, 10); 157 | }); 158 | 159 | }); 160 | 161 | // describe('debounce', () => { 162 | // 163 | // it('service recipe: method only run once in 1000 milliseconds', done => { 164 | // sinon.stub(injector, 'get', () => setTimeout); 165 | // 166 | // class Service { 167 | // @Debounce(100) 168 | // switcher(cb) { 169 | // this.age++; 170 | // cb(); 171 | // } 172 | // } 173 | // 174 | // const service = new Service(); 175 | // 176 | // const now = Date.now(); 177 | // while (Date.now() - now < 101) { 178 | // 179 | // service.switcher(() => { 180 | // assert.equal(serviceInstance.age, 1); 181 | // done(); 182 | // }); 183 | // } 184 | // }); 185 | // }); 186 | 187 | }); 188 | -------------------------------------------------------------------------------- /src/decorators/__tests__/use-case.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-21 5 | */ 6 | 7 | import Bind from '../Bind'; 8 | import Inject from '../Inject'; 9 | import Throttle from '../Throttle'; 10 | 11 | @Inject('$q') 12 | export class Service { 13 | 14 | constructor(name = 'kuitos') { 15 | this.name = name; 16 | this.age = 0; 17 | } 18 | 19 | static getStaticName() { 20 | return 'kuitos'; 21 | } 22 | 23 | getQ() { 24 | return this._$q; 25 | } 26 | 27 | @Bind 28 | getName() { 29 | return this.name; 30 | } 31 | 32 | @Bind 33 | getName2() { 34 | return this.name + '2'; 35 | } 36 | 37 | @Throttle(100) 38 | resize() { 39 | this.age++; 40 | } 41 | 42 | } 43 | 44 | @Inject('$scope') 45 | class Controller { 46 | 47 | constructor() { 48 | this.recipe = 'componentController'; 49 | } 50 | 51 | @Bind 52 | getRecipe() { 53 | return this.recipe; 54 | } 55 | 56 | } 57 | 58 | class Component { 59 | 60 | constructor() { 61 | this.controller = Controller; 62 | this.bindings = { 63 | data: '=' 64 | }; 65 | } 66 | } 67 | 68 | export default angular 69 | .module('decorators', []) 70 | .service('Service', Service) 71 | .controller('Controller', Controller) 72 | .component('component', new Component()) 73 | .name; 74 | -------------------------------------------------------------------------------- /src/decorators/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-01-17 5 | */ 6 | 7 | import Inject from './Inject'; 8 | import Bind from './Bind'; 9 | import Throttle from './Throttle'; 10 | import Debounce from './Debounce'; 11 | import Delay from './Delay'; 12 | 13 | export { 14 | Inject, 15 | Bind, 16 | Throttle, 17 | Debounce, 18 | Delay 19 | }; 20 | -------------------------------------------------------------------------------- /src/deferred/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-03-02 5 | */ 6 | 7 | export default class Deferred { 8 | 9 | constructor() { 10 | 11 | this.promise = new Promise((resolve, reject) => { 12 | this._resolve = resolve; 13 | this._reject = reject; 14 | }); 15 | 16 | } 17 | 18 | resolve(value) { 19 | this._resolve.call(this.promise, value); 20 | } 21 | 22 | reject(value) { 23 | this._reject.call(this.promise, value); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/dynamic-export/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-05-12 5 | */ 6 | 7 | /** 8 | * dynamic export,make the commonjs export has the same behaviour with es module 9 | * @param exportsRef exports reference 10 | * @param prop 11 | * @param getter 12 | */ 13 | export default (exportsRef, prop, getter) => { 14 | 15 | Object.defineProperty(exportsRef, prop, { 16 | get() { 17 | return getter.apply(this); 18 | } 19 | }); 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /src/event-bus/__tests__/test-event-bus.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-05-04 5 | */ 6 | import { assert } from 'chai'; 7 | import EventBus from '../index'; 8 | 9 | describe('event-bus', () => { 10 | 11 | EventBus.on('test', (...args) => { 12 | assert.deepEqual(args, [10, 100, 1000]); 13 | }); 14 | 15 | EventBus.once('once', (...args) => { 16 | assert.deepEqual(args, [10, 100, 1000]); 17 | }); 18 | 19 | it('dispatch correctly', () => { 20 | EventBus.dispatch('test', 10, 100, 1000); 21 | }); 22 | 23 | it('once on', () => { 24 | EventBus.dispatch('once', 10, 100, 1000); 25 | assert.equal(EventBus.getListeners('once'), 0); 26 | }); 27 | 28 | it('add two listener, ensure execution order is correct', () => { 29 | 30 | EventBus.off('test'); 31 | 32 | let test = []; 33 | 34 | EventBus.on('test', () => { 35 | test.push(1); 36 | }); 37 | 38 | EventBus.on('test', () => { 39 | test.push(2); 40 | }); 41 | 42 | EventBus.dispatch('test'); 43 | 44 | assert.deepEqual(test, [1, 2]); 45 | }); 46 | 47 | it('off', () => { 48 | 49 | EventBus.off('test'); 50 | 51 | const off = EventBus.on('test', (...args) => { 52 | assert.equal(args[0], 1); 53 | }); 54 | 55 | EventBus.dispatch('test', 1); 56 | 57 | off(); 58 | 59 | assert.equal(EventBus.getListeners('test'), 0); 60 | 61 | }); 62 | 63 | it('off listener in listener itself', () => { 64 | 65 | EventBus.off('test'); 66 | 67 | let test = 0; 68 | let off = null; 69 | 70 | off = EventBus.on('test', () => { 71 | off(); 72 | }); 73 | 74 | EventBus.on('test', () => { 75 | test = 1; 76 | }); 77 | 78 | EventBus.dispatch('test'); 79 | 80 | off(); 81 | 82 | assert.equal(test, 1); 83 | }); 84 | 85 | it('off listener in another listener', () => { 86 | 87 | EventBus.off('test'); 88 | 89 | let test = 0; 90 | let off = null; 91 | 92 | EventBus.on('test', () => { 93 | off(); 94 | }); 95 | 96 | off = EventBus.on('test', () => { 97 | test = 1; 98 | }); 99 | 100 | EventBus.dispatch('test'); 101 | 102 | off(); 103 | 104 | assert.equal(test, 0); 105 | }); 106 | 107 | it('add listener in another listener', () => { 108 | 109 | EventBus.off('test'); 110 | 111 | let test = 0; 112 | 113 | EventBus.on('test', () => { 114 | EventBus.on('test', () => { 115 | test = 1; 116 | }); 117 | }); 118 | 119 | EventBus.dispatch('test'); 120 | 121 | assert.equal(test, 1); 122 | }); 123 | 124 | it('use once method to add listener', () => { 125 | 126 | EventBus.off('test'); 127 | 128 | let test = 0; 129 | let once = 0; 130 | let anotherTest = 0; 131 | 132 | EventBus.on('test', () => { 133 | test = 1; 134 | }); 135 | 136 | EventBus.once('test', () => { 137 | once = 1; 138 | }); 139 | 140 | EventBus.on('test', () => { 141 | anotherTest = 1; 142 | }); 143 | 144 | EventBus.dispatch('test'); 145 | 146 | assert.equal(test, 1); 147 | assert.equal(once, 1); 148 | assert.equal(anotherTest, 1); 149 | }); 150 | 151 | it('use once method add listener in another listener', () => { 152 | 153 | EventBus.off('test'); 154 | 155 | let test = 0; 156 | let once = 0; 157 | let anotherTest = 0; 158 | 159 | EventBus.on('test', () => { 160 | test = 1; 161 | EventBus.once('test', () => { 162 | once = 1; 163 | }); 164 | }); 165 | 166 | EventBus.on('test', () => { 167 | anotherTest = 1; 168 | }); 169 | 170 | EventBus.dispatch('test'); 171 | 172 | assert.equal(test, 1); 173 | assert.equal(once, 1); 174 | assert.equal(anotherTest, 1); 175 | }); 176 | 177 | 178 | it('listener queue should execute well after off action', () => { 179 | 180 | let called = false; 181 | const msg1 = 'k'; 182 | const off1 = EventBus.on('off1', msg => assert.equal(msg, msg1)); 183 | EventBus.on('off1', msg => { 184 | called = true; 185 | assert.equal(msg, msg1); 186 | }); 187 | off1(); 188 | EventBus.dispatch('off1', msg1); 189 | assert.isTrue(called); 190 | 191 | assert.equal(EventBus.getListeners('off1').length, 1); 192 | 193 | }); 194 | 195 | }); 196 | -------------------------------------------------------------------------------- /src/event-bus/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-05-04 5 | */ 6 | import { isFunction } from '../type-auth'; 7 | 8 | let topics = {}; 9 | 10 | /** 11 | * 事件总线。用于解决各模块间无法通过 $scope.$emit $scope.$on 等方式实现通信的问题(例如兄弟模块间通信) 12 | */ 13 | export default { 14 | 15 | /** 16 | * 订阅消息 17 | * @param topic 订阅消息名 18 | * @param listener 消息发布时触发的回调 19 | * @returns {Function} 取消订阅的反注册函数 20 | */ 21 | on: function (topic, listener) { 22 | 23 | let topicListeners = topics[topic] = topics[topic] || []; 24 | topicListeners.push(listener); 25 | 26 | return this.off.bind(this, topic, listener); 27 | }, 28 | 29 | once: function (topic, listener) { 30 | 31 | const onceListener = (...args) => { 32 | this.off(topic, onceListener); 33 | listener.apply(null, args); 34 | }; 35 | 36 | return this.on(topic, onceListener); 37 | }, 38 | 39 | /** 40 | * 移除注册信息 41 | * @param topic 消息名 42 | * @param listener 移除的注册函数,不传则移除全部注册 43 | */ 44 | off: function (topic, listener) { 45 | 46 | let topicListeners = topics[topic]; 47 | 48 | if (listener) { 49 | 50 | const listenerIndex = topicListeners.indexOf(listener); 51 | if (~listenerIndex) { 52 | topicListeners[listenerIndex] = null; 53 | } 54 | 55 | } else { 56 | // 清空 57 | topicListeners.length = 0; 58 | } 59 | 60 | return this; 61 | }, 62 | 63 | /** 64 | * 发布消息,支持链式调用 65 | */ 66 | dispatch: function (topic, ...args) { 67 | 68 | let i = 0; 69 | const listeners = topics[topic] || []; 70 | 71 | while (i < listeners.length) { 72 | 73 | const listener = listeners[i]; 74 | 75 | if (listener === null) { 76 | listeners.splice(i, 1); 77 | } else { 78 | if (isFunction(listener)) { 79 | listener.apply(null, args); 80 | } else { 81 | console.error('事件总线分发 %s 消息失败,注册的listener不是函数类型!', topic); 82 | } 83 | i++; 84 | } 85 | } 86 | 87 | return this; 88 | }, 89 | 90 | getListeners: function (topic) { 91 | return topics[topic] || []; 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /src/factory-creator/README.md: -------------------------------------------------------------------------------- 1 | # FactoryCreator 迁移指南 2 | 3 | 目前 `FactoryCreator.create` API 已不推荐使用,预计在 **后面两个版本之后** 废弃,建议已在使用的项目及时迁移。(原则上已不建议使用 `module.directive` 定义指令,优先使用 `module.component` )方法参照以下几个example: 4 | 5 | ## case 1 配合 `module.directive` 使用的 6 | 7 | ### 原写法(指令未注入使用外部服务) 8 | 9 | Directive.js 10 | 11 | ```js 12 | import Controller from './Controller'; 13 | 14 | export default class Direcitve { 15 | 16 | constructor() { 17 | this.restrict = 'A'; 18 | this.controller = Controller; 19 | } 20 | 21 | // .... 22 | } 23 | ``` 24 | 25 | index.js 26 | 27 | ```js 28 | import Directive from './Directive'; 29 | import { FactoryCreator } from 'angular-es-utils'; 30 | 31 | export angular 32 | .module('directive', []) 33 | .directive('ccDirective', FactoryCreator.create(Directive)) 34 | .name; 35 | ``` 36 | ### 迁移后写法 37 | index.js 38 | 39 | ```js 40 | import controller from './Controller'; 41 | 42 | const ddo = { 43 | restrict: 'A', 44 | controller 45 | }; 46 | 47 | export angular 48 | .module('directive', []) 49 | .directive('ccDirecrive', () => ddo) 50 | .name; 51 | ``` 52 | 53 | ### 原写法(指令注入了外部服务) 54 | 55 | Directive.js 56 | 57 | ```js 58 | import Controller from './Controller'; 59 | 60 | @Inject('$compile') 61 | export default class Direcitve { 62 | 63 | constructor() { 64 | this.restrict = 'A'; 65 | this.controller = Controller; 66 | } 67 | 68 | link() { 69 | this._$compile(); 70 | // ... 71 | } 72 | } 73 | ``` 74 | 75 | ### 迁移后写法 76 | 77 | ```js 78 | import injector from 'angular-es-utils/injector'; 79 | 80 | export default function directiveLink() { 81 | const $compile = injector.get('$compile'); 82 | $compile(); 83 | // ... 84 | } 85 | ``` 86 | 87 | index.js 88 | 89 | ```js 90 | import controller from './Controller'; 91 | import link from './directiveLink'; 92 | 93 | const ddo = { 94 | restrict: 'A', 95 | controller, 96 | link 97 | }; 98 | 99 | export angular 100 | .module('directive', []) 101 | .directive('ccDirecrive', () => ddo) 102 | .name; 103 | ``` 104 | 105 | ## case 2 配合 `module.filter`/`module.factory` 使用的 106 | 107 | filter 跟 factory 可以改造成 es6 module export出去,不需要定义成 filter/factory。filter/factory 中使用依赖注入的服务可以通过 `injector.get` 的方式获取。 108 | 109 | -------------------------------------------------------------------------------- /src/factory-creator/__tests__/test-factory-creator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-13 5 | */ 6 | 7 | import useCase from './use-case'; 8 | import {assert} from 'chai'; 9 | 10 | describe('factory creator', () => { 11 | 12 | let $compile, $rootScope, directive; 13 | 14 | beforeEach(angular.mock.module(useCase)); 15 | beforeEach(angular.mock.inject((_$compile_, _$rootScope_) => { 16 | $compile = _$compile_; 17 | $rootScope = _$rootScope_; 18 | 19 | const scope = $rootScope.$new(); 20 | Object.assign(scope, {data: {name: 'kuitos'}}); 21 | directive = $compile('')(scope); 22 | 23 | })); 24 | 25 | describe('transform directive constructor into factory', () => { 26 | 27 | it('controller $onInit should run before link function', () => { 28 | $rootScope.$digest(); 29 | document.body.appendChild(directive[0]); 30 | assert.include(directive.html(), 'kuitos rootScope'); 31 | }); 32 | 33 | }); 34 | 35 | }); 36 | -------------------------------------------------------------------------------- /src/factory-creator/__tests__/use-case.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-24 5 | */ 6 | 7 | import angular from 'angular'; 8 | import Inject from '../../decorators/Inject'; 9 | import FactoryCreator from '../index'; 10 | 11 | let data; 12 | 13 | @Inject('$rootScope') 14 | class Controller { 15 | 16 | $onInit() { 17 | this._$rootScope.name = 'controller'; 18 | } 19 | 20 | set data(value) { 21 | data = value; 22 | return value; 23 | } 24 | 25 | get data() { 26 | return `${data.name} ${this._$rootScope.name}`; 27 | } 28 | 29 | } 30 | 31 | @Inject('$rootScope') 32 | class Directive { 33 | 34 | constructor() { 35 | this.restrict = 'EA'; 36 | this.scope = {}; 37 | this.template = ''; 38 | this.controller = Controller; 39 | this.controllerAs = '$vm'; 40 | this.bindToController = { 41 | data: '=' 42 | }; 43 | } 44 | 45 | link() { 46 | this._$rootScope.name = 'rootScope'; 47 | } 48 | 49 | } 50 | 51 | export default angular 52 | .module('useCase', []) 53 | .directive('directive', FactoryCreator.create(Directive)) 54 | .name; 55 | -------------------------------------------------------------------------------- /src/factory-creator/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2015-12-29 5 | */ 6 | 7 | const FUNCTION_PRIVATE_PROPS = ['apply', 'arguments', 'bind', 'call', 'caller', 'constructor', 'Symbol']; 8 | 9 | export default { 10 | 11 | create(Constructor) { 12 | 13 | console.warn('FactoryCreator.create 方法将在下一版本废弃,请尽快使用别的替代解决方案!(迁移指南:https://github.com/kuitos/angular-es-utils/blob/master/src/factory-creator/README.md)'); 14 | 15 | function factory(...args) { 16 | 17 | let instance = new Constructor(...args); 18 | 19 | const prototype = Object.getPrototypeOf(instance); 20 | 21 | Object.getOwnPropertyNames(prototype).forEach(prop => { 22 | 23 | // 只处理非私有方法 24 | if (FUNCTION_PRIVATE_PROPS.indexOf(prop) === -1) { 25 | // 绑定实例到构造函数的每个方法下 26 | let fn = prototype[prop]; 27 | if (typeof fn === 'function') { 28 | prototype[prop] = fn.bind(instance); 29 | } 30 | } 31 | 32 | }); 33 | 34 | return instance; 35 | } 36 | 37 | factory.$inject = Constructor.$inject || []; 38 | 39 | return factory; 40 | } 41 | 42 | }; 43 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-02-02 5 | */ 6 | 7 | import FactoryCreator from './factory-creator'; 8 | import ModuleHelper from './module-helper'; 9 | import Deferred from './deferred'; 10 | import Animation from './animation'; 11 | import {getInjector} from './injector'; 12 | import genResource from './rs-generator'; 13 | import EventBus from './event-bus'; 14 | 15 | export * from './decorators'; 16 | 17 | export { 18 | FactoryCreator, 19 | ModuleHelper, 20 | Deferred, 21 | Animation, 22 | getInjector, 23 | genResource, 24 | EventBus 25 | }; 26 | -------------------------------------------------------------------------------- /src/injector/__tests__/test-injector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-27 5 | */ 6 | import angular from 'angular'; 7 | import {assert} from 'chai'; 8 | 9 | import {getInjector} from '../index'; 10 | 11 | describe('injector', () => { 12 | 13 | it('should equal to $injector service', angular.mock.inject($injector => { 14 | const div = document.createElement('div'); 15 | div.innerHTML = '
0
00
01
010
011
'; 16 | angular.bootstrap(div); 17 | const injector = getInjector(div); 18 | assert.isTrue(angular.equals(injector.modules.ng, $injector.modules.ng)); 19 | })); 20 | 21 | }); 22 | 23 | -------------------------------------------------------------------------------- /src/injector/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-25 5 | */ 6 | 7 | import angular from 'angular'; 8 | 9 | import dynamicExport from '../dynamic-export'; 10 | 11 | /** 12 | * 获取应用的injector,默认查询被ng-app标记的节点,否则从document.documentElement开始找 13 | * @param rootElement 14 | */ 15 | export function getInjector(rootElement = (document.querySelector('[ng-app]') || document.documentElement)) { 16 | 17 | const injector = angular.element(rootElement).injector(); 18 | 19 | if (injector) { 20 | return injector; 21 | } else { 22 | 23 | const childNodes = rootElement.childNodes; 24 | 25 | for (let i = 0; i < childNodes.length; i++) { 26 | 27 | const injector = getInjector(childNodes[i]); 28 | 29 | if (injector) { 30 | return injector; 31 | } 32 | } 33 | } 34 | 35 | return null; 36 | } 37 | 38 | // make commonjs have the same behavior with es6 module 39 | let injector = null; 40 | export default injector; 41 | dynamicExport(exports, 'default', () => injector || (injector = getInjector())); 42 | -------------------------------------------------------------------------------- /src/mappers/FieldsMapper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-02-17 5 | */ 6 | 7 | export default class FieldsMapper { 8 | 9 | static transform(data, schema) { 10 | 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/mock/db.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /src/module-helper/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-01-17 5 | */ 6 | 7 | import angular from 'angular'; 8 | 9 | export default { 10 | 11 | get(moduleName, deps) { 12 | 13 | try { 14 | return angular.module(moduleName); 15 | } catch (e) { 16 | return angular.module(moduleName, deps); 17 | } 18 | 19 | } 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /src/rs-generator/README.md: -------------------------------------------------------------------------------- 1 | ## rs-generator 2 | 基于$resource封装的resource生成器 3 | 4 | ### How To Use 5 | 6 | ```js 7 | import injector from 'angular-es-utils/injector'; 8 | import genResource, {setApiPrefix, defaultHttpConfigs} from 'angular-es-utils/rs-generator'; 9 | import dynamicExport from 'angular-es-utils/dynamic-export'; 10 | 11 | // 设置rest api前缀 12 | setApiPrefix('/rest/1.0'); 13 | 14 | // 设置请求通用配置 15 | defaultHttpConfigs.headers = { 16 | 'Content-Type': 'application/json', 17 | 'X-ID': () => window.localStorage.getItem('X-ID') 18 | }; 19 | 20 | // 由于$http api的限制,只能设置response/responseError拦截逻辑 21 | defaultHttpConfigs.interceptor = { 22 | response: response => {}, 23 | responseError: rejection => { 24 | if(rejection.status === 401){ 25 | injector.get('$location').url('/login'); 26 | } 27 | } 28 | }; 29 | 30 | /* ----------------- 导出resource方案 ----------------- */ 31 | // 方案1: 直接es6 export, 只有嵌入portal的子系统可以直接export 32 | export const User = genResource('/users/:userId', false, {userId: 1}, 33 | {authenticate: {method: 'GET'}}, 34 | {headers: {'X-AUTH-NAME': 'xxxx'}} 35 | ); 36 | 37 | // DEPRECATED!! 38 | // 2.x版本已废弃,genResource 自身已具备 lazy export 能力,所以直接使用方案 1 即可 39 | // 方案2: lazy export 40 | dynamicExport(exports, 'User', () => genResource('/users/:userId', false, {userId: 1}, 41 | {authenticate: {method: 'GET'}}, 42 | {headers: {'X-AUTH-NAME': 'xxxx'}} 43 | )); 44 | 45 | // DEPRECATED!! 46 | // 还不如方案2 47 | // 方案3: 使用angular service 48 | export default angular.module('module.services', []) 49 | .factory('User', () => genResource('/users/:userId', false, {userId: 1})) 50 | .name; 51 | ``` 52 | 53 | ### API 54 | 55 | 56 | * genResource 57 | 58 | `import genResource from 'angular-es-utils/rs-generator';` 59 | 60 | genResource(url, cache, params, additionalActions, additionalHttpConfigs) 61 | 62 | API参数用法更$resource服务一致,具体参见 [$resource](https://docs.angularjs.org/api/ngResource/service/$resource) 63 | 64 | * setApiPrefix 65 | `import {setApiPrefix} from 'angular-es-utils/rs-generator';` 66 | 67 | // 设置使用genResource生成的请求前缀 68 | setApiPrefix(apiPrefix) 69 | 70 | * defaultHttpConfigs 71 | // 设置使用genResource生成的请求通用配置,参考 [$resource usage actions](https://docs.angularjs.org/api/ngResource/service/$resource) 72 | 73 | ```js 74 | defaultHttpConfigs.headers = {xx:xxx}; 75 | defaultHttpConfigs.interceptor = xxxxx; 76 | ``` 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/rs-generator/__tests__/test-rs-generator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-06-21 5 | */ 6 | 7 | import angualr from 'angular'; 8 | import ngResource from 'angular-resource'; 9 | 10 | import { assert } from 'chai'; 11 | import sinon from 'sinon'; 12 | 13 | import injector from '../../injector'; 14 | import genResource, { defaultHttpConfigs } from '../index'; 15 | 16 | defaultHttpConfigs.headers.name = 'Kuitos_L'; 17 | const resource = genResource('/users', false, {userId: 'kuitos'}, { 18 | create: { 19 | method: 'PUT', 20 | name: 'create', 21 | headers: {name: 'lk', age: 20} 22 | } 23 | }, { 24 | name: 'kuitos', 25 | headers: {id: 100} 26 | }); 27 | 28 | describe('resource generator', () => { 29 | 30 | let sandbox = null; 31 | 32 | beforeEach(() => { 33 | angular.module('mock', [ngResource]).run($injector => angular.element(document.body).data('$injector', $injector)); 34 | sandbox = sinon.sandbox.create(); 35 | }); 36 | 37 | afterEach(() => { 38 | sandbox.restore(); 39 | }); 40 | 41 | it('config reference changed will influence resource value', () => { 42 | 43 | const response = { 44 | success: true, 45 | msg: 'wtf' 46 | }; 47 | 48 | let $httpBackend = null; 49 | 50 | angular.module('mock').config($httpProvider => $httpProvider.interceptors.push(() => ({ 51 | 52 | response(response) { 53 | 54 | const config = response.config; 55 | if (config.method === 'GET') { 56 | assert.equal(config.headers.name, 'Kuitos_L'); 57 | assert.equal(config.headers.age, undefined); 58 | assert.equal(config.headers['Cache-Control'], 'no-cache'); 59 | assert.equal(config.name, 'kuitos'); 60 | assert.equal(config.headers.id, 100); 61 | 62 | } 63 | 64 | if (config.method === 'PUT') { 65 | assert.equal(config.headers.name, 'lk'); 66 | assert.equal(config.headers['Cache-Control'], 'no-cache'); 67 | assert.equal(config.headers.age, 20); 68 | assert.equal(config.headers.id, 100); 69 | assert.equal(config.method, 'PUT'); 70 | assert.equal(config.name, 'create'); 71 | } 72 | 73 | return response; 74 | } 75 | 76 | }))); 77 | 78 | angular.mock.module('mock'); 79 | 80 | angualr.mock.inject((_$httpBackend_, $resource) => { 81 | 82 | $httpBackend = _$httpBackend_; 83 | 84 | sandbox.stub(injector, 'get', service => service === '$resource' ? $resource : {}); 85 | 86 | $httpBackend.whenGET('/users?userId=kuitos').respond(200, response); 87 | $httpBackend.whenPUT('/users?userId=kuitos').respond(200, response); 88 | 89 | }); 90 | 91 | resource.get().$promise.then(res => { 92 | assert.equal(response.success, res.success); 93 | assert.equal(response.msg, res.msg); 94 | }); 95 | 96 | $httpBackend.flush(); 97 | 98 | }); 99 | 100 | }); 101 | -------------------------------------------------------------------------------- /src/rs-generator/index.d.ts: -------------------------------------------------------------------------------- 1 | import 'angular-resource'; 2 | export declare function setApiPrefix(prefix: any): void; 3 | export declare let COMMON_HEADERS: { 4 | 'Cache-Control': string; 5 | 'X-Requested-With': string; 6 | }; 7 | export declare let defaultHttpConfigs: { 8 | headers: {}; 9 | interceptor: {}; 10 | }; 11 | declare var _default: (url: string, cache?: any, params?: Object, additionalActions?: Object, additionalHttpConfigs?: Object, options?: Object) => T; 12 | export default _default; 13 | -------------------------------------------------------------------------------- /src/rs-generator/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-05-11 5 | */ 6 | 7 | import angular from 'angular'; 8 | import lazyInitialize from 'esnext-utils/proxy/lazy-initialize'; 9 | 10 | import injector from '../injector'; 11 | 12 | let apiPrefix = ''; 13 | 14 | export function setApiPrefix(prefix) { 15 | apiPrefix = prefix; 16 | } 17 | 18 | export let COMMON_HEADERS = { 19 | 'Cache-Control': 'no-cache', 20 | 'X-Requested-With': 'https://github.com/kuitos' 21 | }; 22 | 23 | export let defaultHttpConfigs = { 24 | headers: {}, 25 | interceptor: {} 26 | }; 27 | 28 | export default (url, cache, params, additionalActions = {}, additionalHttpConfigs = {}, options) => { 29 | 30 | const requestConfigs = angular.merge({}, {headers: COMMON_HEADERS}, defaultHttpConfigs, additionalHttpConfigs); 31 | 32 | // 将默认配置复制到新添加的action里 33 | Object.keys(additionalActions).forEach(action => { 34 | additionalActions[action] = angular.merge({}, requestConfigs, additionalActions[action]); 35 | }); 36 | 37 | // 默认cache为defaultRestCache 38 | // 自定义配置(配合$http interceptor) 39 | const DEFAULT_ACTIONS = { 40 | // 查询,结果为对象 41 | 'get': {method: 'GET', cache, ...requestConfigs}, 42 | // 查询,结果为数组 43 | 'query': {method: 'GET', isArray: true, cache, ...requestConfigs}, 44 | // 保存(新增) 45 | 'save': {method: 'POST', cache, ...requestConfigs}, 46 | // 修改(全量) 47 | 'update': {method: 'PUT', cache, ...requestConfigs}, 48 | // 修改(部分) 49 | 'patch': {method: 'PATCH', cache, ...requestConfigs}, 50 | // 逻辑删除 51 | 'remove': {method: 'DELETE', cache, ...requestConfigs}, 52 | // 物理删除 53 | 'delete': {method: 'DELETE', cache, ...requestConfigs} 54 | }; 55 | 56 | return lazyInitialize({}, () => injector.get('$resource')(apiPrefix + url, params, {...DEFAULT_ACTIONS, ...additionalActions}, options)); 57 | }; 58 | -------------------------------------------------------------------------------- /src/type-auth/__tests__/test-type-auth.js: -------------------------------------------------------------------------------- 1 | import { assert } from 'chai'; 2 | 3 | import { isObject, isArray, isPromiseLike, isRegExp } from '../index'; 4 | 5 | describe('type-auth', () => { 6 | 7 | it('isObject', () => { 8 | assert.isTrue(isObject({})); 9 | assert.isTrue(isObject([])); 10 | assert.isTrue(isObject(/s+/g)); 11 | assert.isTrue(isObject(function () {})); 12 | }); 13 | 14 | it('isArray', () => { 15 | assert.isTrue(isArray([])); 16 | assert.isNotTrue(isArray({})); 17 | }); 18 | 19 | it('isPromiseLike', () => { 20 | const obj = { 21 | then: () => { 22 | } 23 | }; 24 | assert.isTrue(isPromiseLike(obj)); 25 | assert.isTrue(isPromiseLike(new Promise((resolve, reject) => { 26 | }))); 27 | assert.isNotTrue(isPromiseLike({})); 28 | assert.isNotTrue(isPromiseLike([])); 29 | }); 30 | 31 | it('isRegExp', () => { 32 | assert.isTrue(isRegExp(/ui/g)); 33 | assert.isNotTrue(isRegExp('/ui/g')); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/type-auth/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-06-07 5 | */ 6 | 7 | const msie = window.document.documentMode; 8 | const toString = Object.prototype.toString; 9 | 10 | export function isClass(func) { 11 | // IE 9-11 do not support classes and IE9 leaks with the code below. 12 | if (msie <= 11) { 13 | return false; 14 | } 15 | // Workaround for MS Edge. 16 | // Check https://connect.microsoft.com/IE/Feedback/Details/2211653 17 | return typeof func === 'function' && /^(?:class\s|constructor\()/.test(Function.prototype.toString.call(func)); 18 | } 19 | 20 | export function isNumber() { 21 | return typeof value === 'number'; 22 | } 23 | 24 | export function isRegExp(value) { 25 | return toString.call(value) === '[object RegExp]'; 26 | } 27 | 28 | // the specification 29 | // @see https://github.com/kuitos/angular-es-utils/pull/5 30 | export function isObject(value) { 31 | return value != null && (typeof value === 'object' || typeof value === 'function'); 32 | } 33 | 34 | export const isArray = Array.isArray; 35 | 36 | export function isString(value) { 37 | return typeof value === 'string'; 38 | } 39 | 40 | export function isFunction(value) { 41 | return typeof value === 'function'; 42 | } 43 | 44 | export function isPromiseLike(obj) { 45 | return !!obj && typeof obj.then === 'function'; 46 | } 47 | 48 | export function isElement(node) { 49 | return !!(node && 50 | (node.nodeName || (node.prop && node.attr && node.find))); // We have an on and find method part of jQuery API. 51 | } 52 | 53 | export function isDefined(value) { 54 | return typeof value !== 'undefined'; 55 | } 56 | -------------------------------------------------------------------------------- /test/karma.base.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-07-25 5 | */ 6 | 7 | var path = require('path'); 8 | 9 | module.exports = { 10 | 11 | // base path that will be used to resolve all patterns (eg. files, exclude) 12 | basePath: './', 13 | 14 | // frameworks to use 15 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter 16 | frameworks: ['mocha'], 17 | 18 | client: { 19 | mocha: { 20 | timeout: 15000 21 | } 22 | }, 23 | 24 | // list of files / patterns to load in the browser 25 | files: [ 26 | 'test.index.js' 27 | ], 28 | 29 | // list of files to exclude 30 | exclude: [], 31 | 32 | // preprocess matching files before serving them to the browser 33 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 34 | preprocessors: { 35 | 'test.index.js': ['webpack'] 36 | }, 37 | 38 | // Webpack 39 | webpack: { 40 | devtool: 'eval', 41 | output: { 42 | pathinfo: true 43 | }, 44 | eslint: { 45 | configFile: '.eslintrc', 46 | emitWarning: true, 47 | emitError: true, 48 | formatter: require('eslint-friendly-formatter') 49 | }, 50 | module: { 51 | preLoaders: [{ 52 | test: /\.js$/, 53 | loader: 'eslint-loader', 54 | exclude: /node_modules/, 55 | include: [path.join(__dirname, '../src')] 56 | }], 57 | loaders: [ 58 | { 59 | test: /\.js$/, 60 | loaders: ['babel'], 61 | exclude: /(node_modules|bower_components)/, 62 | include: [path.join(__dirname, '../src'), path.join(__dirname, '../test')] 63 | } 64 | ] 65 | } 66 | 67 | }, 68 | 69 | // Webpack middleware 70 | webpackMiddleware: { 71 | noInfo: true 72 | }, 73 | 74 | // test results reporter to use 75 | // possible values: 'dots', 'progress' 76 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter 77 | reporters: ['mocha'], 78 | 79 | // web server port 80 | port: 9876, 81 | 82 | // enable / disable colors in the output (reporters and logs) 83 | colors: true, 84 | 85 | // level of logging 86 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG 87 | // logLevel: config.LOG_INFO, 88 | 89 | // enable / disable watching file and executing tests whenever any file changes 90 | autoWatch: true, 91 | 92 | // Continuous Integration mode 93 | // if true, Karma captures browsers, runs the tests and exits 94 | singleRun: false, 95 | 96 | // Concurrency level 97 | // how many browser should be started simultaneous 98 | concurrency: Infinity 99 | }; 100 | -------------------------------------------------------------------------------- /test/karma.cover.conf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-07-25 5 | */ 6 | 7 | var base = require('./karma.base.conf'); 8 | 9 | module.exports = function (config) { 10 | 11 | var opts = Object.assign(base, { 12 | browsers: ['Firefox'], 13 | reporters: ['progress', 'coverage'], 14 | coverageReporter: { 15 | reporters: [ 16 | {type: 'lcov', dir: './coverage', subdir: '.'}, 17 | {type: 'text-summary', dir: './coverage', subdir: '.'} 18 | ] 19 | } 20 | }); 21 | 22 | opts.singleRun = true; 23 | opts.files.unshift('../node_modules/babel-polyfill/browser.js'); 24 | 25 | opts.webpack.module.postLoaders = [ 26 | { 27 | test: /\.js$/, 28 | exclude: /node_modules|__tests__|test/, 29 | loader: 'istanbul-instrumenter' 30 | } 31 | ]; 32 | 33 | config.set(opts); 34 | }; 35 | -------------------------------------------------------------------------------- /test/karma.unit.conf.js: -------------------------------------------------------------------------------- 1 | var base = require('./karma.base.conf'); 2 | 3 | module.exports = function (config) { 4 | 5 | config.set(Object.assign(base, { 6 | browsers: ['Chrome'], 7 | reporters: ['mocha'] 8 | })); 9 | }; 10 | -------------------------------------------------------------------------------- /test/test.index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Kuitos 3 | * @homepage https://github.com/kuitos/ 4 | * @since 2016-04-21 5 | */ 6 | 7 | import 'angular'; 8 | import 'angular-mocks'; 9 | 10 | const context = require.context('../src', true, /\/__tests__\/test-.*\.js$/); 11 | context.keys().forEach(context); 12 | 13 | // require all `src/**/index.js` 14 | const appContext = require.context('../src', true, /[a-z\-]+\/[A-Za-z]+\.js$/); 15 | appContext.keys().forEach(appContext); 16 | -------------------------------------------------------------------------------- /typings/angularjs/angular-resource.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.5 (ngResource module) 2 | // Project: http://angularjs.org 3 | // Definitions by: Diego Vilar , Michael Jess 4 | // Definitions: https://github.com/daptiv/DefinitelyTyped 5 | 6 | /// 7 | 8 | declare module 'angular-resource' { 9 | var _: string; 10 | export = _; 11 | } 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | // ngResource module (angular-resource.js) 15 | /////////////////////////////////////////////////////////////////////////////// 16 | declare namespace angular.resource { 17 | 18 | /** 19 | * Currently supported options for the $resource factory options argument. 20 | */ 21 | interface IResourceOptions { 22 | /** 23 | * If true then the trailing slashes from any calculated URL will be stripped (defaults to true) 24 | */ 25 | stripTrailingSlashes?: boolean; 26 | /** 27 | * If true, the request made by a "non-instance" call will be cancelled (if not already completed) by calling 28 | * $cancelRequest() on the call's return value. This can be overwritten per action. (Defaults to false.) 29 | */ 30 | cancellable?: boolean; 31 | } 32 | 33 | 34 | /////////////////////////////////////////////////////////////////////////// 35 | // ResourceService 36 | // see http://docs.angularjs.org/api/ngResource.$resource 37 | // Most part of the following definitions were achieved by analyzing the 38 | // actual implementation, since the documentation doesn't seem to cover 39 | // that deeply. 40 | /////////////////////////////////////////////////////////////////////////// 41 | interface IResourceService { 42 | (url: string, paramDefaults?: any, 43 | /** example: {update: { method: 'PUT' }, delete: deleteDescriptor } 44 | where deleteDescriptor : IActionDescriptor */ 45 | actions?: IActionHash, options?: IResourceOptions): IResourceClass>; 46 | (url: string, paramDefaults?: any, 47 | /** example: {update: { method: 'PUT' }, delete: deleteDescriptor } 48 | where deleteDescriptor : IActionDescriptor */ 49 | actions?: IActionHash, options?: IResourceOptions): U; 50 | (url: string, paramDefaults?: any, 51 | /** example: {update: { method: 'PUT' }, delete: deleteDescriptor } 52 | where deleteDescriptor : IActionDescriptor */ 53 | actions?: IActionHash, options?: IResourceOptions): IResourceClass; 54 | } 55 | 56 | // Hash of action descriptors allows custom action names 57 | interface IActionHash { 58 | [action: string]: IActionDescriptor 59 | } 60 | 61 | // Just a reference to facilitate describing new actions 62 | interface IActionDescriptor { 63 | method: string; 64 | params?: any; 65 | url?: string; 66 | isArray?: boolean; 67 | transformRequest?: angular.IHttpRequestTransformer | angular.IHttpRequestTransformer[]; 68 | transformResponse?: angular.IHttpResponseTransformer | angular.IHttpResponseTransformer[]; 69 | headers?: any; 70 | cache?: boolean | angular.ICacheObject; 71 | /** 72 | * Note: In contrast to $http.config, promises are not supported in $resource, because the same value 73 | * would be used for multiple requests. If you are looking for a way to cancel requests, you should 74 | * use the cancellable option. 75 | */ 76 | timeout?: number 77 | cancellable?: boolean; 78 | withCredentials?: boolean; 79 | responseType?: string; 80 | interceptor?: IHttpInterceptor; 81 | } 82 | 83 | // Allow specify more resource methods 84 | // No need to add duplicates for all four overloads. 85 | interface IResourceMethod { 86 | (): T; 87 | (params: Object): T; 88 | (success: Function, error?: Function): T; 89 | (params: Object, success: Function, error?: Function): T; 90 | (params: Object, data: Object, success?: Function, error?: Function): T; 91 | } 92 | 93 | // Allow specify resource moethod which returns the array 94 | // No need to add duplicates for all four overloads. 95 | interface IResourceArrayMethod { 96 | (): IResourceArray; 97 | (params: Object): IResourceArray; 98 | (success: Function, error?: Function): IResourceArray; 99 | (params: Object, success: Function, error?: Function): IResourceArray; 100 | (params: Object, data: Object, success?: Function, error?: Function): IResourceArray; 101 | } 102 | 103 | // Baseclass for every resource with default actions. 104 | // If you define your new actions for the resource, you will need 105 | // to extend this interface and typecast the ResourceClass to it. 106 | // 107 | // In case of passing the first argument as anything but a function, 108 | // it's gonna be considered data if the action method is POST, PUT or 109 | // PATCH (in other words, methods with body). Otherwise, it's going 110 | // to be considered as parameters to the request. 111 | // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L461-L465 112 | // 113 | // Only those methods with an HTTP body do have 'data' as first parameter: 114 | // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L463 115 | // More specifically, those methods are POST, PUT and PATCH: 116 | // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L432 117 | // 118 | // Also, static calls always return the IResource (or IResourceArray) retrieved 119 | // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L538-L549 120 | interface IResourceClass { 121 | new(dataOrParams? : any) : T & IResource; 122 | get: IResourceMethod; 123 | 124 | query: IResourceArrayMethod; 125 | 126 | save: IResourceMethod; 127 | 128 | remove: IResourceMethod; 129 | 130 | delete: IResourceMethod; 131 | } 132 | 133 | // Instance calls always return the the promise of the request which retrieved the object 134 | // https://github.com/angular/angular.js/blob/v1.2.0/src/ngResource/resource.js#L538-L546 135 | interface IResource { 136 | $get(): angular.IPromise; 137 | $get(params?: Object, success?: Function, error?: Function): angular.IPromise; 138 | $get(success: Function, error?: Function): angular.IPromise; 139 | 140 | $query(): angular.IPromise>; 141 | $query(params?: Object, success?: Function, error?: Function): angular.IPromise>; 142 | $query(success: Function, error?: Function): angular.IPromise>; 143 | 144 | $save(): angular.IPromise; 145 | $save(params?: Object, success?: Function, error?: Function): angular.IPromise; 146 | $save(success: Function, error?: Function): angular.IPromise; 147 | 148 | $remove(): angular.IPromise; 149 | $remove(params?: Object, success?: Function, error?: Function): angular.IPromise; 150 | $remove(success: Function, error?: Function): angular.IPromise; 151 | 152 | $delete(): angular.IPromise; 153 | $delete(params?: Object, success?: Function, error?: Function): angular.IPromise; 154 | $delete(success: Function, error?: Function): angular.IPromise; 155 | 156 | $cancelRequest(): void; 157 | 158 | /** the promise of the original server interaction that created this instance. **/ 159 | $promise : angular.IPromise; 160 | $resolved : boolean; 161 | toJSON(): T; 162 | } 163 | 164 | /** 165 | * Really just a regular Array object with $promise and $resolve attached to it 166 | */ 167 | interface IResourceArray extends Array> { 168 | /** the promise of the original server interaction that created this collection. **/ 169 | $promise : angular.IPromise>; 170 | $resolved : boolean; 171 | } 172 | 173 | /** when creating a resource factory via IModule.factory */ 174 | interface IResourceServiceFactoryFunction { 175 | ($resource: angular.resource.IResourceService): IResourceClass; 176 | >($resource: angular.resource.IResourceService): U; 177 | } 178 | 179 | // IResourceServiceProvider used to configure global settings 180 | interface IResourceServiceProvider extends angular.IServiceProvider { 181 | 182 | defaults: IResourceOptions; 183 | } 184 | 185 | } 186 | 187 | /** extensions to base ng based on using angular-resource */ 188 | declare namespace angular { 189 | 190 | interface IModule { 191 | /** creating a resource service factory */ 192 | factory(name: string, resourceServiceFactoryFunction: angular.resource.IResourceServiceFactoryFunction): IModule; 193 | } 194 | 195 | namespace auto { 196 | interface IInjectorService { 197 | get(name: '$resource'): ng.resource.IResourceService; 198 | } 199 | } 200 | } 201 | 202 | interface Array 203 | { 204 | /** the promise of the original server interaction that created this collection. **/ 205 | $promise : angular.IPromise>; 206 | $resolved : boolean; 207 | } 208 | -------------------------------------------------------------------------------- /typings/angularjs/angular.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Angular JS 1.5 2 | // Project: http://angularjs.org 3 | // Definitions by: Diego Vilar , Georgii Dolzhykov 4 | // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped 5 | 6 | 7 | /// 8 | 9 | declare var angular: angular.IAngularStatic; 10 | 11 | // Support for painless dependency injection 12 | interface Function { 13 | $inject?: string[]; 14 | } 15 | 16 | // Collapse angular into ng 17 | import ng = angular; 18 | // Support AMD require 19 | declare module 'angular' { 20 | export = angular; 21 | } 22 | 23 | /////////////////////////////////////////////////////////////////////////////// 24 | // ng module (angular.js) 25 | /////////////////////////////////////////////////////////////////////////////// 26 | declare namespace angular { 27 | 28 | type Injectable = T | (string | T)[]; 29 | 30 | // not directly implemented, but ensures that constructed class implements $get 31 | interface IServiceProviderClass { 32 | new (...args: any[]): IServiceProvider; 33 | } 34 | 35 | interface IServiceProviderFactory { 36 | (...args: any[]): IServiceProvider; 37 | } 38 | 39 | // All service providers extend this interface 40 | interface IServiceProvider { 41 | $get: any; 42 | } 43 | 44 | interface IAngularBootstrapConfig { 45 | strictDi?: boolean; 46 | } 47 | 48 | /////////////////////////////////////////////////////////////////////////// 49 | // AngularStatic 50 | // see http://docs.angularjs.org/api 51 | /////////////////////////////////////////////////////////////////////////// 52 | interface IAngularStatic { 53 | bind(context: any, fn: Function, ...args: any[]): Function; 54 | 55 | /** 56 | * Use this function to manually start up angular application. 57 | * 58 | * @param element DOM element which is the root of angular application. 59 | * @param modules An array of modules to load into the application. 60 | * Each item in the array should be the name of a predefined module or a (DI annotated) 61 | * function that will be invoked by the injector as a config block. 62 | * @param config an object for defining configuration options for the application. The following keys are supported: 63 | * - `strictDi`: disable automatic function annotation for the application. This is meant to assist in finding bugs which break minified code. 64 | */ 65 | bootstrap(element: string|Element|JQuery|Document, modules?: (string|Function|any[])[], config?: IAngularBootstrapConfig): auto.IInjectorService; 66 | 67 | /** 68 | * Creates a deep copy of source, which should be an object or an array. 69 | * 70 | * - If no destination is supplied, a copy of the object or array is created. 71 | * - If a destination is provided, all of its elements (for array) or properties (for objects) are deleted and then all elements/properties from the source are copied to it. 72 | * - If source is not an object or array (inc. null and undefined), source is returned. 73 | * - If source is identical to 'destination' an exception will be thrown. 74 | * 75 | * @param source The source that will be used to make a copy. Can be any type, including primitives, null, and undefined. 76 | * @param destination Destination into which the source is copied. If provided, must be of the same type as source. 77 | */ 78 | copy(source: T, destination?: T): T; 79 | 80 | /** 81 | * Wraps a raw DOM element or HTML string as a jQuery element. 82 | * 83 | * If jQuery is available, angular.element is an alias for the jQuery function. If jQuery is not available, angular.element delegates to Angular's built-in subset of jQuery, called "jQuery lite" or "jqLite." 84 | */ 85 | element: JQueryStatic; 86 | equals(value1: any, value2: any): boolean; 87 | extend(destination: any, ...sources: any[]): any; 88 | 89 | /** 90 | * Invokes the iterator function once for each item in obj collection, which can be either an object or an array. The iterator function is invoked with iterator(value, key), where value is the value of an object property or an array element and key is the object property key or array element index. Specifying a context for the function is optional. 91 | * 92 | * It is worth noting that .forEach does not iterate over inherited properties because it filters using the hasOwnProperty method. 93 | * 94 | * @param obj Object to iterate over. 95 | * @param iterator Iterator function. 96 | * @param context Object to become context (this) for the iterator function. 97 | */ 98 | forEach(obj: T[], iterator: (value: T, key: number) => any, context?: any): any; 99 | /** 100 | * Invokes the iterator function once for each item in obj collection, which can be either an object or an array. The iterator function is invoked with iterator(value, key), where value is the value of an object property or an array element and key is the object property key or array element index. Specifying a context for the function is optional. 101 | * 102 | * It is worth noting that .forEach does not iterate over inherited properties because it filters using the hasOwnProperty method. 103 | * 104 | * @param obj Object to iterate over. 105 | * @param iterator Iterator function. 106 | * @param context Object to become context (this) for the iterator function. 107 | */ 108 | forEach(obj: { [index: string]: T; }, iterator: (value: T, key: string) => any, context?: any): any; 109 | /** 110 | * Invokes the iterator function once for each item in obj collection, which can be either an object or an array. The iterator function is invoked with iterator(value, key), where value is the value of an object property or an array element and key is the object property key or array element index. Specifying a context for the function is optional. 111 | * 112 | * It is worth noting that .forEach does not iterate over inherited properties because it filters using the hasOwnProperty method. 113 | * 114 | * @param obj Object to iterate over. 115 | * @param iterator Iterator function. 116 | * @param context Object to become context (this) for the iterator function. 117 | */ 118 | forEach(obj: any, iterator: (value: any, key: any) => any, context?: any): any; 119 | 120 | fromJson(json: string): any; 121 | identity(arg?: T): T; 122 | injector(modules?: any[], strictDi?: boolean): auto.IInjectorService; 123 | isArray(value: any): value is Array; 124 | isDate(value: any): value is Date; 125 | isDefined(value: any): boolean; 126 | isElement(value: any): boolean; 127 | isFunction(value: any): value is Function; 128 | isNumber(value: any): value is number; 129 | isObject(value: any): value is Object; 130 | isObject(value: any): value is T; 131 | isString(value: any): value is string; 132 | isUndefined(value: any): boolean; 133 | lowercase(str: string): string; 134 | 135 | /** 136 | * Deeply extends the destination object dst by copying own enumerable properties from the src object(s) to dst. You can specify multiple src objects. If you want to preserve original objects, you can do so by passing an empty object as the target: var object = angular.merge({}, object1, object2). 137 | * 138 | * Unlike extend(), merge() recursively descends into object properties of source objects, performing a deep copy. 139 | * 140 | * @param dst Destination object. 141 | * @param src Source object(s). 142 | */ 143 | merge(dst: any, ...src: any[]): any; 144 | 145 | /** 146 | * The angular.module is a global place for creating, registering and retrieving Angular modules. All modules (angular core or 3rd party) that should be available to an application must be registered using this mechanism. 147 | * 148 | * When passed two or more arguments, a new module is created. If passed only one argument, an existing module (the name passed as the first argument to module) is retrieved. 149 | * 150 | * @param name The name of the module to create or retrieve. 151 | * @param requires The names of modules this module depends on. If specified then new module is being created. If unspecified then the module is being retrieved for further configuration. 152 | * @param configFn Optional configuration function for the module. 153 | */ 154 | module( 155 | name: string, 156 | requires?: string[], 157 | configFn?: Function): IModule; 158 | 159 | noop(...args: any[]): void; 160 | reloadWithDebugInfo(): void; 161 | toJson(obj: any, pretty?: boolean | number): string; 162 | uppercase(str: string): string; 163 | version: { 164 | full: string; 165 | major: number; 166 | minor: number; 167 | dot: number; 168 | codeName: string; 169 | }; 170 | 171 | /** 172 | * If window.name contains prefix NG_DEFER_BOOTSTRAP! when angular.bootstrap is called, the bootstrap process will be paused until angular.resumeBootstrap() is called. 173 | * @param extraModules An optional array of modules that should be added to the original list of modules that the app was about to be bootstrapped with. 174 | */ 175 | resumeBootstrap?(extraModules?: string[]): ng.auto.IInjectorService; 176 | } 177 | 178 | /////////////////////////////////////////////////////////////////////////// 179 | // Module 180 | // see http://docs.angularjs.org/api/angular.Module 181 | /////////////////////////////////////////////////////////////////////////// 182 | interface IModule { 183 | /** 184 | * Use this method to register a component. 185 | * 186 | * @param name The name of the component. 187 | * @param options A definition object passed into the component. 188 | */ 189 | component(name: string, options: IComponentOptions): IModule; 190 | /** 191 | * Use this method to register work which needs to be performed on module loading. 192 | * 193 | * @param configFn Execute this function on module load. Useful for service configuration. 194 | */ 195 | config(configFn: Function): IModule; 196 | /** 197 | * Use this method to register work which needs to be performed on module loading. 198 | * 199 | * @param inlineAnnotatedFunction Execute this function on module load. Useful for service configuration. 200 | */ 201 | config(inlineAnnotatedFunction: any[]): IModule; 202 | config(object: Object): IModule; 203 | /** 204 | * Register a constant service, such as a string, a number, an array, an object or a function, with the $injector. Unlike value it can be injected into a module configuration function (see config) and it cannot be overridden by an Angular decorator. 205 | * 206 | * @param name The name of the constant. 207 | * @param value The constant value. 208 | */ 209 | constant(name: string, value: T): IModule; 210 | constant(object: Object): IModule; 211 | /** 212 | * The $controller service is used by Angular to create new controllers. 213 | * 214 | * This provider allows controller registration via the register method. 215 | * 216 | * @param name Controller name, or an object map of controllers where the keys are the names and the values are the constructors. 217 | * @param controllerConstructor Controller constructor fn (optionally decorated with DI annotations in the array notation). 218 | */ 219 | controller(name: string, controllerConstructor: Injectable): IModule; 220 | controller(object: {[name: string]: Injectable}): IModule; 221 | /** 222 | * Register a new directive with the compiler. 223 | * 224 | * @param name Name of the directive in camel-case (i.e. ngBind which will match as ng-bind) 225 | * @param directiveFactory An injectable directive factory function. 226 | */ 227 | directive(name: string, directiveFactory: Injectable): IModule; 228 | directive(object: {[directiveName: string]: Injectable}): IModule; 229 | /** 230 | * Register a service factory, which will be called to return the service instance. This is short for registering a service where its provider consists of only a $get property, which is the given service factory function. You should use $provide.factory(getFn) if you do not need to configure your service in a provider. 231 | * 232 | * @param name The name of the instance. 233 | * @param $getFn The $getFn for the instance creation. Internally this is a short hand for $provide.provider(name, {$get: $getFn}). 234 | */ 235 | factory(name: string, $getFn: Injectable): IModule; 236 | factory(object: {[name: string]: Injectable}): IModule; 237 | filter(name: string, filterFactoryFunction: Injectable): IModule; 238 | filter(object: {[name: string]: Injectable}): IModule; 239 | provider(name: string, serviceProviderFactory: IServiceProviderFactory): IModule; 240 | provider(name: string, serviceProviderConstructor: IServiceProviderClass): IModule; 241 | provider(name: string, inlineAnnotatedConstructor: any[]): IModule; 242 | provider(name: string, providerObject: IServiceProvider): IModule; 243 | provider(object: Object): IModule; 244 | /** 245 | * Run blocks are the closest thing in Angular to the main method. A run block is the code which needs to run to kickstart the application. It is executed after all of the service have been configured and the injector has been created. Run blocks typically contain code which is hard to unit-test, and for this reason should be declared in isolated modules, so that they can be ignored in the unit-tests. 246 | */ 247 | run(initializationFunction: Injectable): IModule; 248 | /** 249 | * Register a service constructor, which will be invoked with new to create the service instance. This is short for registering a service where its provider's $get property is a factory function that returns an instance instantiated by the injector from the service constructor function. 250 | * 251 | * @param name The name of the instance. 252 | * @param serviceConstructor An injectable class (constructor function) that will be instantiated. 253 | */ 254 | service(name: string, serviceConstructor: Injectable): IModule; 255 | service(object: {[name: string]: Injectable}): IModule; 256 | /** 257 | * Register a value service with the $injector, such as a string, a number, an array, an object or a function. This is short for registering a service where its provider's $get property is a factory function that takes no arguments and returns the value service. 258 | 259 | Value services are similar to constant services, except that they cannot be injected into a module configuration function (see config) but they can be overridden by an Angular decorator. 260 | * 261 | * @param name The name of the instance. 262 | * @param value The value. 263 | */ 264 | value(name: string, value: T): IModule; 265 | value(object: Object): IModule; 266 | 267 | /** 268 | * Register a service decorator with the $injector. A service decorator intercepts the creation of a service, allowing it to override or modify the behaviour of the service. The object returned by the decorator may be the original service, or a new service object which replaces or wraps and delegates to the original service. 269 | * @param name The name of the service to decorate 270 | * @param decorator This function will be invoked when the service needs to be instantiated and should return the decorated service instance. The function is called using the injector.invoke method and is therefore fully injectable. Local injection arguments: $delegate - The original service instance, which can be monkey patched, configured, decorated or delegated to. 271 | */ 272 | decorator(name: string, decorator: Injectable): IModule; 273 | 274 | // Properties 275 | name: string; 276 | requires: string[]; 277 | } 278 | 279 | /////////////////////////////////////////////////////////////////////////// 280 | // Attributes 281 | // see http://docs.angularjs.org/api/ng.$compile.directive.Attributes 282 | /////////////////////////////////////////////////////////////////////////// 283 | interface IAttributes { 284 | /** 285 | * this is necessary to be able to access the scoped attributes. it's not very elegant 286 | * because you have to use attrs['foo'] instead of attrs.foo but I don't know of a better way 287 | * this should really be limited to return string but it creates this problem: http://stackoverflow.com/q/17201854/165656 288 | */ 289 | [name: string]: any; 290 | 291 | /** 292 | * Converts an attribute name (e.g. dash/colon/underscore-delimited string, optionally prefixed with x- or data-) to its normalized, camelCase form. 293 | * 294 | * Also there is special case for Moz prefix starting with upper case letter. 295 | * 296 | * For further information check out the guide on @see https://docs.angularjs.org/guide/directive#matching-directives 297 | */ 298 | $normalize(name: string): string; 299 | 300 | /** 301 | * Adds the CSS class value specified by the classVal parameter to the 302 | * element. If animations are enabled then an animation will be triggered 303 | * for the class addition. 304 | */ 305 | $addClass(classVal: string): void; 306 | 307 | /** 308 | * Removes the CSS class value specified by the classVal parameter from the 309 | * element. If animations are enabled then an animation will be triggered for 310 | * the class removal. 311 | */ 312 | $removeClass(classVal: string): void; 313 | 314 | /** 315 | * Adds and removes the appropriate CSS class values to the element based on the difference between 316 | * the new and old CSS class values (specified as newClasses and oldClasses). 317 | */ 318 | $updateClass(newClasses: string, oldClasses: string): void; 319 | 320 | /** 321 | * Set DOM element attribute value. 322 | */ 323 | $set(key: string, value: any): void; 324 | 325 | /** 326 | * Observes an interpolated attribute. 327 | * The observer function will be invoked once during the next $digest 328 | * following compilation. The observer is then invoked whenever the 329 | * interpolated value changes. 330 | */ 331 | $observe(name: string, fn: (value?: T) => any): Function; 332 | 333 | /** 334 | * A map of DOM element attribute names to the normalized name. This is needed 335 | * to do reverse lookup from normalized name back to actual name. 336 | */ 337 | $attr: Object; 338 | } 339 | 340 | /** 341 | * form.FormController - type in module ng 342 | * see https://docs.angularjs.org/api/ng/type/form.FormController 343 | */ 344 | interface IFormController { 345 | 346 | /** 347 | * Indexer which should return ng.INgModelController for most properties but cannot because of "All named properties must be assignable to string indexer type" constraint - see https://github.com/Microsoft/TypeScript/issues/272 348 | */ 349 | [name: string]: any; 350 | 351 | $pristine: boolean; 352 | $dirty: boolean; 353 | $valid: boolean; 354 | $invalid: boolean; 355 | $submitted: boolean; 356 | $error: any; 357 | $name: string; 358 | $pending: any; 359 | $addControl(control: INgModelController | IFormController): void; 360 | $removeControl(control: INgModelController | IFormController): void; 361 | $setValidity(validationErrorKey: string, isValid: boolean, control: INgModelController | IFormController): void; 362 | $setDirty(): void; 363 | $setPristine(): void; 364 | $commitViewValue(): void; 365 | $rollbackViewValue(): void; 366 | $setSubmitted(): void; 367 | $setUntouched(): void; 368 | } 369 | 370 | /////////////////////////////////////////////////////////////////////////// 371 | // NgModelController 372 | // see http://docs.angularjs.org/api/ng.directive:ngModel.NgModelController 373 | /////////////////////////////////////////////////////////////////////////// 374 | interface INgModelController { 375 | $render(): void; 376 | $setValidity(validationErrorKey: string, isValid: boolean): void; 377 | // Documentation states viewValue and modelValue to be a string but other 378 | // types do work and it's common to use them. 379 | $setViewValue(value: any, trigger?: string): void; 380 | $setPristine(): void; 381 | $setDirty(): void; 382 | $validate(): void; 383 | $setTouched(): void; 384 | $setUntouched(): void; 385 | $rollbackViewValue(): void; 386 | $commitViewValue(): void; 387 | $isEmpty(value: any): boolean; 388 | 389 | $viewValue: any; 390 | 391 | $modelValue: any; 392 | 393 | $parsers: IModelParser[]; 394 | $formatters: IModelFormatter[]; 395 | $viewChangeListeners: IModelViewChangeListener[]; 396 | $error: any; 397 | $name: string; 398 | 399 | $touched: boolean; 400 | $untouched: boolean; 401 | 402 | $validators: IModelValidators; 403 | $asyncValidators: IAsyncModelValidators; 404 | 405 | $pending: any; 406 | $pristine: boolean; 407 | $dirty: boolean; 408 | $valid: boolean; 409 | $invalid: boolean; 410 | } 411 | 412 | //Allows tuning how model updates are done. 413 | //https://docs.angularjs.org/api/ng/directive/ngModelOptions 414 | interface INgModelOptions { 415 | updateOn?: string; 416 | debounce?: any; 417 | allowInvalid?: boolean; 418 | getterSetter?: boolean; 419 | timezone?: string; 420 | } 421 | 422 | interface IModelValidators { 423 | /** 424 | * viewValue is any because it can be an object that is called in the view like $viewValue.name:$viewValue.subName 425 | */ 426 | [index: string]: (modelValue: any, viewValue: any) => boolean; 427 | } 428 | 429 | interface IAsyncModelValidators { 430 | [index: string]: (modelValue: any, viewValue: any) => IPromise; 431 | } 432 | 433 | interface IModelParser { 434 | (value: any): any; 435 | } 436 | 437 | interface IModelFormatter { 438 | (value: any): any; 439 | } 440 | 441 | interface IModelViewChangeListener { 442 | (): void; 443 | } 444 | 445 | /** 446 | * $rootScope - $rootScopeProvider - service in module ng 447 | * see https://docs.angularjs.org/api/ng/type/$rootScope.Scope and https://docs.angularjs.org/api/ng/service/$rootScope 448 | */ 449 | interface IRootScopeService { 450 | [index: string]: any; 451 | 452 | $apply(): any; 453 | $apply(exp: string): any; 454 | $apply(exp: (scope: IScope) => any): any; 455 | 456 | $applyAsync(): any; 457 | $applyAsync(exp: string): any; 458 | $applyAsync(exp: (scope: IScope) => any): any; 459 | 460 | /** 461 | * Dispatches an event name downwards to all child scopes (and their children) notifying the registered $rootScope.Scope listeners. 462 | * 463 | * The event life cycle starts at the scope on which $broadcast was called. All listeners listening for name event on this scope get notified. Afterwards, the event propagates to all direct and indirect scopes of the current scope and calls all registered listeners along the way. The event cannot be canceled. 464 | * 465 | * Any exception emitted from the listeners will be passed onto the $exceptionHandler service. 466 | * 467 | * @param name Event name to broadcast. 468 | * @param args Optional one or more arguments which will be passed onto the event listeners. 469 | */ 470 | $broadcast(name: string, ...args: any[]): IAngularEvent; 471 | $destroy(): void; 472 | $digest(): void; 473 | /** 474 | * Dispatches an event name upwards through the scope hierarchy notifying the registered $rootScope.Scope listeners. 475 | * 476 | * The event life cycle starts at the scope on which $emit was called. All listeners listening for name event on this scope get notified. Afterwards, the event traverses upwards toward the root scope and calls all registered listeners along the way. The event will stop propagating if one of the listeners cancels it. 477 | * 478 | * Any exception emitted from the listeners will be passed onto the $exceptionHandler service. 479 | * 480 | * @param name Event name to emit. 481 | * @param args Optional one or more arguments which will be passed onto the event listeners. 482 | */ 483 | $emit(name: string, ...args: any[]): IAngularEvent; 484 | 485 | $eval(): any; 486 | $eval(expression: string, locals?: Object): any; 487 | $eval(expression: (scope: IScope) => any, locals?: Object): any; 488 | 489 | $evalAsync(): void; 490 | $evalAsync(expression: string): void; 491 | $evalAsync(expression: (scope: IScope) => any): void; 492 | 493 | // Defaults to false by the implementation checking strategy 494 | $new(isolate?: boolean, parent?: IScope): IScope; 495 | 496 | /** 497 | * Listens on events of a given type. See $emit for discussion of event life cycle. 498 | * 499 | * The event listener function format is: function(event, args...). 500 | * 501 | * @param name Event name to listen on. 502 | * @param listener Function to call when the event is emitted. 503 | */ 504 | $on(name: string, listener: (event: IAngularEvent, ...args: any[]) => any): () => void; 505 | 506 | $watch(watchExpression: string, listener?: string, objectEquality?: boolean): () => void; 507 | $watch(watchExpression: string, listener?: (newValue: T, oldValue: T, scope: IScope) => any, objectEquality?: boolean): () => void; 508 | $watch(watchExpression: (scope: IScope) => any, listener?: string, objectEquality?: boolean): () => void; 509 | $watch(watchExpression: (scope: IScope) => T, listener?: (newValue: T, oldValue: T, scope: IScope) => any, objectEquality?: boolean): () => void; 510 | 511 | $watchCollection(watchExpression: string, listener: (newValue: T, oldValue: T, scope: IScope) => any): () => void; 512 | $watchCollection(watchExpression: (scope: IScope) => T, listener: (newValue: T, oldValue: T, scope: IScope) => any): () => void; 513 | 514 | $watchGroup(watchExpressions: any[], listener: (newValue: any, oldValue: any, scope: IScope) => any): () => void; 515 | $watchGroup(watchExpressions: { (scope: IScope): any }[], listener: (newValue: any, oldValue: any, scope: IScope) => any): () => void; 516 | 517 | $parent: IScope; 518 | $root: IRootScopeService; 519 | $id: number; 520 | 521 | // Hidden members 522 | $$isolateBindings: any; 523 | $$phase: any; 524 | } 525 | 526 | interface IScope extends IRootScopeService { } 527 | 528 | /** 529 | * $scope for ngRepeat directive. 530 | * see https://docs.angularjs.org/api/ng/directive/ngRepeat 531 | */ 532 | interface IRepeatScope extends IScope { 533 | 534 | /** 535 | * iterator offset of the repeated element (0..length-1). 536 | */ 537 | $index: number; 538 | 539 | /** 540 | * true if the repeated element is first in the iterator. 541 | */ 542 | $first: boolean; 543 | 544 | /** 545 | * true if the repeated element is between the first and last in the iterator. 546 | */ 547 | $middle: boolean; 548 | 549 | /** 550 | * true if the repeated element is last in the iterator. 551 | */ 552 | $last: boolean; 553 | 554 | /** 555 | * true if the iterator position $index is even (otherwise false). 556 | */ 557 | $even: boolean; 558 | 559 | /** 560 | * true if the iterator position $index is odd (otherwise false). 561 | */ 562 | $odd: boolean; 563 | 564 | } 565 | 566 | interface IAngularEvent { 567 | /** 568 | * the scope on which the event was $emit-ed or $broadcast-ed. 569 | */ 570 | targetScope: IScope; 571 | /** 572 | * the scope that is currently handling the event. Once the event propagates through the scope hierarchy, this property is set to null. 573 | */ 574 | currentScope: IScope; 575 | /** 576 | * name of the event. 577 | */ 578 | name: string; 579 | /** 580 | * calling stopPropagation function will cancel further event propagation (available only for events that were $emit-ed). 581 | */ 582 | stopPropagation?(): void; 583 | /** 584 | * calling preventDefault sets defaultPrevented flag to true. 585 | */ 586 | preventDefault(): void; 587 | /** 588 | * true if preventDefault was called. 589 | */ 590 | defaultPrevented: boolean; 591 | } 592 | 593 | /////////////////////////////////////////////////////////////////////////// 594 | // WindowService 595 | // see http://docs.angularjs.org/api/ng.$window 596 | /////////////////////////////////////////////////////////////////////////// 597 | interface IWindowService extends Window { 598 | [key: string]: any; 599 | } 600 | 601 | /////////////////////////////////////////////////////////////////////////// 602 | // TimeoutService 603 | // see http://docs.angularjs.org/api/ng.$timeout 604 | /////////////////////////////////////////////////////////////////////////// 605 | interface ITimeoutService { 606 | (delay?: number, invokeApply?: boolean): IPromise; 607 | (fn: (...args: any[]) => T, delay?: number, invokeApply?: boolean, ...args: any[]): IPromise; 608 | cancel(promise?: IPromise): boolean; 609 | } 610 | 611 | /////////////////////////////////////////////////////////////////////////// 612 | // IntervalService 613 | // see http://docs.angularjs.org/api/ng.$interval 614 | /////////////////////////////////////////////////////////////////////////// 615 | interface IIntervalService { 616 | (func: Function, delay: number, count?: number, invokeApply?: boolean, ...args: any[]): IPromise; 617 | cancel(promise: IPromise): boolean; 618 | } 619 | 620 | /** 621 | * $filter - $filterProvider - service in module ng 622 | * 623 | * Filters are used for formatting data displayed to the user. 624 | * 625 | * see https://docs.angularjs.org/api/ng/service/$filter 626 | */ 627 | interface IFilterService { 628 | (name: 'filter'): IFilterFilter; 629 | (name: 'currency'): IFilterCurrency; 630 | (name: 'number'): IFilterNumber; 631 | (name: 'date'): IFilterDate; 632 | (name: 'json'): IFilterJson; 633 | (name: 'lowercase'): IFilterLowercase; 634 | (name: 'uppercase'): IFilterUppercase; 635 | (name: 'limitTo'): IFilterLimitTo; 636 | (name: 'orderBy'): IFilterOrderBy; 637 | /** 638 | * Usage: 639 | * $filter(name); 640 | * 641 | * @param name Name of the filter function to retrieve 642 | */ 643 | (name: string): T; 644 | } 645 | 646 | interface IFilterFilter { 647 | (array: T[], expression: string | IFilterFilterPatternObject | IFilterFilterPredicateFunc, comparator?: IFilterFilterComparatorFunc|boolean): T[]; 648 | } 649 | 650 | interface IFilterFilterPatternObject { 651 | [name: string]: any; 652 | } 653 | 654 | interface IFilterFilterPredicateFunc { 655 | (value: T, index: number, array: T[]): boolean; 656 | } 657 | 658 | interface IFilterFilterComparatorFunc { 659 | (actual: T, expected: T): boolean; 660 | } 661 | 662 | interface IFilterCurrency { 663 | /** 664 | * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default symbol for current locale is used. 665 | * @param amount Input to filter. 666 | * @param symbol Currency symbol or identifier to be displayed. 667 | * @param fractionSize Number of decimal places to round the amount to, defaults to default max fraction size for current locale 668 | * @return Formatted number 669 | */ 670 | (amount: number, symbol?: string, fractionSize?: number): string; 671 | } 672 | 673 | interface IFilterNumber { 674 | /** 675 | * Formats a number as text. 676 | * @param number Number to format. 677 | * @param fractionSize Number of decimal places to round the number to. If this is not provided then the fraction size is computed from the current locale's number formatting pattern. In the case of the default locale, it will be 3. 678 | * @return Number rounded to decimalPlaces and places a “,” after each third digit. 679 | */ 680 | (value: number|string, fractionSize?: number|string): string; 681 | } 682 | 683 | interface IFilterDate { 684 | /** 685 | * Formats date to a string based on the requested format. 686 | * 687 | * @param date Date to format either as Date object, milliseconds (string or number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.sssZ and its shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is specified in the string input, the time is considered to be in the local timezone. 688 | * @param format Formatting rules (see Description). If not specified, mediumDate is used. 689 | * @param timezone Timezone to be used for formatting. It understands UTC/GMT and the continental US time zone abbreviations, but for general use, use a time zone offset, for example, '+0430' (4 hours, 30 minutes east of the Greenwich meridian) If not specified, the timezone of the browser will be used. 690 | * @return Formatted string or the input if input is not recognized as date/millis. 691 | */ 692 | (date: Date | number | string, format?: string, timezone?: string): string; 693 | } 694 | 695 | interface IFilterJson { 696 | /** 697 | * Allows you to convert a JavaScript object into JSON string. 698 | * @param object Any JavaScript object (including arrays and primitive types) to filter. 699 | * @param spacing The number of spaces to use per indentation, defaults to 2. 700 | * @return JSON string. 701 | */ 702 | (object: any, spacing?: number): string; 703 | } 704 | 705 | interface IFilterLowercase { 706 | /** 707 | * Converts string to lowercase. 708 | */ 709 | (value: string): string; 710 | } 711 | 712 | interface IFilterUppercase { 713 | /** 714 | * Converts string to uppercase. 715 | */ 716 | (value: string): string; 717 | } 718 | 719 | interface IFilterLimitTo { 720 | /** 721 | * Creates a new array containing only a specified number of elements. The elements are taken from either the beginning or the end of the source array, string or number, as specified by the value and sign (positive or negative) of limit. 722 | * @param input Source array to be limited. 723 | * @param limit The length of the returned array. If the limit number is positive, limit number of items from the beginning of the source array/string are copied. If the number is negative, limit number of items from the end of the source array are copied. The limit will be trimmed if it exceeds array.length. If limit is undefined, the input will be returned unchanged. 724 | * @param begin Index at which to begin limitation. As a negative index, begin indicates an offset from the end of input. Defaults to 0. 725 | * @return A new sub-array of length limit or less if input array had less than limit elements. 726 | */ 727 | (input: T[], limit: string|number, begin?: string|number): T[]; 728 | /** 729 | * Creates a new string containing only a specified number of elements. The elements are taken from either the beginning or the end of the source string or number, as specified by the value and sign (positive or negative) of limit. If a number is used as input, it is converted to a string. 730 | * @param input Source string or number to be limited. 731 | * @param limit The length of the returned string. If the limit number is positive, limit number of items from the beginning of the source string are copied. If the number is negative, limit number of items from the end of the source string are copied. The limit will be trimmed if it exceeds input.length. If limit is undefined, the input will be returned unchanged. 732 | * @param begin Index at which to begin limitation. As a negative index, begin indicates an offset from the end of input. Defaults to 0. 733 | * @return A new substring of length limit or less if input had less than limit elements. 734 | */ 735 | (input: string|number, limit: string|number, begin?: string|number): string; 736 | } 737 | 738 | interface IFilterOrderBy { 739 | /** 740 | * Orders a specified array by the expression predicate. It is ordered alphabetically for strings and numerically for numbers. Note: if you notice numbers are not being sorted as expected, make sure they are actually being saved as numbers and not strings. 741 | * @param array The array to sort. 742 | * @param expression A predicate to be used by the comparator to determine the order of elements. 743 | * @param reverse Reverse the order of the array. 744 | * @return Reverse the order of the array. 745 | */ 746 | (array: T[], expression: string|((value: T) => any)|(((value: T) => any)|string)[], reverse?: boolean): T[]; 747 | } 748 | 749 | /** 750 | * $filterProvider - $filter - provider in module ng 751 | * 752 | * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To achieve this a filter definition consists of a factory function which is annotated with dependencies and is responsible for creating a filter function. 753 | * 754 | * see https://docs.angularjs.org/api/ng/provider/$filterProvider 755 | */ 756 | interface IFilterProvider extends IServiceProvider { 757 | /** 758 | * register(name); 759 | * 760 | * @param name Name of the filter function, or an object map of filters where the keys are the filter names and the values are the filter factories. Note: Filter names must be valid angular Expressions identifiers, such as uppercase or orderBy. Names with special characters, such as hyphens and dots, are not allowed. If you wish to namespace your filters, then you can use capitalization (myappSubsectionFilterx) or underscores (myapp_subsection_filterx). 761 | */ 762 | register(name: string | {}): IServiceProvider; 763 | } 764 | 765 | /////////////////////////////////////////////////////////////////////////// 766 | // LocaleService 767 | // see http://docs.angularjs.org/api/ng.$locale 768 | /////////////////////////////////////////////////////////////////////////// 769 | interface ILocaleService { 770 | id: string; 771 | 772 | // These are not documented 773 | // Check angular's i18n files for exemples 774 | NUMBER_FORMATS: ILocaleNumberFormatDescriptor; 775 | DATETIME_FORMATS: ILocaleDateTimeFormatDescriptor; 776 | pluralCat: (num: any) => string; 777 | } 778 | 779 | interface ILocaleNumberFormatDescriptor { 780 | DECIMAL_SEP: string; 781 | GROUP_SEP: string; 782 | PATTERNS: ILocaleNumberPatternDescriptor[]; 783 | CURRENCY_SYM: string; 784 | } 785 | 786 | interface ILocaleNumberPatternDescriptor { 787 | minInt: number; 788 | minFrac: number; 789 | maxFrac: number; 790 | posPre: string; 791 | posSuf: string; 792 | negPre: string; 793 | negSuf: string; 794 | gSize: number; 795 | lgSize: number; 796 | } 797 | 798 | interface ILocaleDateTimeFormatDescriptor { 799 | MONTH: string[]; 800 | SHORTMONTH: string[]; 801 | DAY: string[]; 802 | SHORTDAY: string[]; 803 | AMPMS: string[]; 804 | medium: string; 805 | short: string; 806 | fullDate: string; 807 | longDate: string; 808 | mediumDate: string; 809 | shortDate: string; 810 | mediumTime: string; 811 | shortTime: string; 812 | } 813 | 814 | /////////////////////////////////////////////////////////////////////////// 815 | // LogService 816 | // see http://docs.angularjs.org/api/ng.$log 817 | // see http://docs.angularjs.org/api/ng.$logProvider 818 | /////////////////////////////////////////////////////////////////////////// 819 | interface ILogService { 820 | debug: ILogCall; 821 | error: ILogCall; 822 | info: ILogCall; 823 | log: ILogCall; 824 | warn: ILogCall; 825 | } 826 | 827 | interface ILogProvider extends IServiceProvider { 828 | debugEnabled(): boolean; 829 | debugEnabled(enabled: boolean): ILogProvider; 830 | } 831 | 832 | // We define this as separate interface so we can reopen it later for 833 | // the ngMock module. 834 | interface ILogCall { 835 | (...args: any[]): void; 836 | } 837 | 838 | /////////////////////////////////////////////////////////////////////////// 839 | // ParseService 840 | // see http://docs.angularjs.org/api/ng.$parse 841 | // see http://docs.angularjs.org/api/ng.$parseProvider 842 | /////////////////////////////////////////////////////////////////////////// 843 | interface IParseService { 844 | (expression: string, interceptorFn?: (value: any, scope: IScope, locals: any) => any, expensiveChecks?: boolean): ICompiledExpression; 845 | } 846 | 847 | interface IParseProvider { 848 | logPromiseWarnings(): boolean; 849 | logPromiseWarnings(value: boolean): IParseProvider; 850 | 851 | unwrapPromises(): boolean; 852 | unwrapPromises(value: boolean): IParseProvider; 853 | 854 | /** 855 | * Configure $parse service to add literal values that will be present as literal at expressions. 856 | * 857 | * @param literalName Token for the literal value. The literal name value must be a valid literal name. 858 | * @param literalValue Value for this literal. All literal values must be primitives or `undefined`. 859 | **/ 860 | addLiteral(literalName: string, literalValue: any): void; 861 | 862 | /** 863 | * Allows defining the set of characters that are allowed in Angular expressions. The function identifierStart will get called to know if a given character is a valid character to be the first character for an identifier. The function identifierContinue will get called to know if a given character is a valid character to be a follow-up identifier character. The functions identifierStart and identifierContinue will receive as arguments the single character to be identifier and the character code point. These arguments will be string and numeric. Keep in mind that the string parameter can be two characters long depending on the character representation. It is expected for the function to return true or false, whether that character is allowed or not. 864 | * Since this function will be called extensivelly, keep the implementation of these functions fast, as the performance of these functions have a direct impact on the expressions parsing speed. 865 | * 866 | * @param identifierStart The function that will decide whether the given character is a valid identifier start character. 867 | * @param identifierContinue The function that will decide whether the given character is a valid identifier continue character. 868 | **/ 869 | setIdentifierFns(identifierStart?: (character: string, codePoint: number) => boolean, 870 | identifierContinue?: (character: string, codePoint: number) => boolean): void; 871 | } 872 | 873 | interface ICompiledExpression { 874 | (context: any, locals?: any): any; 875 | 876 | literal: boolean; 877 | constant: boolean; 878 | 879 | // If value is not provided, undefined is gonna be used since the implementation 880 | // does not check the parameter. Let's force a value for consistency. If consumer 881 | // whants to undefine it, pass the undefined value explicitly. 882 | assign(context: any, value: any): any; 883 | } 884 | 885 | /** 886 | * $location - $locationProvider - service in module ng 887 | * see https://docs.angularjs.org/api/ng/service/$location 888 | */ 889 | interface ILocationService { 890 | absUrl(): string; 891 | hash(): string; 892 | hash(newHash: string): ILocationService; 893 | host(): string; 894 | 895 | /** 896 | * Return path of current url 897 | */ 898 | path(): string; 899 | 900 | /** 901 | * Change path when called with parameter and return $location. 902 | * Note: Path should always begin with forward slash (/), this method will add the forward slash if it is missing. 903 | * 904 | * @param path New path 905 | */ 906 | path(path: string): ILocationService; 907 | 908 | port(): number; 909 | protocol(): string; 910 | replace(): ILocationService; 911 | 912 | /** 913 | * Return search part (as object) of current url 914 | */ 915 | search(): any; 916 | 917 | /** 918 | * Change search part when called with parameter and return $location. 919 | * 920 | * @param search When called with a single argument the method acts as a setter, setting the search component of $location to the specified value. 921 | * 922 | * If the argument is a hash object containing an array of values, these values will be encoded as duplicate search parameters in the url. 923 | */ 924 | search(search: any): ILocationService; 925 | 926 | /** 927 | * Change search part when called with parameter and return $location. 928 | * 929 | * @param search New search params 930 | * @param paramValue If search is a string or a Number, then paramValue will override only a single search property. If paramValue is null, the property specified via the first argument will be deleted. If paramValue is an array, it will override the property of the search component of $location specified via the first argument. If paramValue is true, the property specified via the first argument will be added with no value nor trailing equal sign. 931 | */ 932 | search(search: string, paramValue: string|number|string[]|boolean): ILocationService; 933 | 934 | state(): any; 935 | state(state: any): ILocationService; 936 | url(): string; 937 | url(url: string): ILocationService; 938 | } 939 | 940 | interface ILocationProvider extends IServiceProvider { 941 | hashPrefix(): string; 942 | hashPrefix(prefix: string): ILocationProvider; 943 | html5Mode(): boolean; 944 | 945 | // Documentation states that parameter is string, but 946 | // implementation tests it as boolean, which makes more sense 947 | // since this is a toggler 948 | html5Mode(active: boolean): ILocationProvider; 949 | html5Mode(mode: { enabled?: boolean; requireBase?: boolean; rewriteLinks?: boolean; }): ILocationProvider; 950 | } 951 | 952 | /////////////////////////////////////////////////////////////////////////// 953 | // DocumentService 954 | // see http://docs.angularjs.org/api/ng.$document 955 | /////////////////////////////////////////////////////////////////////////// 956 | interface IDocumentService extends JQuery { 957 | // Must return intersection type for index signature compatibility with JQuery 958 | [index: number]: HTMLElement & Document; 959 | } 960 | 961 | /////////////////////////////////////////////////////////////////////////// 962 | // ExceptionHandlerService 963 | // see http://docs.angularjs.org/api/ng.$exceptionHandler 964 | /////////////////////////////////////////////////////////////////////////// 965 | interface IExceptionHandlerService { 966 | (exception: Error, cause?: string): void; 967 | } 968 | 969 | /////////////////////////////////////////////////////////////////////////// 970 | // RootElementService 971 | // see http://docs.angularjs.org/api/ng.$rootElement 972 | /////////////////////////////////////////////////////////////////////////// 973 | interface IRootElementService extends JQuery {} 974 | 975 | interface IQResolveReject { 976 | (): void; 977 | (value: T): void; 978 | } 979 | /** 980 | * $q - service in module ng 981 | * A promise/deferred implementation inspired by Kris Kowal's Q. 982 | * See http://docs.angularjs.org/api/ng/service/$q 983 | */ 984 | interface IQService { 985 | new (resolver: (resolve: IQResolveReject) => any): IPromise; 986 | new (resolver: (resolve: IQResolveReject, reject: IQResolveReject) => any): IPromise; 987 | (resolver: (resolve: IQResolveReject) => any): IPromise; 988 | (resolver: (resolve: IQResolveReject, reject: IQResolveReject) => any): IPromise; 989 | 990 | /** 991 | * Combines multiple promises into a single promise that is resolved when all of the input promises are resolved. 992 | * 993 | * Returns a single promise that will be resolved with an array of values, each value corresponding to the promise at the same index in the promises array. If any of the promises is resolved with a rejection, this resulting promise will be rejected with the same rejection value. 994 | * 995 | * @param promises An array of promises. 996 | */ 997 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise , T5 | IPromise, T6 | IPromise, T7 | IPromise, T8 | IPromise, T9 | IPromise, T10 | IPromise]): IPromise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>; 998 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise , T5 | IPromise, T6 | IPromise, T7 | IPromise, T8 | IPromise, T9 | IPromise]): IPromise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>; 999 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise , T5 | IPromise, T6 | IPromise, T7 | IPromise, T8 | IPromise]): IPromise<[T1, T2, T3, T4, T5, T6, T7, T8]>; 1000 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise , T5 | IPromise, T6 | IPromise, T7 | IPromise]): IPromise<[T1, T2, T3, T4, T5, T6, T7]>; 1001 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise , T5 | IPromise, T6 | IPromise]): IPromise<[T1, T2, T3, T4, T5, T6]>; 1002 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise , T5 | IPromise]): IPromise<[T1, T2, T3, T4, T5]>; 1003 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise, T4 | IPromise ]): IPromise<[T1, T2, T3, T4]>; 1004 | all(values: [T1 | IPromise, T2 | IPromise, T3 | IPromise]): IPromise<[T1, T2, T3]>; 1005 | all(values: [T1 | IPromise, T2 | IPromise]): IPromise<[T1, T2]>; 1006 | all(promises: IPromise[]): IPromise; 1007 | /** 1008 | * Combines multiple promises into a single promise that is resolved when all of the input promises are resolved. 1009 | * 1010 | * Returns a single promise that will be resolved with a hash of values, each value corresponding to the promise at the same key in the promises hash. If any of the promises is resolved with a rejection, this resulting promise will be rejected with the same rejection value. 1011 | * 1012 | * @param promises A hash of promises. 1013 | */ 1014 | all(promises: { [id: string]: IPromise; }): IPromise<{ [id: string]: any; }>; 1015 | all(promises: { [id: string]: IPromise; }): IPromise; 1016 | /** 1017 | * Creates a Deferred object which represents a task which will finish in the future. 1018 | */ 1019 | defer(): IDeferred; 1020 | /** 1021 | * Creates a promise that is resolved as rejected with the specified reason. This api should be used to forward rejection in a chain of promises. If you are dealing with the last promise in a promise chain, you don't need to worry about it. 1022 | * 1023 | * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of reject as the throw keyword in JavaScript. This also means that if you "catch" an error via a promise error callback and you want to forward the error to the promise derived from the current promise, you have to "rethrow" the error by returning a rejection constructed via reject. 1024 | * 1025 | * @param reason Constant, message, exception or an object representing the rejection reason. 1026 | */ 1027 | reject(reason?: any): IPromise; 1028 | /** 1029 | * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted. 1030 | * 1031 | * @param value Value or a promise 1032 | */ 1033 | resolve(value: IPromise|T): IPromise; 1034 | /** 1035 | * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted. 1036 | */ 1037 | resolve(): IPromise; 1038 | /** 1039 | * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted. 1040 | * 1041 | * @param value Value or a promise 1042 | */ 1043 | when(value: IPromise|T): IPromise; 1044 | when(value: IPromise|T, successCallback: (promiseValue: T) => IPromise|TResult, errorCallback?: (reason: any) => any, notifyCallback?: (state: any) => any): IPromise; 1045 | /** 1046 | * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted. 1047 | */ 1048 | when(): IPromise; 1049 | } 1050 | 1051 | interface IPromise { 1052 | /** 1053 | * Regardless of when the promise was or will be resolved or rejected, then calls one of the success or error callbacks asynchronously as soon as the result is available. The callbacks are called with a single argument: the result or rejection reason. Additionally, the notify callback may be called zero or more times to provide a progress indication, before the promise is resolved or rejected. 1054 | * The successCallBack may return IPromise for when a $q.reject() needs to be returned 1055 | * This method returns a new promise which is resolved or rejected via the return value of the successCallback, errorCallback. It also notifies via the return value of the notifyCallback method. The promise can not be resolved or rejected from the notifyCallback method. 1056 | */ 1057 | then(successCallback: (promiseValue: T) => IPromise|TResult, errorCallback?: (reason: any) => any, notifyCallback?: (state: any) => any): IPromise; 1058 | 1059 | /** 1060 | * Shorthand for promise.then(null, errorCallback) 1061 | */ 1062 | catch(onRejected: (reason: any) => IPromise|TResult): IPromise; 1063 | 1064 | /** 1065 | * Allows you to observe either the fulfillment or rejection of a promise, but to do so without modifying the final value. This is useful to release resources or do some clean-up that needs to be done whether the promise was rejected or resolved. See the full specification for more information. 1066 | * 1067 | * Because finally is a reserved word in JavaScript and reserved keywords are not supported as property names by ES3, you'll need to invoke the method like promise['finally'](callback) to make your code IE8 and Android 2.x compatible. 1068 | */ 1069 | finally(finallyCallback: () => any): IPromise; 1070 | } 1071 | 1072 | interface IDeferred { 1073 | resolve(value?: T|IPromise): void; 1074 | reject(reason?: any): void; 1075 | notify(state?: any): void; 1076 | promise: IPromise; 1077 | } 1078 | 1079 | /////////////////////////////////////////////////////////////////////////// 1080 | // AnchorScrollService 1081 | // see http://docs.angularjs.org/api/ng.$anchorScroll 1082 | /////////////////////////////////////////////////////////////////////////// 1083 | interface IAnchorScrollService { 1084 | (): void; 1085 | (hash: string): void; 1086 | yOffset: any; 1087 | } 1088 | 1089 | interface IAnchorScrollProvider extends IServiceProvider { 1090 | disableAutoScrolling(): void; 1091 | } 1092 | 1093 | /** 1094 | * $cacheFactory - service in module ng 1095 | * 1096 | * Factory that constructs Cache objects and gives access to them. 1097 | * 1098 | * see https://docs.angularjs.org/api/ng/service/$cacheFactory 1099 | */ 1100 | interface ICacheFactoryService { 1101 | /** 1102 | * Factory that constructs Cache objects and gives access to them. 1103 | * 1104 | * @param cacheId Name or id of the newly created cache. 1105 | * @param optionsMap Options object that specifies the cache behavior. Properties: 1106 | * 1107 | * capacity — turns the cache into LRU cache. 1108 | */ 1109 | (cacheId: string, optionsMap?: { capacity?: number; }): ICacheObject; 1110 | 1111 | /** 1112 | * Get information about all the caches that have been created. 1113 | * @returns key-value map of cacheId to the result of calling cache#info 1114 | */ 1115 | info(): any; 1116 | 1117 | /** 1118 | * Get access to a cache object by the cacheId used when it was created. 1119 | * 1120 | * @param cacheId Name or id of a cache to access. 1121 | */ 1122 | get(cacheId: string): ICacheObject; 1123 | } 1124 | 1125 | /** 1126 | * $cacheFactory.Cache - type in module ng 1127 | * 1128 | * A cache object used to store and retrieve data, primarily used by $http and the script directive to cache templates and other data. 1129 | * 1130 | * see https://docs.angularjs.org/api/ng/type/$cacheFactory.Cache 1131 | */ 1132 | interface ICacheObject { 1133 | /** 1134 | * Retrieve information regarding a particular Cache. 1135 | */ 1136 | info(): { 1137 | /** 1138 | * the id of the cache instance 1139 | */ 1140 | id: string; 1141 | 1142 | /** 1143 | * the number of entries kept in the cache instance 1144 | */ 1145 | size: number; 1146 | 1147 | //...: any additional properties from the options object when creating the cache. 1148 | }; 1149 | 1150 | /** 1151 | * Inserts a named entry into the Cache object to be retrieved later, and incrementing the size of the cache if the key was not already present in the cache. If behaving like an LRU cache, it will also remove stale entries from the set. 1152 | * 1153 | * It will not insert undefined values into the cache. 1154 | * 1155 | * @param key the key under which the cached data is stored. 1156 | * @param value the value to store alongside the key. If it is undefined, the key will not be stored. 1157 | */ 1158 | put(key: string, value?: T): T; 1159 | 1160 | /** 1161 | * Retrieves named data stored in the Cache object. 1162 | * 1163 | * @param key the key of the data to be retrieved 1164 | */ 1165 | get(key: string): T; 1166 | 1167 | /** 1168 | * Removes an entry from the Cache object. 1169 | * 1170 | * @param key the key of the entry to be removed 1171 | */ 1172 | remove(key: string): void; 1173 | 1174 | /** 1175 | * Clears the cache object of any entries. 1176 | */ 1177 | removeAll(): void; 1178 | 1179 | /** 1180 | * Destroys the Cache object entirely, removing it from the $cacheFactory set. 1181 | */ 1182 | destroy(): void; 1183 | } 1184 | 1185 | /////////////////////////////////////////////////////////////////////////// 1186 | // CompileService 1187 | // see http://docs.angularjs.org/api/ng.$compile 1188 | // see http://docs.angularjs.org/api/ng.$compileProvider 1189 | /////////////////////////////////////////////////////////////////////////// 1190 | interface ICompileService { 1191 | (element: string | Element | JQuery, transclude?: ITranscludeFunction, maxPriority?: number): ITemplateLinkingFunction; 1192 | } 1193 | 1194 | interface ICompileProvider extends IServiceProvider { 1195 | directive(name: string, directiveFactory: Injectable): ICompileProvider; 1196 | directive(object: {[directiveName: string]: Injectable}): ICompileProvider; 1197 | 1198 | component(name: string, options: IComponentOptions): ICompileProvider; 1199 | 1200 | aHrefSanitizationWhitelist(): RegExp; 1201 | aHrefSanitizationWhitelist(regexp: RegExp): ICompileProvider; 1202 | 1203 | imgSrcSanitizationWhitelist(): RegExp; 1204 | imgSrcSanitizationWhitelist(regexp: RegExp): ICompileProvider; 1205 | 1206 | debugInfoEnabled(): boolean; 1207 | debugInfoEnabled(enabled: boolean): ICompileProvider; 1208 | } 1209 | 1210 | interface ICloneAttachFunction { 1211 | // Let's hint but not force cloneAttachFn's signature 1212 | (clonedElement?: JQuery, scope?: IScope): any; 1213 | } 1214 | 1215 | // This corresponds to the "publicLinkFn" returned by $compile. 1216 | interface ITemplateLinkingFunction { 1217 | (scope: IScope, cloneAttachFn?: ICloneAttachFunction): JQuery; 1218 | } 1219 | 1220 | /** 1221 | * This corresponds to $transclude passed to controllers and to the transclude function passed to link functions. 1222 | * https://docs.angularjs.org/api/ng/service/$compile#-controller- 1223 | * http://teropa.info/blog/2015/06/09/transclusion.html 1224 | */ 1225 | interface ITranscludeFunction { 1226 | // If the scope is provided, then the cloneAttachFn must be as well. 1227 | (scope: IScope, cloneAttachFn: ICloneAttachFunction, futureParentElement?: JQuery, slotName?: string): JQuery; 1228 | // If one argument is provided, then it's assumed to be the cloneAttachFn. 1229 | (cloneAttachFn?: ICloneAttachFunction, futureParentElement?: JQuery, slotName?: string): JQuery; 1230 | } 1231 | 1232 | /////////////////////////////////////////////////////////////////////////// 1233 | // ControllerService 1234 | // see http://docs.angularjs.org/api/ng.$controller 1235 | // see http://docs.angularjs.org/api/ng.$controllerProvider 1236 | /////////////////////////////////////////////////////////////////////////// 1237 | interface IControllerService { 1238 | // Although the documentation doesn't state this, locals are optional 1239 | (controllerConstructor: new (...args: any[]) => T, locals?: any, later?: boolean, ident?: string): T; 1240 | (controllerConstructor: Function, locals?: any, later?: boolean, ident?: string): T; 1241 | (controllerName: string, locals?: any, later?: boolean, ident?: string): T; 1242 | } 1243 | 1244 | interface IControllerProvider extends IServiceProvider { 1245 | register(name: string, controllerConstructor: Function): void; 1246 | register(name: string, dependencyAnnotatedConstructor: any[]): void; 1247 | allowGlobals(): void; 1248 | } 1249 | 1250 | /** 1251 | * xhrFactory 1252 | * Replace or decorate this service to create your own custom XMLHttpRequest objects. 1253 | * see https://docs.angularjs.org/api/ng/service/$xhrFactory 1254 | */ 1255 | interface IXhrFactory { 1256 | (method: string, url: string): T; 1257 | } 1258 | 1259 | /** 1260 | * HttpService 1261 | * see http://docs.angularjs.org/api/ng/service/$http 1262 | */ 1263 | interface IHttpService { 1264 | /** 1265 | * Object describing the request to be made and how it should be processed. 1266 | */ 1267 | (config: IRequestConfig): IHttpPromise; 1268 | 1269 | /** 1270 | * Shortcut method to perform GET request. 1271 | * 1272 | * @param url Relative or absolute URL specifying the destination of the request 1273 | * @param config Optional configuration object 1274 | */ 1275 | get(url: string, config?: IRequestShortcutConfig): IHttpPromise; 1276 | 1277 | /** 1278 | * Shortcut method to perform DELETE request. 1279 | * 1280 | * @param url Relative or absolute URL specifying the destination of the request 1281 | * @param config Optional configuration object 1282 | */ 1283 | delete(url: string, config?: IRequestShortcutConfig): IHttpPromise; 1284 | 1285 | /** 1286 | * Shortcut method to perform HEAD request. 1287 | * 1288 | * @param url Relative or absolute URL specifying the destination of the request 1289 | * @param config Optional configuration object 1290 | */ 1291 | head(url: string, config?: IRequestShortcutConfig): IHttpPromise; 1292 | 1293 | /** 1294 | * Shortcut method to perform JSONP request. 1295 | * 1296 | * @param url Relative or absolute URL specifying the destination of the request 1297 | * @param config Optional configuration object 1298 | */ 1299 | jsonp(url: string, config?: IRequestShortcutConfig): IHttpPromise; 1300 | 1301 | /** 1302 | * Shortcut method to perform POST request. 1303 | * 1304 | * @param url Relative or absolute URL specifying the destination of the request 1305 | * @param data Request content 1306 | * @param config Optional configuration object 1307 | */ 1308 | post(url: string, data: any, config?: IRequestShortcutConfig): IHttpPromise; 1309 | 1310 | /** 1311 | * Shortcut method to perform PUT request. 1312 | * 1313 | * @param url Relative or absolute URL specifying the destination of the request 1314 | * @param data Request content 1315 | * @param config Optional configuration object 1316 | */ 1317 | put(url: string, data: any, config?: IRequestShortcutConfig): IHttpPromise; 1318 | 1319 | /** 1320 | * Shortcut method to perform PATCH request. 1321 | * 1322 | * @param url Relative or absolute URL specifying the destination of the request 1323 | * @param data Request content 1324 | * @param config Optional configuration object 1325 | */ 1326 | patch(url: string, data: any, config?: IRequestShortcutConfig): IHttpPromise; 1327 | 1328 | /** 1329 | * Runtime equivalent of the $httpProvider.defaults property. Allows configuration of default headers, withCredentials as well as request and response transformations. 1330 | */ 1331 | defaults: IHttpProviderDefaults; 1332 | 1333 | /** 1334 | * Array of config objects for currently pending requests. This is primarily meant to be used for debugging purposes. 1335 | */ 1336 | pendingRequests: IRequestConfig[]; 1337 | } 1338 | 1339 | /** 1340 | * Object describing the request to be made and how it should be processed. 1341 | * see http://docs.angularjs.org/api/ng/service/$http#usage 1342 | */ 1343 | interface IRequestShortcutConfig extends IHttpProviderDefaults { 1344 | /** 1345 | * {Object.} 1346 | * Map of strings or objects which will be turned to ?key1=value1&key2=value2 after the url. If the value is not a string, it will be JSONified. 1347 | */ 1348 | params?: any; 1349 | 1350 | /** 1351 | * {string|Object} 1352 | * Data to be sent as the request message data. 1353 | */ 1354 | data?: any; 1355 | 1356 | /** 1357 | * Timeout in milliseconds, or promise that should abort the request when resolved. 1358 | */ 1359 | timeout?: number|IPromise; 1360 | 1361 | /** 1362 | * See [XMLHttpRequest.responseType]https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#xmlhttprequest-responsetype 1363 | */ 1364 | responseType?: string; 1365 | } 1366 | 1367 | /** 1368 | * Object describing the request to be made and how it should be processed. 1369 | * see http://docs.angularjs.org/api/ng/service/$http#usage 1370 | */ 1371 | interface IRequestConfig extends IRequestShortcutConfig { 1372 | /** 1373 | * HTTP method (e.g. 'GET', 'POST', etc) 1374 | */ 1375 | method: string; 1376 | /** 1377 | * Absolute or relative URL of the resource that is being requested. 1378 | */ 1379 | url: string; 1380 | /** 1381 | * Event listeners to be bound to the XMLHttpRequest object. 1382 | * To bind events to the XMLHttpRequest upload object, use uploadEventHandlers. The handler will be called in the context of a $apply block. 1383 | */ 1384 | eventHandlers?: { [type: string]: EventListenerOrEventListenerObject }; 1385 | /** 1386 | * Event listeners to be bound to the XMLHttpRequest upload object. 1387 | * To bind events to the XMLHttpRequest object, use eventHandlers. The handler will be called in the context of a $apply block. 1388 | */ 1389 | uploadEventHandlers?: { [type: string]: EventListenerOrEventListenerObject }; 1390 | } 1391 | 1392 | interface IHttpHeadersGetter { 1393 | (): { [name: string]: string; }; 1394 | (headerName: string): string; 1395 | } 1396 | 1397 | interface IHttpPromiseCallback { 1398 | (data: T, status: number, headers: IHttpHeadersGetter, config: IRequestConfig): void; 1399 | } 1400 | 1401 | interface IHttpPromiseCallbackArg { 1402 | data?: T; 1403 | status?: number; 1404 | headers?: IHttpHeadersGetter; 1405 | config?: IRequestConfig; 1406 | statusText?: string; 1407 | } 1408 | 1409 | interface IHttpPromise extends IPromise> { 1410 | /** 1411 | * The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. 1412 | * If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error. 1413 | * @deprecated 1414 | */ 1415 | success?(callback: IHttpPromiseCallback): IHttpPromise; 1416 | /** 1417 | * The $http legacy promise methods success and error have been deprecated. Use the standard then method instead. 1418 | * If $httpProvider.useLegacyPromiseExtensions is set to false then these methods will throw $http/legacy error. 1419 | * @deprecated 1420 | */ 1421 | error?(callback: IHttpPromiseCallback): IHttpPromise; 1422 | } 1423 | 1424 | // See the jsdoc for transformData() at https://github.com/angular/angular.js/blob/master/src/ng/http.js#L228 1425 | interface IHttpRequestTransformer { 1426 | (data: any, headersGetter: IHttpHeadersGetter): any; 1427 | } 1428 | 1429 | // The definition of fields are the same as IHttpPromiseCallbackArg 1430 | interface IHttpResponseTransformer { 1431 | (data: any, headersGetter: IHttpHeadersGetter, status: number): any; 1432 | } 1433 | 1434 | type HttpHeaderType = {[requestType: string]:string|((config:IRequestConfig) => string)}; 1435 | 1436 | interface IHttpRequestConfigHeaders { 1437 | [requestType: string]: any; 1438 | common?: any; 1439 | get?: any; 1440 | post?: any; 1441 | put?: any; 1442 | patch?: any; 1443 | } 1444 | 1445 | /** 1446 | * Object that controls the defaults for $http provider. Not all fields of IRequestShortcutConfig can be configured 1447 | * via defaults and the docs do not say which. The following is based on the inspection of the source code. 1448 | * https://docs.angularjs.org/api/ng/service/$http#defaults 1449 | * https://docs.angularjs.org/api/ng/service/$http#usage 1450 | * https://docs.angularjs.org/api/ng/provider/$httpProvider The properties section 1451 | */ 1452 | interface IHttpProviderDefaults { 1453 | /** 1454 | * {boolean|Cache} 1455 | * If true, a default $http cache will be used to cache the GET request, otherwise if a cache instance built with $cacheFactory, this cache will be used for caching. 1456 | */ 1457 | cache?: any; 1458 | 1459 | /** 1460 | * Transform function or an array of such functions. The transform function takes the http request body and 1461 | * headers and returns its transformed (typically serialized) version. 1462 | * @see {@link https://docs.angularjs.org/api/ng/service/$http#transforming-requests-and-responses} 1463 | */ 1464 | transformRequest?: IHttpRequestTransformer |IHttpRequestTransformer[]; 1465 | 1466 | /** 1467 | * Transform function or an array of such functions. The transform function takes the http response body and 1468 | * headers and returns its transformed (typically deserialized) version. 1469 | */ 1470 | transformResponse?: IHttpResponseTransformer | IHttpResponseTransformer[]; 1471 | 1472 | /** 1473 | * Map of strings or functions which return strings representing HTTP headers to send to the server. If the 1474 | * return value of a function is null, the header will not be sent. 1475 | * The key of the map is the request verb in lower case. The "common" key applies to all requests. 1476 | * @see {@link https://docs.angularjs.org/api/ng/service/$http#setting-http-headers} 1477 | */ 1478 | headers?: IHttpRequestConfigHeaders; 1479 | 1480 | /** Name of HTTP header to populate with the XSRF token. */ 1481 | xsrfHeaderName?: string; 1482 | 1483 | /** Name of cookie containing the XSRF token. */ 1484 | xsrfCookieName?: string; 1485 | 1486 | /** 1487 | * whether to to set the withCredentials flag on the XHR object. See [requests with credentials]https://developer.mozilla.org/en/http_access_control#section_5 for more information. 1488 | */ 1489 | withCredentials?: boolean; 1490 | 1491 | /** 1492 | * A function used to the prepare string representation of request parameters (specified as an object). If 1493 | * specified as string, it is interpreted as a function registered with the $injector. Defaults to 1494 | * $httpParamSerializer. 1495 | */ 1496 | paramSerializer?: string | ((obj: any) => string); 1497 | } 1498 | 1499 | interface IHttpInterceptor { 1500 | request?: (config: IRequestConfig) => IRequestConfig|IPromise; 1501 | requestError?: (rejection: any) => any; 1502 | response?: (response: IHttpPromiseCallbackArg) => IPromise>|IHttpPromiseCallbackArg; 1503 | responseError?: (rejection: any) => any; 1504 | } 1505 | 1506 | interface IHttpInterceptorFactory { 1507 | (...args: any[]): IHttpInterceptor; 1508 | } 1509 | 1510 | interface IHttpProvider extends IServiceProvider { 1511 | defaults: IHttpProviderDefaults; 1512 | 1513 | /** 1514 | * Register service factories (names or implementations) for interceptors which are called before and after 1515 | * each request. 1516 | */ 1517 | interceptors: (string | Injectable)[]; 1518 | useApplyAsync(): boolean; 1519 | useApplyAsync(value: boolean): IHttpProvider; 1520 | 1521 | /** 1522 | * 1523 | * @param {boolean=} value If true, `$http` will return a normal promise without the `success` and `error` methods. 1524 | * @returns {boolean|Object} If a value is specified, returns the $httpProvider for chaining. 1525 | * otherwise, returns the current configured value. 1526 | */ 1527 | useLegacyPromiseExtensions(value:boolean) : boolean | IHttpProvider; 1528 | } 1529 | 1530 | /////////////////////////////////////////////////////////////////////////// 1531 | // HttpBackendService 1532 | // see http://docs.angularjs.org/api/ng.$httpBackend 1533 | // You should never need to use this service directly. 1534 | /////////////////////////////////////////////////////////////////////////// 1535 | interface IHttpBackendService { 1536 | // XXX Perhaps define callback signature in the future 1537 | (method: string, url: string, post?: any, callback?: Function, headers?: any, timeout?: number, withCredentials?: boolean): void; 1538 | } 1539 | 1540 | /////////////////////////////////////////////////////////////////////////// 1541 | // InterpolateService 1542 | // see http://docs.angularjs.org/api/ng.$interpolate 1543 | // see http://docs.angularjs.org/api/ng.$interpolateProvider 1544 | /////////////////////////////////////////////////////////////////////////// 1545 | interface IInterpolateService { 1546 | (text: string, mustHaveExpression?: boolean, trustedContext?: string, allOrNothing?: boolean): IInterpolationFunction; 1547 | endSymbol(): string; 1548 | startSymbol(): string; 1549 | } 1550 | 1551 | interface IInterpolationFunction { 1552 | (context: any): string; 1553 | } 1554 | 1555 | interface IInterpolateProvider extends IServiceProvider { 1556 | startSymbol(): string; 1557 | startSymbol(value: string): IInterpolateProvider; 1558 | endSymbol(): string; 1559 | endSymbol(value: string): IInterpolateProvider; 1560 | } 1561 | 1562 | /////////////////////////////////////////////////////////////////////////// 1563 | // TemplateCacheService 1564 | // see http://docs.angularjs.org/api/ng.$templateCache 1565 | /////////////////////////////////////////////////////////////////////////// 1566 | interface ITemplateCacheService extends ICacheObject {} 1567 | 1568 | /////////////////////////////////////////////////////////////////////////// 1569 | // SCEService 1570 | // see http://docs.angularjs.org/api/ng.$sce 1571 | /////////////////////////////////////////////////////////////////////////// 1572 | interface ISCEService { 1573 | getTrusted(type: string, mayBeTrusted: any): any; 1574 | getTrustedCss(value: any): any; 1575 | getTrustedHtml(value: any): any; 1576 | getTrustedJs(value: any): any; 1577 | getTrustedResourceUrl(value: any): any; 1578 | getTrustedUrl(value: any): any; 1579 | parse(type: string, expression: string): (context: any, locals: any) => any; 1580 | parseAsCss(expression: string): (context: any, locals: any) => any; 1581 | parseAsHtml(expression: string): (context: any, locals: any) => any; 1582 | parseAsJs(expression: string): (context: any, locals: any) => any; 1583 | parseAsResourceUrl(expression: string): (context: any, locals: any) => any; 1584 | parseAsUrl(expression: string): (context: any, locals: any) => any; 1585 | trustAs(type: string, value: any): any; 1586 | trustAsHtml(value: any): any; 1587 | trustAsJs(value: any): any; 1588 | trustAsResourceUrl(value: any): any; 1589 | trustAsUrl(value: any): any; 1590 | isEnabled(): boolean; 1591 | } 1592 | 1593 | /////////////////////////////////////////////////////////////////////////// 1594 | // SCEProvider 1595 | // see http://docs.angularjs.org/api/ng.$sceProvider 1596 | /////////////////////////////////////////////////////////////////////////// 1597 | interface ISCEProvider extends IServiceProvider { 1598 | enabled(value: boolean): void; 1599 | } 1600 | 1601 | /////////////////////////////////////////////////////////////////////////// 1602 | // SCEDelegateService 1603 | // see http://docs.angularjs.org/api/ng.$sceDelegate 1604 | /////////////////////////////////////////////////////////////////////////// 1605 | interface ISCEDelegateService { 1606 | getTrusted(type: string, mayBeTrusted: any): any; 1607 | trustAs(type: string, value: any): any; 1608 | valueOf(value: any): any; 1609 | } 1610 | 1611 | 1612 | /////////////////////////////////////////////////////////////////////////// 1613 | // SCEDelegateProvider 1614 | // see http://docs.angularjs.org/api/ng.$sceDelegateProvider 1615 | /////////////////////////////////////////////////////////////////////////// 1616 | interface ISCEDelegateProvider extends IServiceProvider { 1617 | resourceUrlBlacklist(blacklist: any[]): void; 1618 | resourceUrlWhitelist(whitelist: any[]): void; 1619 | resourceUrlBlacklist(): any[]; 1620 | resourceUrlWhitelist(): any[]; 1621 | } 1622 | 1623 | /** 1624 | * $templateRequest service 1625 | * see http://docs.angularjs.org/api/ng/service/$templateRequest 1626 | */ 1627 | interface ITemplateRequestService { 1628 | /** 1629 | * Downloads a template using $http and, upon success, stores the 1630 | * contents inside of $templateCache. 1631 | * 1632 | * If the HTTP request fails or the response data of the HTTP request is 1633 | * empty then a $compile error will be thrown (unless 1634 | * {ignoreRequestError} is set to true). 1635 | * 1636 | * @param tpl The template URL. 1637 | * @param ignoreRequestError Whether or not to ignore the exception 1638 | * when the request fails or the template is 1639 | * empty. 1640 | * 1641 | * @return A promise whose value is the template content. 1642 | */ 1643 | (tpl: string, ignoreRequestError?: boolean): IPromise; 1644 | /** 1645 | * total amount of pending template requests being downloaded. 1646 | * @type {number} 1647 | */ 1648 | totalPendingRequests: number; 1649 | } 1650 | 1651 | /////////////////////////////////////////////////////////////////////////// 1652 | // Component 1653 | // see http://angularjs.blogspot.com.br/2015/11/angularjs-15-beta2-and-14-releases.html 1654 | // and http://toddmotto.com/exploring-the-angular-1-5-component-method/ 1655 | /////////////////////////////////////////////////////////////////////////// 1656 | /** 1657 | * Component definition object (a simplified directive definition object) 1658 | */ 1659 | interface IComponentOptions { 1660 | /** 1661 | * Controller constructor function that should be associated with newly created scope or the name of a registered 1662 | * controller if passed as a string. Empty function by default. 1663 | * Use the array form to define dependencies (necessary if strictDi is enabled and you require dependency injection) 1664 | */ 1665 | controller?: string | Injectable; 1666 | /** 1667 | * An identifier name for a reference to the controller. If present, the controller will be published to its scope under 1668 | * the specified name. If not present, this will default to '$ctrl'. 1669 | */ 1670 | controllerAs?: string; 1671 | /** 1672 | * html template as a string or a function that returns an html template as a string which should be used as the 1673 | * contents of this component. Empty string by default. 1674 | * If template is a function, then it is injected with the following locals: 1675 | * $element - Current element 1676 | * $attrs - Current attributes object for the element 1677 | * Use the array form to define dependencies (necessary if strictDi is enabled and you require dependency injection) 1678 | */ 1679 | template?: string | Injectable<(...args: any[]) => string>; 1680 | /** 1681 | * Path or function that returns a path to an html template that should be used as the contents of this component. 1682 | * If templateUrl is a function, then it is injected with the following locals: 1683 | * $element - Current element 1684 | * $attrs - Current attributes object for the element 1685 | * Use the array form to define dependencies (necessary if strictDi is enabled and you require dependency injection) 1686 | */ 1687 | templateUrl?: string | Injectable<(...args: any[]) => string>; 1688 | /** 1689 | * Define DOM attribute binding to component properties. Component properties are always bound to the component 1690 | * controller and not to the scope. 1691 | */ 1692 | bindings?: {[boundProperty: string]: string}; 1693 | /** 1694 | * Whether transclusion is enabled. Disabled by default. 1695 | */ 1696 | transclude?: boolean | {[slot: string]: string}; 1697 | /** 1698 | * Requires the controllers of other directives and binds them to this component's controller. 1699 | * The object keys specify the property names under which the required controllers (object values) will be bound. 1700 | * Note that the required controllers will not be available during the instantiation of the controller, 1701 | * but they are guaranteed to be available just before the $onInit method is executed! 1702 | */ 1703 | require?: {[controller: string]: string}; 1704 | } 1705 | 1706 | type IControllerConstructor = 1707 | (new (...args: any[]) => IController) | 1708 | // Instead of classes, plain functions are often used as controller constructors, especially in examples. 1709 | ((...args: any[]) => (void | IController)); 1710 | 1711 | /** 1712 | * Directive controllers have a well-defined lifecycle. Each controller can implement "lifecycle hooks". These are methods that 1713 | * will be called by Angular at certain points in the life cycle of the directive. 1714 | * https://docs.angularjs.org/api/ng/service/$compile#life-cycle-hooks 1715 | * https://docs.angularjs.org/guide/component 1716 | */ 1717 | interface IController { 1718 | /** 1719 | * Called on each controller after all the controllers on an element have been constructed and had their bindings 1720 | * initialized (and before the pre & post linking functions for the directives on this element). This is a good 1721 | * place to put initialization code for your controller. 1722 | */ 1723 | $onInit?(): void; 1724 | /** 1725 | * Called on each turn of the digest cycle. Provides an opportunity to detect and act on changes. 1726 | * Any actions that you wish to take in response to the changes that you detect must be invoked from this hook; 1727 | * implementing this has no effect on when `$onChanges` is called. For example, this hook could be useful if you wish 1728 | * to perform a deep equality check, or to check a `Dat`e object, changes to which would not be detected by Angular's 1729 | * change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments; if detecting changes, 1730 | * you must store the previous value(s) for comparison to the current values. 1731 | */ 1732 | $doCheck?(): void; 1733 | /** 1734 | * Called whenever one-way bindings are updated. The onChangesObj is a hash whose keys are the names of the bound 1735 | * properties that have changed, and the values are an {@link IChangesObject} object of the form 1736 | * { currentValue, previousValue, isFirstChange() }. Use this hook to trigger updates within a component such as 1737 | * cloning the bound value to prevent accidental mutation of the outer value. 1738 | */ 1739 | $onChanges?(onChangesObj: IOnChangesObject): void; 1740 | /** 1741 | * Called on a controller when its containing scope is destroyed. Use this hook for releasing external resources, 1742 | * watches and event handlers. 1743 | */ 1744 | $onDestroy?(): void; 1745 | /** 1746 | * Called after this controller's element and its children have been linked. Similar to the post-link function this 1747 | * hook can be used to set up DOM event handlers and do direct DOM manipulation. Note that child elements that contain 1748 | * templateUrl directives will not have been compiled and linked since they are waiting for their template to load 1749 | * asynchronously and their own compilation and linking has been suspended until that occurs. This hook can be considered 1750 | * analogous to the ngAfterViewInit and ngAfterContentInit hooks in Angular 2. Since the compilation process is rather 1751 | * different in Angular 1 there is no direct mapping and care should be taken when upgrading. 1752 | */ 1753 | $postLink?(): void; 1754 | } 1755 | 1756 | interface IOnChangesObject { 1757 | [property: string]: IChangesObject; 1758 | } 1759 | 1760 | interface IChangesObject { 1761 | currentValue: T; 1762 | previousValue: T; 1763 | isFirstChange(): boolean; 1764 | } 1765 | 1766 | /////////////////////////////////////////////////////////////////////////// 1767 | // Directive 1768 | // see http://docs.angularjs.org/api/ng.$compileProvider#directive 1769 | // and http://docs.angularjs.org/guide/directive 1770 | /////////////////////////////////////////////////////////////////////////// 1771 | 1772 | interface IDirectiveFactory { 1773 | (...args: any[]): IDirective | IDirectiveLinkFn; 1774 | } 1775 | 1776 | interface IDirectiveLinkFn { 1777 | ( 1778 | scope: IScope, 1779 | instanceElement: JQuery, 1780 | instanceAttributes: IAttributes, 1781 | controller?: IController | IController[] | {[key: string]: IController}, 1782 | transclude?: ITranscludeFunction 1783 | ): void; 1784 | } 1785 | 1786 | interface IDirectivePrePost { 1787 | pre?: IDirectiveLinkFn; 1788 | post?: IDirectiveLinkFn; 1789 | } 1790 | 1791 | interface IDirectiveCompileFn { 1792 | ( 1793 | templateElement: JQuery, 1794 | templateAttributes: IAttributes, 1795 | /** 1796 | * @deprecated 1797 | * Note: The transclude function that is passed to the compile function is deprecated, 1798 | * as it e.g. does not know about the right outer scope. Please use the transclude function 1799 | * that is passed to the link function instead. 1800 | */ 1801 | transclude: ITranscludeFunction 1802 | ): void | IDirectiveLinkFn | IDirectivePrePost; 1803 | } 1804 | 1805 | interface IDirective { 1806 | compile?: IDirectiveCompileFn; 1807 | controller?: string | Injectable; 1808 | controllerAs?: string; 1809 | /** 1810 | * Deprecation warning: although bindings for non-ES6 class controllers are currently bound to this before 1811 | * the controller constructor is called, this use is now deprecated. Please place initialization code that 1812 | * relies upon bindings inside a $onInit method on the controller, instead. 1813 | */ 1814 | bindToController?: boolean | {[boundProperty: string]: string}; 1815 | link?: IDirectiveLinkFn | IDirectivePrePost; 1816 | multiElement?: boolean; 1817 | priority?: number; 1818 | /** 1819 | * @deprecated 1820 | */ 1821 | replace?: boolean; 1822 | require?: string | string[] | {[controller: string]: string}; 1823 | restrict?: string; 1824 | scope?: boolean | {[boundProperty: string]: string}; 1825 | template?: string | ((tElement: JQuery, tAttrs: IAttributes) => string); 1826 | templateNamespace?: string; 1827 | templateUrl?: string | ((tElement: JQuery, tAttrs: IAttributes) => string); 1828 | terminal?: boolean; 1829 | transclude?: boolean | 'element' | {[slot: string]: string}; 1830 | } 1831 | 1832 | /** 1833 | * These interfaces are kept for compatibility with older versions of these type definitions. 1834 | * Actually, Angular doesn't create a special subclass of jQuery objects. It extends jQuery.prototype 1835 | * like jQuery plugins do, that's why all jQuery objects have these Angular-specific methods, not 1836 | * only those returned from angular.element. 1837 | * See: http://docs.angularjs.org/api/angular.element 1838 | */ 1839 | interface IAugmentedJQueryStatic extends JQueryStatic {} 1840 | interface IAugmentedJQuery extends JQuery {} 1841 | 1842 | /** 1843 | * Same as IController. Keeping it for compatibility with older versions of these type definitions. 1844 | */ 1845 | interface IComponentController extends IController {} 1846 | 1847 | /////////////////////////////////////////////////////////////////////////// 1848 | // AUTO module (angular.js) 1849 | /////////////////////////////////////////////////////////////////////////// 1850 | export module auto { 1851 | 1852 | /////////////////////////////////////////////////////////////////////// 1853 | // InjectorService 1854 | // see http://docs.angularjs.org/api/AUTO.$injector 1855 | /////////////////////////////////////////////////////////////////////// 1856 | interface IInjectorService { 1857 | annotate(fn: Function, strictDi?: boolean): string[]; 1858 | annotate(inlineAnnotatedFunction: any[]): string[]; 1859 | get(name: string, caller?: string): T; 1860 | get(name: '$anchorScroll'): IAnchorScrollService 1861 | get(name: '$cacheFactory'): ICacheFactoryService 1862 | get(name: '$compile'): ICompileService 1863 | get(name: '$controller'): IControllerService 1864 | get(name: '$document'): IDocumentService 1865 | get(name: '$exceptionHandler'): IExceptionHandlerService 1866 | get(name: '$filter'): IFilterService 1867 | get(name: '$http'): IHttpService 1868 | get(name: '$httpBackend'): IHttpBackendService 1869 | get(name: '$httpParamSerializer'): IHttpParamSerializer 1870 | get(name: '$httpParamSerializerJQLike'): IHttpParamSerializer 1871 | get(name: '$interpolate'): IInterpolateService 1872 | get(name: '$interval'): IIntervalService 1873 | get(name: '$locale'): ILocaleService 1874 | get(name: '$location'): ILocationService 1875 | get(name: '$log'): ILogService 1876 | get(name: '$parse'): IParseService 1877 | get(name: '$q'): IQService 1878 | get(name: '$rootElement'): IRootElementService 1879 | get(name: '$rootScope'): IRootScopeService 1880 | get(name: '$sce'): ISCEService 1881 | get(name: '$sceDelegate'): ISCEDelegateService 1882 | get(name: '$templateCache'): ITemplateCacheService 1883 | get(name: '$templateRequest'): ITemplateRequestService 1884 | get(name: '$timeout'): ITimeoutService 1885 | get(name: '$window'): IWindowService 1886 | get(name: '$xhrFactory'): IXhrFactory 1887 | has(name: string): boolean; 1888 | instantiate(typeConstructor: Function, locals?: any): T; 1889 | invoke(inlineAnnotatedFunction: any[]): any; 1890 | invoke(func: Function, context?: any, locals?: any): any; 1891 | strictDi: boolean; 1892 | } 1893 | 1894 | /////////////////////////////////////////////////////////////////////// 1895 | // ProvideService 1896 | // see http://docs.angularjs.org/api/AUTO.$provide 1897 | /////////////////////////////////////////////////////////////////////// 1898 | interface IProvideService { 1899 | // Documentation says it returns the registered instance, but actual 1900 | // implementation does not return anything. 1901 | // constant(name: string, value: any): any; 1902 | /** 1903 | * Register a constant service, such as a string, a number, an array, an object or a function, with the $injector. Unlike value it can be injected into a module configuration function (see config) and it cannot be overridden by an Angular decorator. 1904 | * 1905 | * @param name The name of the constant. 1906 | * @param value The constant value. 1907 | */ 1908 | constant(name: string, value: any): void; 1909 | 1910 | /** 1911 | * Register a service decorator with the $injector. A service decorator intercepts the creation of a service, allowing it to override or modify the behaviour of the service. The object returned by the decorator may be the original service, or a new service object which replaces or wraps and delegates to the original service. 1912 | * 1913 | * @param name The name of the service to decorate. 1914 | * @param decorator This function will be invoked when the service needs to be instantiated and should return the decorated service instance. The function is called using the injector.invoke method and is therefore fully injectable. Local injection arguments: 1915 | * 1916 | * $delegate - The original service instance, which can be monkey patched, configured, decorated or delegated to. 1917 | */ 1918 | decorator(name: string, decorator: Function): void; 1919 | /** 1920 | * Register a service decorator with the $injector. A service decorator intercepts the creation of a service, allowing it to override or modify the behaviour of the service. The object returned by the decorator may be the original service, or a new service object which replaces or wraps and delegates to the original service. 1921 | * 1922 | * @param name The name of the service to decorate. 1923 | * @param inlineAnnotatedFunction This function will be invoked when the service needs to be instantiated and should return the decorated service instance. The function is called using the injector.invoke method and is therefore fully injectable. Local injection arguments: 1924 | * 1925 | * $delegate - The original service instance, which can be monkey patched, configured, decorated or delegated to. 1926 | */ 1927 | decorator(name: string, inlineAnnotatedFunction: any[]): void; 1928 | factory(name: string, serviceFactoryFunction: Function): IServiceProvider; 1929 | factory(name: string, inlineAnnotatedFunction: any[]): IServiceProvider; 1930 | provider(name: string, provider: IServiceProvider): IServiceProvider; 1931 | provider(name: string, serviceProviderConstructor: Function): IServiceProvider; 1932 | service(name: string, constructor: Function): IServiceProvider; 1933 | service(name: string, inlineAnnotatedFunction: any[]): IServiceProvider; 1934 | value(name: string, value: any): IServiceProvider; 1935 | } 1936 | 1937 | } 1938 | 1939 | /** 1940 | * $http params serializer that converts objects to strings 1941 | * see https://docs.angularjs.org/api/ng/service/$httpParamSerializer 1942 | */ 1943 | interface IHttpParamSerializer { 1944 | (obj: Object): string; 1945 | } 1946 | } 1947 | 1948 | interface JQuery { 1949 | // TODO: events, how to define? 1950 | //$destroy 1951 | 1952 | find(element: any): JQuery; 1953 | find(obj: JQuery): JQuery; 1954 | controller(name?: string): any; 1955 | injector(): ng.auto.IInjectorService; 1956 | /** It's declared generic for custom scope interfaces */ 1957 | scope(): T; 1958 | isolateScope(): T; 1959 | 1960 | inheritedData(key: string, value: any): JQuery; 1961 | inheritedData(obj: { [key: string]: any; }): JQuery; 1962 | inheritedData(key?: string): any; 1963 | } 1964 | --------------------------------------------------------------------------------