You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

278 lines
6.1 KiB

4 years ago
  1. (function (root, factory){
  2. 'use strict';
  3. /*istanbul ignore next:cant test*/
  4. if (typeof module === 'object' && typeof module.exports === 'object') {
  5. module.exports = factory();
  6. } else if (typeof define === 'function' && define.amd) {
  7. // AMD. Register as an anonymous module.
  8. define([], factory);
  9. } else {
  10. // Browser globals
  11. root.objectPath = factory();
  12. }
  13. })(this, function(){
  14. 'use strict';
  15. var
  16. toStr = Object.prototype.toString,
  17. _hasOwnProperty = Object.prototype.hasOwnProperty;
  18. function isEmpty(value){
  19. if (!value) {
  20. return true;
  21. }
  22. if (isArray(value) && value.length === 0) {
  23. return true;
  24. } else if (!isString(value)) {
  25. for (var i in value) {
  26. if (_hasOwnProperty.call(value, i)) {
  27. return false;
  28. }
  29. }
  30. return true;
  31. }
  32. return false;
  33. }
  34. function toString(type){
  35. return toStr.call(type);
  36. }
  37. function isNumber(value){
  38. return typeof value === 'number' || toString(value) === "[object Number]";
  39. }
  40. function isString(obj){
  41. return typeof obj === 'string' || toString(obj) === "[object String]";
  42. }
  43. function isObject(obj){
  44. return typeof obj === 'object' && toString(obj) === "[object Object]";
  45. }
  46. function isArray(obj){
  47. return typeof obj === 'object' && typeof obj.length === 'number' && toString(obj) === '[object Array]';
  48. }
  49. function isBoolean(obj){
  50. return typeof obj === 'boolean' || toString(obj) === '[object Boolean]';
  51. }
  52. function getKey(key){
  53. var intKey = parseInt(key);
  54. if (intKey.toString() === key) {
  55. return intKey;
  56. }
  57. return key;
  58. }
  59. function set(obj, path, value, doNotReplace){
  60. if (isNumber(path)) {
  61. path = [path];
  62. }
  63. if (isEmpty(path)) {
  64. return obj;
  65. }
  66. if (isString(path)) {
  67. return set(obj, path.split('.').map(getKey), value, doNotReplace);
  68. }
  69. var currentPath = path[0];
  70. if (path.length === 1) {
  71. var oldVal = obj[currentPath];
  72. if (oldVal === void 0 || !doNotReplace) {
  73. obj[currentPath] = value;
  74. }
  75. return oldVal;
  76. }
  77. if (obj[currentPath] === void 0) {
  78. //check if we assume an array
  79. if(isNumber(path[1])) {
  80. obj[currentPath] = [];
  81. } else {
  82. obj[currentPath] = {};
  83. }
  84. }
  85. return set(obj[currentPath], path.slice(1), value, doNotReplace);
  86. }
  87. function del(obj, path) {
  88. if (isNumber(path)) {
  89. path = [path];
  90. }
  91. if (isEmpty(obj)) {
  92. return void 0;
  93. }
  94. if (isEmpty(path)) {
  95. return obj;
  96. }
  97. if(isString(path)) {
  98. return del(obj, path.split('.'));
  99. }
  100. var currentPath = getKey(path[0]);
  101. var oldVal = obj[currentPath];
  102. if(path.length === 1) {
  103. if (oldVal !== void 0) {
  104. if (isArray(obj)) {
  105. obj.splice(currentPath, 1);
  106. } else {
  107. delete obj[currentPath];
  108. }
  109. }
  110. } else {
  111. if (obj[currentPath] !== void 0) {
  112. return del(obj[currentPath], path.slice(1));
  113. }
  114. }
  115. return obj;
  116. }
  117. var objectPath = function(obj) {
  118. return Object.keys(objectPath).reduce(function(proxy, prop) {
  119. if (typeof objectPath[prop] === 'function') {
  120. proxy[prop] = objectPath[prop].bind(objectPath, obj);
  121. }
  122. return proxy;
  123. }, {});
  124. };
  125. objectPath.has = function (obj, path) {
  126. if (isEmpty(obj)) {
  127. return false;
  128. }
  129. if (isNumber(path)) {
  130. path = [path];
  131. } else if (isString(path)) {
  132. path = path.split('.');
  133. }
  134. if (isEmpty(path) || path.length === 0) {
  135. return false;
  136. }
  137. for (var i = 0; i < path.length; i++) {
  138. var j = path[i];
  139. if ((isObject(obj) || isArray(obj)) && _hasOwnProperty.call(obj, j)) {
  140. obj = obj[j];
  141. } else {
  142. return false;
  143. }
  144. }
  145. return true;
  146. };
  147. objectPath.ensureExists = function (obj, path, value){
  148. return set(obj, path, value, true);
  149. };
  150. objectPath.set = function (obj, path, value, doNotReplace){
  151. return set(obj, path, value, doNotReplace);
  152. };
  153. objectPath.insert = function (obj, path, value, at){
  154. var arr = objectPath.get(obj, path);
  155. at = ~~at;
  156. if (!isArray(arr)) {
  157. arr = [];
  158. objectPath.set(obj, path, arr);
  159. }
  160. arr.splice(at, 0, value);
  161. };
  162. objectPath.empty = function(obj, path) {
  163. if (isEmpty(path)) {
  164. return obj;
  165. }
  166. if (isEmpty(obj)) {
  167. return void 0;
  168. }
  169. var value, i;
  170. if (!(value = objectPath.get(obj, path))) {
  171. return obj;
  172. }
  173. if (isString(value)) {
  174. return objectPath.set(obj, path, '');
  175. } else if (isBoolean(value)) {
  176. return objectPath.set(obj, path, false);
  177. } else if (isNumber(value)) {
  178. return objectPath.set(obj, path, 0);
  179. } else if (isArray(value)) {
  180. value.length = 0;
  181. } else if (isObject(value)) {
  182. for (i in value) {
  183. if (_hasOwnProperty.call(value, i)) {
  184. delete value[i];
  185. }
  186. }
  187. } else {
  188. return objectPath.set(obj, path, null);
  189. }
  190. };
  191. objectPath.push = function (obj, path /*, values */){
  192. var arr = objectPath.get(obj, path);
  193. if (!isArray(arr)) {
  194. arr = [];
  195. objectPath.set(obj, path, arr);
  196. }
  197. arr.push.apply(arr, Array.prototype.slice.call(arguments, 2));
  198. };
  199. objectPath.coalesce = function (obj, paths, defaultValue) {
  200. var value;
  201. for (var i = 0, len = paths.length; i < len; i++) {
  202. if ((value = objectPath.get(obj, paths[i])) !== void 0) {
  203. return value;
  204. }
  205. }
  206. return defaultValue;
  207. };
  208. objectPath.get = function (obj, path, defaultValue){
  209. if (isNumber(path)) {
  210. path = [path];
  211. }
  212. if (isEmpty(path)) {
  213. return obj;
  214. }
  215. if (isEmpty(obj)) {
  216. return defaultValue;
  217. }
  218. if (isString(path)) {
  219. return objectPath.get(obj, path.split('.'), defaultValue);
  220. }
  221. var currentPath = getKey(path[0]);
  222. if (path.length === 1) {
  223. if (obj[currentPath] === void 0) {
  224. return defaultValue;
  225. }
  226. return obj[currentPath];
  227. }
  228. return objectPath.get(obj[currentPath], path.slice(1), defaultValue);
  229. };
  230. objectPath.del = function(obj, path) {
  231. return del(obj, path);
  232. };
  233. return objectPath;
  234. });