Dieses Repository beinhaltet HTML- und Javascript Code zur einer NotizenWebApp auf Basis von Web Storage. Zudem sind Mocha/Chai Tests im Browser enthalten. https://meinenotizen.netlify.app/
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.

index.js 7.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. 'use strict';
  2. /* !
  3. * Chai - pathval utility
  4. * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
  5. * @see https://github.com/logicalparadox/filtr
  6. * MIT Licensed
  7. */
  8. /**
  9. * ### .hasProperty(object, name)
  10. *
  11. * This allows checking whether an object has own
  12. * or inherited from prototype chain named property.
  13. *
  14. * Basically does the same thing as the `in`
  15. * operator but works properly with null/undefined values
  16. * and other primitives.
  17. *
  18. * var obj = {
  19. * arr: ['a', 'b', 'c']
  20. * , str: 'Hello'
  21. * }
  22. *
  23. * The following would be the results.
  24. *
  25. * hasProperty(obj, 'str'); // true
  26. * hasProperty(obj, 'constructor'); // true
  27. * hasProperty(obj, 'bar'); // false
  28. *
  29. * hasProperty(obj.str, 'length'); // true
  30. * hasProperty(obj.str, 1); // true
  31. * hasProperty(obj.str, 5); // false
  32. *
  33. * hasProperty(obj.arr, 'length'); // true
  34. * hasProperty(obj.arr, 2); // true
  35. * hasProperty(obj.arr, 3); // false
  36. *
  37. * @param {Object} object
  38. * @param {String|Symbol} name
  39. * @returns {Boolean} whether it exists
  40. * @namespace Utils
  41. * @name hasProperty
  42. * @api public
  43. */
  44. function hasProperty(obj, name) {
  45. if (typeof obj === 'undefined' || obj === null) {
  46. return false;
  47. }
  48. // The `in` operator does not work with primitives.
  49. return name in Object(obj);
  50. }
  51. /* !
  52. * ## parsePath(path)
  53. *
  54. * Helper function used to parse string object
  55. * paths. Use in conjunction with `internalGetPathValue`.
  56. *
  57. * var parsed = parsePath('myobject.property.subprop');
  58. *
  59. * ### Paths:
  60. *
  61. * * Can be infinitely deep and nested.
  62. * * Arrays are also valid using the formal `myobject.document[3].property`.
  63. * * Literal dots and brackets (not delimiter) must be backslash-escaped.
  64. *
  65. * @param {String} path
  66. * @returns {Object} parsed
  67. * @api private
  68. */
  69. function parsePath(path) {
  70. var str = path.replace(/([^\\])\[/g, '$1.[');
  71. var parts = str.match(/(\\\.|[^.]+?)+/g);
  72. return parts.map(function mapMatches(value) {
  73. var regexp = /^\[(\d+)\]$/;
  74. var mArr = regexp.exec(value);
  75. var parsed = null;
  76. if (mArr) {
  77. parsed = { i: parseFloat(mArr[1]) };
  78. } else {
  79. parsed = { p: value.replace(/\\([.\[\]])/g, '$1') };
  80. }
  81. return parsed;
  82. });
  83. }
  84. /* !
  85. * ## internalGetPathValue(obj, parsed[, pathDepth])
  86. *
  87. * Helper companion function for `.parsePath` that returns
  88. * the value located at the parsed address.
  89. *
  90. * var value = getPathValue(obj, parsed);
  91. *
  92. * @param {Object} object to search against
  93. * @param {Object} parsed definition from `parsePath`.
  94. * @param {Number} depth (nesting level) of the property we want to retrieve
  95. * @returns {Object|Undefined} value
  96. * @api private
  97. */
  98. function internalGetPathValue(obj, parsed, pathDepth) {
  99. var temporaryValue = obj;
  100. var res = null;
  101. pathDepth = (typeof pathDepth === 'undefined' ? parsed.length : pathDepth);
  102. for (var i = 0; i < pathDepth; i++) {
  103. var part = parsed[i];
  104. if (temporaryValue) {
  105. if (typeof part.p === 'undefined') {
  106. temporaryValue = temporaryValue[part.i];
  107. } else {
  108. temporaryValue = temporaryValue[part.p];
  109. }
  110. if (i === (pathDepth - 1)) {
  111. res = temporaryValue;
  112. }
  113. }
  114. }
  115. return res;
  116. }
  117. /* !
  118. * ## internalSetPathValue(obj, value, parsed)
  119. *
  120. * Companion function for `parsePath` that sets
  121. * the value located at a parsed address.
  122. *
  123. * internalSetPathValue(obj, 'value', parsed);
  124. *
  125. * @param {Object} object to search and define on
  126. * @param {*} value to use upon set
  127. * @param {Object} parsed definition from `parsePath`
  128. * @api private
  129. */
  130. function internalSetPathValue(obj, val, parsed) {
  131. var tempObj = obj;
  132. var pathDepth = parsed.length;
  133. var part = null;
  134. // Here we iterate through every part of the path
  135. for (var i = 0; i < pathDepth; i++) {
  136. var propName = null;
  137. var propVal = null;
  138. part = parsed[i];
  139. // If it's the last part of the path, we set the 'propName' value with the property name
  140. if (i === (pathDepth - 1)) {
  141. propName = typeof part.p === 'undefined' ? part.i : part.p;
  142. // Now we set the property with the name held by 'propName' on object with the desired val
  143. tempObj[propName] = val;
  144. } else if (typeof part.p !== 'undefined' && tempObj[part.p]) {
  145. tempObj = tempObj[part.p];
  146. } else if (typeof part.i !== 'undefined' && tempObj[part.i]) {
  147. tempObj = tempObj[part.i];
  148. } else {
  149. // If the obj doesn't have the property we create one with that name to define it
  150. var next = parsed[i + 1];
  151. // Here we set the name of the property which will be defined
  152. propName = typeof part.p === 'undefined' ? part.i : part.p;
  153. // Here we decide if this property will be an array or a new object
  154. propVal = typeof next.p === 'undefined' ? [] : {};
  155. tempObj[propName] = propVal;
  156. tempObj = tempObj[propName];
  157. }
  158. }
  159. }
  160. /**
  161. * ### .getPathInfo(object, path)
  162. *
  163. * This allows the retrieval of property info in an
  164. * object given a string path.
  165. *
  166. * The path info consists of an object with the
  167. * following properties:
  168. *
  169. * * parent - The parent object of the property referenced by `path`
  170. * * name - The name of the final property, a number if it was an array indexer
  171. * * value - The value of the property, if it exists, otherwise `undefined`
  172. * * exists - Whether the property exists or not
  173. *
  174. * @param {Object} object
  175. * @param {String} path
  176. * @returns {Object} info
  177. * @namespace Utils
  178. * @name getPathInfo
  179. * @api public
  180. */
  181. function getPathInfo(obj, path) {
  182. var parsed = parsePath(path);
  183. var last = parsed[parsed.length - 1];
  184. var info = {
  185. parent: parsed.length > 1 ? internalGetPathValue(obj, parsed, parsed.length - 1) : obj,
  186. name: last.p || last.i,
  187. value: internalGetPathValue(obj, parsed),
  188. };
  189. info.exists = hasProperty(info.parent, info.name);
  190. return info;
  191. }
  192. /**
  193. * ### .getPathValue(object, path)
  194. *
  195. * This allows the retrieval of values in an
  196. * object given a string path.
  197. *
  198. * var obj = {
  199. * prop1: {
  200. * arr: ['a', 'b', 'c']
  201. * , str: 'Hello'
  202. * }
  203. * , prop2: {
  204. * arr: [ { nested: 'Universe' } ]
  205. * , str: 'Hello again!'
  206. * }
  207. * }
  208. *
  209. * The following would be the results.
  210. *
  211. * getPathValue(obj, 'prop1.str'); // Hello
  212. * getPathValue(obj, 'prop1.att[2]'); // b
  213. * getPathValue(obj, 'prop2.arr[0].nested'); // Universe
  214. *
  215. * @param {Object} object
  216. * @param {String} path
  217. * @returns {Object} value or `undefined`
  218. * @namespace Utils
  219. * @name getPathValue
  220. * @api public
  221. */
  222. function getPathValue(obj, path) {
  223. var info = getPathInfo(obj, path);
  224. return info.value;
  225. }
  226. /**
  227. * ### .setPathValue(object, path, value)
  228. *
  229. * Define the value in an object at a given string path.
  230. *
  231. * ```js
  232. * var obj = {
  233. * prop1: {
  234. * arr: ['a', 'b', 'c']
  235. * , str: 'Hello'
  236. * }
  237. * , prop2: {
  238. * arr: [ { nested: 'Universe' } ]
  239. * , str: 'Hello again!'
  240. * }
  241. * };
  242. * ```
  243. *
  244. * The following would be acceptable.
  245. *
  246. * ```js
  247. * var properties = require('tea-properties');
  248. * properties.set(obj, 'prop1.str', 'Hello Universe!');
  249. * properties.set(obj, 'prop1.arr[2]', 'B');
  250. * properties.set(obj, 'prop2.arr[0].nested.value', { hello: 'universe' });
  251. * ```
  252. *
  253. * @param {Object} object
  254. * @param {String} path
  255. * @param {Mixed} value
  256. * @api private
  257. */
  258. function setPathValue(obj, path, val) {
  259. var parsed = parsePath(path);
  260. internalSetPathValue(obj, val, parsed);
  261. return obj;
  262. }
  263. module.exports = {
  264. hasProperty: hasProperty,
  265. getPathInfo: getPathInfo,
  266. getPathValue: getPathValue,
  267. setPathValue: setPathValue,
  268. };