From 1986d97f0f8071cd9027d7597a5b908cd121ec54 Mon Sep 17 00:00:00 2001 From: Thomas Dillard Date: Tue, 28 Aug 2018 15:12:53 -0700 Subject: [PATCH] Updated examples to can-define/list/list. (#377) Fixes a majority of #370. * get documentation moved and updated to ES6 and are now codepenable. It was moved to prototype.get.md. * set documentation moved and updated to ES6 and are now codepenable. It was moved to prototype.set.md. * Assign documentation moved and updated to ES6 and are now codepenable. It was moved to prototype.assign.md. * Moved update documentation to prototype.update.md updated examples to es6 and added codepen link. * assignDeep documentation moved to prototype.assignDeep.md, syntax has also been updated for examples. * updateDeep docs moved to prototype,updateDeep.md, ES6 syntax and links to codepen. * Splice documentation moved to docs/prototype.splice.md. Highlighted and ES6'd syntax. * Removed unnecessary spaing in docs/prototype.splice.md. * serialize documentation moved to docs/prototype.serialize.md. Added syntax highlighting and updated to ES6 syntax. Example now links to codepen. * push documentation moved to docs/prototype.push.md. Added syntax highlighting. Updated to ES6. * Unshift documentation moved to docs/prototype.unshift.md. Examples link to codepen. Syntax highlighting. Updated to ES6. * removed empty comment block. * pop documentation moved to docs/prototype.pop.md. Examples have syntax highlighting, are Codepenable and in ES6 syntax. * shift documentation was moved to docs/prototype.shift.md. Example links to codepen, has syntax highlighting and uses ES6 syntax. * map documentation moved to docs/prototype.map.md. Example is using es6 syntax and linking to codepen. * removed empty codeblock * filter documentation moved to docs/prototype.filter.md. ES6 syntax highlighting, they're codepen-able. * removed empty codeblock * reduce documentation moved to docs/prototype.reduce.md. ES6 syntax and codepen-able. * reduceRight documentation moved to docs/prototype.reduceRight.md. Updated syntax to ES6, provided example for reduceRight. * documentation moved to docs/prototype.every.md. Updated syntax to ES6 added syntax highlighting. Links to codepen. * added imports to prototype.every.md examples * documentation moved to docs/prototype.some.md. ES6 syntax, highlighting and corrected the comments. * indexOf documentation moved to docs/prototype.indexOf.md. Synxax highlighting, ES6 syntax. * lastIndexOf documentation moved to docs/prototype.lastIndexOf. Added syntax highlighting and updated to ES6. changed IndexOf and lastIndexOf to double quotes to match the rest of the examples. * join documentation moved to docs/prototype.join.md added syntax highlighting and es6. It's codepenable. * reverse documentaiton moved to docs/prototype.reverse.md added syntax highlighting and es6. It's codepenable. * removed semicolon from comments * slice documentation has been moved to docs/prototype.slice.md. ES6 syntax and highlighting added. Examples are linked to codepen. * concat documentation moved to docs/prototype.concat.md. Added syntax highlighting and ES6. Removed extra parenthesis from example. * removed empty block comment * forEach documentation moved to docs/prototype.forEach.md. Fixed example where it functions properly. ES6 and highlighted syntax. Links to codepen. * replace documentation moved to docs/prototype.replace.md. examples are highlighted and using ES6 syntax. It's codepenable. * sort documentation moved to docs/prototype.sort.md. Examples are highlighted and ES6. It's codepenable. Updated example to better relate to similarities across the documentation. * Codepenable docs in define-list.md, updated to es6 syntax. * fixes to assign * up to concat tweeks * removed unneeded @body tag * linting * Fixed spacing across all prototype files * Updated to ES6 syntax, Added semi-colons. * fixed spelling error. * Updated spacing for most examples to match some sort of cohesive style. * changed quote to apostrophe * removed redundant example. * Added another example showing that justin object is mutated. * updated events.propertyName.md example. * example's style is now closer to the rest. * Added syntax highlighting. * Updated indexOf docs to note that it returns the index position of the item given * Added an example if forEach returns false. * changed reduce to reduce right. * fixed spacing issues in prototype.concat.md --- list/docs/define-list.md | 33 +- list/docs/events.add.md | 10 +- list/docs/events.length.md | 14 +- list/docs/events.propertyName.md | 24 +- list/docs/prototype.assign.md | 37 ++ list/docs/prototype.assignDeep.md | 38 ++ list/docs/prototype.concat.md | 31 + list/docs/prototype.every.md | 57 ++ list/docs/prototype.filter.md | 52 ++ list/docs/prototype.forEach.md | 53 ++ list/docs/prototype.get.md | 64 ++ list/docs/prototype.indexOf.md | 21 + list/docs/prototype.join.md | 21 + list/docs/prototype.lastIndexOf.md | 21 + list/docs/prototype.map.md | 36 ++ list/docs/prototype.pop.md | 46 ++ list/docs/prototype.push.md | 47 ++ list/docs/prototype.reduce.md | 41 ++ list/docs/prototype.reduceRight.md | 41 ++ list/docs/prototype.replace.md | 31 + list/docs/prototype.reverse.md | 20 + list/docs/prototype.serialize.md | 23 + list/docs/prototype.set.md | 73 +++ list/docs/prototype.shift.md | 36 ++ list/docs/prototype.slice.md | 41 ++ list/docs/prototype.some.md | 56 ++ list/docs/prototype.sort.md | 49 ++ list/docs/prototype.splice.md | 45 ++ list/docs/prototype.unshift.md | 48 ++ list/docs/prototype.update.md | 40 ++ list/docs/prototype.updateDeep.md | 46 ++ list/list.js | 942 ----------------------------- test/test-list-and-map.js | 16 + 33 files changed, 1179 insertions(+), 974 deletions(-) create mode 100644 list/docs/prototype.assign.md create mode 100644 list/docs/prototype.assignDeep.md create mode 100644 list/docs/prototype.concat.md create mode 100644 list/docs/prototype.every.md create mode 100644 list/docs/prototype.filter.md create mode 100644 list/docs/prototype.forEach.md create mode 100644 list/docs/prototype.get.md create mode 100644 list/docs/prototype.indexOf.md create mode 100644 list/docs/prototype.join.md create mode 100644 list/docs/prototype.lastIndexOf.md create mode 100644 list/docs/prototype.map.md create mode 100644 list/docs/prototype.pop.md create mode 100644 list/docs/prototype.push.md create mode 100644 list/docs/prototype.reduce.md create mode 100644 list/docs/prototype.reduceRight.md create mode 100644 list/docs/prototype.replace.md create mode 100644 list/docs/prototype.reverse.md create mode 100644 list/docs/prototype.serialize.md create mode 100644 list/docs/prototype.set.md create mode 100644 list/docs/prototype.shift.md create mode 100644 list/docs/prototype.slice.md create mode 100644 list/docs/prototype.some.md create mode 100644 list/docs/prototype.sort.md create mode 100644 list/docs/prototype.splice.md create mode 100644 list/docs/prototype.unshift.md create mode 100644 list/docs/prototype.update.md create mode 100644 list/docs/prototype.updateDeep.md diff --git a/list/docs/define-list.md b/list/docs/define-list.md index dad59fc..758f19e 100644 --- a/list/docs/define-list.md +++ b/list/docs/define-list.md @@ -60,7 +60,7 @@ Example: ```js const MyList = DefineList.extend( { "#": "string" } ); -canReflect.onInstancePatches( MyList, function( instance, patches ) { +canReflect.onInstancePatches( MyList, ( instance, patches ) => { } ); ``` @@ -71,33 +71,43 @@ The `can-define/list/list` module exports a `DefineList` constructor function. with `new` to create observable lists that behave very similar to `Array`s. For example: ```js +import { DefineList } from "can"; const list = new DefineList( [ "a", "b", "c" ] ); -list[ 0 ]; //-> "a"; +console.log(list[ 0 ]); //-> "a"; list.push( "x" ); -list.pop(); //-> "x" +console.log(list.pop()); //-> "x" ``` +@codepen It can also be extended to define custom observable list types with [can-define/list/list.extend]. For example, the following defines a `StringList` type where every item is converted to a string by specifying the [can-define/list/list.prototype.wildcardItems items definition] `(#)`: ```js +import { DefineList } from "can"; const StringList = DefineList.extend( { "#": "string" } ); const strings = new StringList( [ 1, new Date( 1475370478173 ), false ] ); -strings[ 0 ]; //-> "1" -strings[ 1 ]; //-> "Sat Oct 01 2016 20:07:58 GMT-0500 (CDT)" -strings[ 2 ]; //-> "false" +console.log(strings[ 0 ]); //-> "1" +console.log(strings[ 1 ]); //-> "Sat Oct 01 2016 20:07:58 GMT-0500 (CDT)" +console.log(strings[ 2 ]); //-> "false" ``` +@codepen Non-numeric properties can also be defined on custom DefineList type. The following defines a `completed` property that returns the completed todos: ```js +import { DefineList, DefineMap } from "can"; + +const Todo = DefineMap.extend("Todo", { + complete: { type: "boolean", default: false }, +}); + const TodoList = DefineList.extend( { "#": Todo, get completed() { @@ -106,8 +116,9 @@ const TodoList = DefineList.extend( { } ); const todos = new TodoList( [ { complete: true }, { complete: false } ] ); -todos.completed.length; //-> 1 +console.log(todos.completed.length); //-> 1 ``` +@codepen Finally, DefineList instances are observable, so you can use the [can-event-queue/map/map] methods to listen to its [can-define/list/list/AddEvent], @@ -115,13 +126,14 @@ methods to listen to its [can-define/list/list/AddEvent], and [can-define/list/list/PropertyNameEvent] events: ```js +import { DefineList } from "can"; const people = new DefineList( [ "alice", "bob", "eve" ] ); -people.on( "add", function( ev, items, index ) { +people.on( "add", ( ev, items, index ) => { console.log( "add", items, index ); -} ).on( "remove", function( ev, items, index ) { +} ).on( "remove", ( ev, items, index ) => { console.log( "remove", items, index ); -} ).on( "length", function( ev, newVal, oldVal ) { +} ).on( "length", ( ev, newVal, oldVal ) => { console.log( "length", newVal, oldVal ); } ); @@ -131,6 +143,7 @@ people.pop(); // remove ["eve"] 2 people.unshift( "Xerxes" ); // add ["Xerxes"] 1 // length 3 2 ``` +@codepen __NOTE:__ Only changes made to indexed values using the list's `set` method will dispatch change events. 👍 `defineList.set(0, 'newValue'); // will dispatch event` diff --git a/list/docs/events.add.md b/list/docs/events.add.md index eb0fc95..d6d4f16 100644 --- a/list/docs/events.add.md +++ b/list/docs/events.add.md @@ -5,12 +5,12 @@ Event fired when items are added to the list. @signature `handler(event, added, index)` -Handlers registered with [can-event-queue/map/map] methods on `list` will be called back when -items are added to a list. + Handlers registered with [can-event-queue/map/map] methods on `list` will be called back when + items are added to a list. -``` -list.on("add", function(event, added, index){ ... }); -``` + ```js + list.on("add", function(event, added, index){ ... }); + ``` @param {Event} event An event object. @param {Array} added An array of the items added to the list. diff --git a/list/docs/events.length.md b/list/docs/events.length.md index 362c3cb..15d586b 100644 --- a/list/docs/events.length.md +++ b/list/docs/events.length.md @@ -5,15 +5,15 @@ Event fired when items are added or removed from the list. @signature `handler(event, length)` -Handlers registered on "length" events will be called -back as follows. + Handlers registered on "length" events will be called + back as follows. -``` -list.on("length", function(event, length){ ... }); -``` + ```js + list.on("length", function(event, length){ ... }); + ``` -It's possible that the length was not changed, but an item was [can-define/list/list::set] on the list. -In this case, a `length` event will still be fired. + It's possible that the length was not changed, but an item was [can-define/list/list::set] on the list. + In this case, a `length` event will still be fired. @param {Event} event An event object. @param {Number} length The new length of the list. diff --git a/list/docs/events.propertyName.md b/list/docs/events.propertyName.md index cff51ae..0f3d874 100644 --- a/list/docs/events.propertyName.md +++ b/list/docs/events.propertyName.md @@ -5,18 +5,22 @@ Event fired when a property on the list changes values. @signature `handler(event, newValue, oldValue)` -Handlers registered on `propertyName` events will be called -back as follows. + Handlers registered on `propertyName` events will be called + back as follows. -``` -list.set("totalCount", 500); -list.on("totalCount", function(event, newVal, oldVal){ - newVal //-> 5 - oldVal //-> 500 -}); -list.set("totalCount", 5); -``` + ```js + import {DefineList} from "can"; + const list = new DefineList(); + list.set("totalCount", 500); + + list.on("totalCount", (event, newVal, oldVal) => { + console.log(newVal); //-> 5 + console.log(oldVal); //-> 500 + }); + list.set("totalCount", 5); + ``` + @codepen @param {Event} event An event object. @param {*} newVal The new value of the `propertyName` property. diff --git a/list/docs/prototype.assign.md b/list/docs/prototype.assign.md new file mode 100644 index 0000000..4447950 --- /dev/null +++ b/list/docs/prototype.assign.md @@ -0,0 +1,37 @@ +@function can-define/list/list.prototype.assign assign +@parent can-define/list/list.prototype + +Sets values within a list or properties on a list. + +@signature `list.assign(newItems)` + + If `newItems` [can-reflect.isListLike is list like] the values in `newItems` will replace the indexed value in the `list`. For example: + + ```js + import { DefineList } from "can"; + + const list = new DefineList(["A","B"]); + + list.assign( ["a"] ); + console.log( list.serialize() ); //-> ["a","B"] + ``` + @codepen + + > NOTICE: `.assign()` will not remove properties in the list that have indexes + greater than or equal to the `newItem`'s length. Use [can-define/list/list.prototype.update .update()] to replace all of a list's values. + + If `newItems` is an object, the object's properties will be added as properties to + the `list`. For example: + + ```js + import { DefineList } from "can"; + + const list = new DefineList(["A","B"]); + + list.assign( {count: 1000, skip: 2} ); + console.log( list.count ); //-> 1000 + ``` + @codepen + + @param {Array|Object} newItems A list or array of values, or an object of properties. + @return {can-define/list/list} The list instance. diff --git a/list/docs/prototype.assignDeep.md b/list/docs/prototype.assignDeep.md new file mode 100644 index 0000000..acbc968 --- /dev/null +++ b/list/docs/prototype.assignDeep.md @@ -0,0 +1,38 @@ +@function can-define/list/list.prototype.assignDeep assignDeep +@parent can-define/list/list.prototype + +Recursively sets values within a list or properties on a list. + +@signature `list.assignDeep(newItems)` + + Similar to [can-define/list/list.prototype.assign .assign()], `.assignDeep()` will + overwrite values within `list` with values from `newItems`. Where `assign()` will replace + values or properties one level deep, `.assignDeep()` will overwrite values or + properties on objects and lists recursively. + + For example, the following only assigns `justin`'s `age` to 36: + + ```js + import { DefineMap, DefineList } from "can"; + + const justin = new DefineMap({name: "Justin", age: 35}), + payal = new DefineMap({name: "Payal", age: 35}); + + const people = new DefineList([justin, payal]); + + people.assignDeep([ + {age: 36} + ]); + + console.log(people.serialize()) //-> [ + // {name: "Justin", age: 36}, + // {name: "Payal", age: 35} + // ] + ``` + @codepen + + + @param {Array|Object} newItems A list or array of values, or an object of property values. + If an object is passed, the properties of the list will be assigned with the values + in `newItems`. + @return {can-define/list/list} The list instance. diff --git a/list/docs/prototype.concat.md b/list/docs/prototype.concat.md new file mode 100644 index 0000000..58ca8d1 --- /dev/null +++ b/list/docs/prototype.concat.md @@ -0,0 +1,31 @@ +@function can-define/list/list.prototype.concat concat +@parent can-define/list/list.prototype + +@description Merge many collections together into a DefineList. +@signature `list.concat(...listN)` + + Returns a `DefineList` with the `list`'s items merged with the Arrays and lists + passed as arguments. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["a","b"]); + + const result = list.concat( + [1,2], + new DefineList(["X","Y"]), + {value: "Z"} + ); + + console.log( result.serialize() ); + //-> ["a", "b", 1, 2, "X", "Y", {value: "Z"}] + ``` + @codepen + + @param {Array|can-define/list/list|} listN Any number of arrays, Lists, or values to add in + For each parameter given, if it is an Array or a DefineList, each of its elements will be added to + the end of the concatenated DefineList. Otherwise, the parameter itself will be added. + + @return {can-define/list/list} A DefineList of the same type. + diff --git a/list/docs/prototype.every.md b/list/docs/prototype.every.md new file mode 100644 index 0000000..44606e1 --- /dev/null +++ b/list/docs/prototype.every.md @@ -0,0 +1,57 @@ +@function can-define/list/list.prototype.every every +@parent can-define/list/list.prototype + +Return true if every item in a list matches a predicate. + +@signature `list.every( callback [,thisArg] )` + + Tests each item in `list` by calling `callback` on it. If `callback` returns truthy for every + element in `list`, `every` returns `true`. + + ```js + import { DefineList } from "can"; + + const names = new DefineList(["alice","adam","zack","zeffer"]); + + const aNames = names.every((name) => { + return name[0] === "a"; + }); + + console.log(aNames); //-> false + ``` + @codepen + + @param {function(*, Number, can-define/list/list)} callback(item, index, list) A + function to call with each element of the DefineList. The three parameters that callback gets passed are: + - item (*) - the element at index. + - index (Integer) - the index of the current element of the list. + - list (DefineList) - the `DefineList` the elements are coming from. + + If `callback` returns a truthy result, `every` will evaluate the callback on the next element. Otherwise, `every` + will return `false`. + + @param {Object} thisArg What `this` should be in the `callback`. + @return {Boolean} `true` if calling the callback on every element in `list` returns a truthy value, `false` otherwise. + +@signature `list.every( props )` + + Tests each item in `list` by comparing its properties to `props`. If `props` match for every element in + `list`, `every` returns `true`. + + ```js + import {DefineList} from "can"; + + const todos = new DefineList([ + {name: "dishes", complete: false}, + {name: "lawn", complete: true} + ]); + + const complete = todos.every({complete: true}); + + console.log(complete); //-> false + ``` + @codepen + + @param {Object} props An object of key-value properties. Each key and value in + `props` must be present on an `item` for the `item` to match. + @return {Boolean} `true` if every element in `list` matches `props`, `false` otherwise. diff --git a/list/docs/prototype.filter.md b/list/docs/prototype.filter.md new file mode 100644 index 0000000..abcf30d --- /dev/null +++ b/list/docs/prototype.filter.md @@ -0,0 +1,52 @@ +@function can-define/list/list.prototype.filter filter +@parent can-define/list/list.prototype + +Filter a list to a new list of the matched items. + +@signature `list.filter( callback [,thisArg] )` + + Filters `list` based on the return value of `callback`. + + ```js + import{DefineList} from "can"; + + const names = new DefineList(["alice","adam","zack","zeffer"]); + + const aNames = names.filter((name) => { + return name[0] === "a"; + }); + + console.log(aNames.get()); //-> ["alice","adam"] + ``` + @codepen + + @param {function(*, Number, can-define/list/list)} callback(item, index, list) A + function to call with each element of the DefineList. The three parameters that callback gets passed are: + - item (*) - the element at index. + - index (Integer) - the index of the current element of the list. + - list (DefineList) - the `DefineList` the elements are coming from. + + If `callback` returns a truthy result, `item` will be added to the result. Otherwise, the `item` will be + excluded. + + @param {Object} thisArg What `this` should be in the `callback`. + @return {can-define/list/list} A new instance of this `DefineList` (may be a subclass), containing the items that passed the filter. + +@signature `list.filter( props )` + + Filters items in `list` based on the property values in `props`. + + ```js + import { DefineList } from "can"; + const todos = new DefineList([ + {name: "dishes", complete: false}, + {name: "lawn", complete: true} + ]); + const complete = todos.filter({complete: true}); + console.log(complete.get()); //-> [{name: "lawn", complete: true}] + ``` + @codepen + + @param {Object} props An object of key-value properties. Each key and value in + `props` must be present on an `item` for the `item` to be in the returned list. + @return {can-define/list/list} A new `DefineList` of the same type. diff --git a/list/docs/prototype.forEach.md b/list/docs/prototype.forEach.md new file mode 100644 index 0000000..e46e776 --- /dev/null +++ b/list/docs/prototype.forEach.md @@ -0,0 +1,53 @@ +@function can-define/list/list.prototype.forEach forEach +@parent can-define/list/list.prototype + +@description Call a function for each element of a DefineList. +@signature `list.forEach(callback[, thisArg])` + + Loops through the values of the list, calling `callback` for each value until the list ends + or `false` is returned. + + ```js + import {DefineList} from "can"; + + const list = new DefineList([1, 2, 3]); + + list.forEach((element, index, list) => { + list.set(index, element * element); + }); + + console.log(list.get()); //-> [1, 4, 9] + ``` + @codepen + + @param {function(item, index, list)} callback A function to call with each element of the DefineList. + The three parameters that callback gets passed are: + - item - the element at index. + - index - the current element of the list. + - list - the DefineList the elements are coming from. + + If the callback returns `false` the looping stops. + + @param {Object} [thisArg] The object to use as `this` inside the callback. + @return {can-define/list/list} The list instance. +@body + +## Use + +If `false` is returned by the callback the `forEach` loop would exit. + +```js +import {DefineList} from "can"; + +const list = new DefineList([1, 2, 3, 4, 5]); + +list.forEach((element, index, list) => { + if (index === 2) { + return false; + } + list.set(index, `index: ${index}`); +}); + +console.log(list.get()); //-> ["index: 0", "index: 1", 3, 4, 5] +``` +@codepen diff --git a/list/docs/prototype.get.md b/list/docs/prototype.get.md new file mode 100644 index 0000000..8cc4cc3 --- /dev/null +++ b/list/docs/prototype.get.md @@ -0,0 +1,64 @@ +@function can-define/list/list.prototype.get get +@parent can-define/list/list.prototype + +Gets an item or all items from a DefineList. + +@signature `list.get()` + + Returns the list converted into a plain JS array. Any items that also have a + `get` method will have their `get` method called and the resulting value will be used as item value. + + This can be used to recursively convert a list instance to an Array of other plain JavaScript objects. + Cycles are supported and only create one object. + + `get()` can still return other non-plain JS objects like Dates. + Use [can-define/map/map.prototype.serialize] when a form proper for `JSON.stringify` is needed. + + ```js + import { DefineList } from "can"; + const list = new DefineList(["A","B"]); + console.log(list.get()); //-> ["A","B"] + ``` + @codepen + + + @return {Array} A plain JavaScript `Array` that contains each item in the list. + +@signature `list.get(index)` + + Gets the item at `index`. `list.get(index)` should be used instead of + `list[index]` if the list's items are going to be updated via [can-define/list/list.prototype.set list.set(index, value)] + (as opposed to [can-define/list/list.prototype.splice] which is the better way). + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + + console.log(list.get(1)); //-> "B" + ``` + @codepen + + @param {Number} index A numeric position in the list. + + @return {*} The value at index. + +@signature `list.get(prop)` + + Gets the property at `prop` if it might not have already been defined. + + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + + list.set("count",1000); + + console.log(list.get("count")); //-> 1000 + ``` + @codepen + + @param {String} prop A property on the list. + + @return {*} The value at `prop`. \ No newline at end of file diff --git a/list/docs/prototype.indexOf.md b/list/docs/prototype.indexOf.md new file mode 100644 index 0000000..5def740 --- /dev/null +++ b/list/docs/prototype.indexOf.md @@ -0,0 +1,21 @@ +@function can-define/list/list.prototype.indexOf indexOf +@parent can-define/list/list.prototype + +@description Look for an item in a DefineList. +@signature `list.indexOf(item)` + + `indexOf` finds the first index position of a given item in the DefineList. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["Alice", "Bob", "Eve"]); + + console.log(list.indexOf("Alice")); //-> 0 + console.log(list.indexOf("Charlie")); //-> -1 + ``` + @codepen + + @param {*} item The item to find. + + @return {Number} The index of the item in the DefineList, or -1 if the item is not found. diff --git a/list/docs/prototype.join.md b/list/docs/prototype.join.md new file mode 100644 index 0000000..76f3699 --- /dev/null +++ b/list/docs/prototype.join.md @@ -0,0 +1,21 @@ +@function can-define/list/list.prototype.join join +@parent can-define/list/list.prototype + +@description Join a DefineList's elements into a string. +@signature `list.join(separator)` + + `join` turns a DefineList into a string by inserting _separator_ between the string representations + of all the elements of the DefineList. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["Alice", "Bob", "Eve"]); + + console.log(list.join(", ")); //-> "Alice, Bob, Eve" + ``` + @codepen + + @param {String} separator The string to separate elements. + + @return {String} The joined string. diff --git a/list/docs/prototype.lastIndexOf.md b/list/docs/prototype.lastIndexOf.md new file mode 100644 index 0000000..c49b86b --- /dev/null +++ b/list/docs/prototype.lastIndexOf.md @@ -0,0 +1,21 @@ +@function can-define/list/list.prototype.lastIndexOf lastIndexOf +@parent can-define/list/list.prototype + +@description Look for an item in a DefineList starting from the end. +@signature `list.lastIndexOf(item)` + + `lastIndexOf` finds the last position of a given item in the DefineList. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["Alice", "Bob", "Alice", "Eve"]); + + console.log(list.lastIndexOf("Alice")); //-> 2 + console.log(list.lastIndexOf("Charlie")); //-> -1 + ``` + @codepen + + @param {*} item The item to find. + + @return {Number} The position of the item in the DefineList, or -1 if the item is not found. diff --git a/list/docs/prototype.map.md b/list/docs/prototype.map.md new file mode 100644 index 0000000..5711126 --- /dev/null +++ b/list/docs/prototype.map.md @@ -0,0 +1,36 @@ +@function can-define/list/list.prototype.map map +@parent can-define/list/list.prototype + +@description Map the values in this list to another list. + +@signature `list.map(callback[, thisArg])` + + Loops through the values of the list, calling `callback` for each one until the list + ends. The return values of `callback` are used to populate the returned list. + + ```js + import {DefineList} from "can"; + + const todos = new DefineList([ + {name: "dishes", complete: false}, + {name: "lawn", complete: true} + ]); + + const names = todos.map((todo) => { + return todo.name; + }); + + console.log(names.get()); //-> ["dishes","lawn"] + ``` + @codepen + + @param {function(item, index, list)} callback A function to call with each element of the DefineList. + The three parameters that callback gets passed are: + - item (*) - the element at index. + - index (Integer) - the index of the current element of the list. + - list (DefineList) - the `DefineList` the elements are coming from. + + The return value of `callback`, including `undefined` values are used to populate the resulting list. + + @param {Object} [thisArg] The object to use as `this` inside the callback. + @return {can-define/list/list} a new `DefineList` with the results of the map transform. diff --git a/list/docs/prototype.pop.md b/list/docs/prototype.pop.md new file mode 100644 index 0000000..342efe4 --- /dev/null +++ b/list/docs/prototype.pop.md @@ -0,0 +1,46 @@ +@function can-define/list/list.prototype.pop pop +@parent can-define/list/list.prototype + +@description Remove an element from the end of a DefineList. +@signature `list.pop()` + + `pop` removes an element from the end of a DefineList. + + ```js + import { DefineList } from "can"; + + const names = new DefineList(['Alice', 'Bob', 'Eve']); + + console.log(names.pop()); //-> 'Eve' + ``` + @codepen + + @return {*} The element just popped off the DefineList, or `undefined` if the DefineList was empty + +@body + +## Use + +`pop` is the opposite action from [can-define/list/list::push push]: + +```js +import {DefineList} from "can"; + +const list = new DefineList(['Alice', 'Bob', 'Eve']); + +console.log(list.pop()); //-> 'Eve' +console.log(list.pop()); //-> 'Bob' +console.log(list.pop()); //-> 'Alice' +console.log(list.pop()); //-> undefined +``` +@codepen + +## Events + +`pop` causes _remove_ and _length_ events to be fired if the DefineList is not empty +when it is called. + +## See also + +`pop` has its counterpart in [can-define/list/list::push push], or you may be +looking for [can-define/list/list::unshift unshift] and its counterpart [can-define/list/list::shift shift]. diff --git a/list/docs/prototype.push.md b/list/docs/prototype.push.md new file mode 100644 index 0000000..3cd4996 --- /dev/null +++ b/list/docs/prototype.push.md @@ -0,0 +1,47 @@ +@function can-define/list/list.prototype.push push +@parent can-define/list/list.prototype + +@description Add elements to the end of a list. +@signature `list.push(...elements)` + + `push` adds elements onto the end of a DefineList. + + ```js + import { DefineList } from "can"; + + const names = new DefineList(['Alice']); + names.push('Bob', 'Eve'); + + console.log(names.get()); //-> ['Alice','Bob', 'Eve'] + ``` + @codepen + + @param {*} elements the elements to add to the DefineList + + @return {Number} the new length of the DefineList + +@body + +## Use + +If you have an array you want to concatenate to the end +of the DefineList, you can use `apply`: + +```js +import {DefineList} from "can"; +const names = ['Bob', 'Eve']; +const list = new DefineList(['Alice']); + +list.push.apply(list, names); +console.log(list.get()); // ['Alice', 'Bob', 'Eve'] +``` +@codepen + +## Events + +`push` causes _add_, and _length_ events to be fired. + +## See also + +`push` has a counterpart in [can-define/list/list::pop pop], or you may be +looking for [can-define/list/list::unshift unshift] and its counterpart [can-define/list/list::shift shift]. diff --git a/list/docs/prototype.reduce.md b/list/docs/prototype.reduce.md new file mode 100644 index 0000000..7ae7f81 --- /dev/null +++ b/list/docs/prototype.reduce.md @@ -0,0 +1,41 @@ +@function can-define/list/list.prototype.reduce reduce +@parent can-define/list/list.prototype + +@description Map the values in this list to a single value + +@signature `list.reduce(callback, initialValue, [, thisArg])` + + Loops through the values of the list, calling `callback` for each one until the list + ends. The return value of `callback` is passed to the next iteration as the first argument, + and finally returned by `reduce`. + + ```js + import {DefineList} from "can"; + + const todos = new DefineList([ + {name: "dishes", complete: false}, + {name: "lawn", complete: true} + ]); + + const todosAsOneObject = todos.reduce((todos, todo) => { + todos[todo.name] = todo.complete; + return todos; + }, {}); + + console.log(todosAsOneObject); //-> { dishes: false, lawn: true } + ``` + @codepen + + @param {function(item, index, list)} callback A function to call with each element of the DefineList. + The four parameters that callback gets passed are: + - current (*) - the current aggregate value of reducing over the list -- the initial value if the first iteration + - item (*) - the element at index. + - index (Integer) - the index of the current element of the list. + - list (DefineList) - the `DefineList` the elements are coming from. + + The return value of `callback` is passed to the next iteration as the first argument, and returned from + `reduce` if the last iteration. + + @param {*} [initialValue] The initial value to use as `current` in the first iteration + @param {Object} [thisArg] The object to use as `this` inside the callback. + @return {*} The result of the final call of `callback` on the list. diff --git a/list/docs/prototype.reduceRight.md b/list/docs/prototype.reduceRight.md new file mode 100644 index 0000000..4c37303 --- /dev/null +++ b/list/docs/prototype.reduceRight.md @@ -0,0 +1,41 @@ +@function can-define/list/list.prototype.reduceRight reduceRight +@parent can-define/list/list.prototype + +@description Map the values in this list to a single value from right to left + +@signature `list.reduceRight(callback, initialValue, [, thisArg])` + + Loops through the values of the list in reverse order, calling `callback` for each one until the list + ends. The return value of `callback` is passed to the next iteration as the first argument, + and finally returned by `reduceRight`. + + ```js + import {DefineList} from "can"; + + const todos = new DefineList([ + {name: "dishes", complete: false}, + {name: "lawn", complete: true} + ]); + + const todosAsOneObject = todos.reduceRight((todos, todo) => { + todos.push([todo.name, todo.complete]); + return todos; + }, []); + + console.log(todosAsOneObject); //-> [["lawn", true], ["dishes", false]] + ``` + @codepen + + @param {function(item, index, list)} callback A function to call with each element of the DefineList. + The four parameters that callback gets passed are: + - current (*) - the current aggregate value of reducing over the list -- the initial value if the first iteration + - item (*) - the element at index. + - index (Integer) - the index of the current element of the list. + - list (DefineList) - the `DefineList` the elements are coming from. + + The return value of `callback` is passed to the next iteration as the first argument, and returned from + `reduceRight` if the last iteration. + + @param {*} [initialValue] The initial value to use as `current` in the first iteration + @param {Object} [thisArg] The object to use as `this` inside the callback. + @return {*} The result of the final call of `callback` on the list. diff --git a/list/docs/prototype.replace.md b/list/docs/prototype.replace.md new file mode 100644 index 0000000..3bfb6b3 --- /dev/null +++ b/list/docs/prototype.replace.md @@ -0,0 +1,31 @@ +@function can-define/list/list.prototype.replace replace +@parent can-define/list/list.prototype +@hide + +@description Replace all the elements of a DefineList. +@signature `list.replace(collection)` + + Replaces every item in the list with `collection`. + + ```js + import {DefineList} from "can"; + + const names = new DefineList(["alice","adam","eve"]); + names.replace(["Justin","Xena"]); + + console.log(names.get()); //-> ["Justin","Xena"] + ``` + @codepen + + @param {Array|can-define/list/list} collection The collection of items that will be in `list`. + @return {can-define/list/list} Returns the `list`. + +@body + +## Use + +`replace` is essentially a shortcut for [can-define/list/list.prototype.splice]. + +## Events + +`replace` causes _remove_, _add_, and _length_ events. diff --git a/list/docs/prototype.reverse.md b/list/docs/prototype.reverse.md new file mode 100644 index 0000000..e4329be --- /dev/null +++ b/list/docs/prototype.reverse.md @@ -0,0 +1,20 @@ +@function can-define/list/list.prototype.reverse reverse +@parent can-define/list/list.prototype + +@description Reverse the order of a DefineList. +@signature `list.reverse()` + + Reverses the elements of the DefineList in place. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["Alice", "Bob", "Eve"]); + const reversedList = list.reverse(); + + console.log(reversedList.get()); //-> ["Eve", "Bob", "Alice"] + console.log(list === reversedList); //-> true + ``` + @codepen + + @return {can-define/list/list} The DefineList, for chaining. diff --git a/list/docs/prototype.serialize.md b/list/docs/prototype.serialize.md new file mode 100644 index 0000000..bbc940c --- /dev/null +++ b/list/docs/prototype.serialize.md @@ -0,0 +1,23 @@ +@function can-define/list/list.prototype.serialize serialize +@parent can-define/list/list.prototype + +Returns the a serialized version of this list. + +@signature `list.serialize()` + + Goes through each item in the list and gets its serialized + value and returns them in a plain Array. + + Each items serialized value is the result of calling [can-reflect.serialize canReflect.serialize()] on the item. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["first", {foo: "bar"}]); + const serializedList = list.serialize(); + + console.log(serializedList); //-> ["first", {foo: "bar"}] + ``` + @codepen + + @return {Array} An array with each item's serialized value. diff --git a/list/docs/prototype.set.md b/list/docs/prototype.set.md new file mode 100644 index 0000000..ffeff89 --- /dev/null +++ b/list/docs/prototype.set.md @@ -0,0 +1,73 @@ +@function can-define/list/list.prototype.set set +@parent can-define/list/list.prototype + +@description Sets an item or property or items or properties on a list. + +@signature `list.set(index, value)` + + Sets the item at `index`. Typically, [can-define/list/list::splice] should be used instead. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + list.set(2,"C"); + + console.log(list[2]); //-> "C" + ``` + @codepen + + Splice should be used because it will trigger a [can-define/list/list/LengthEvent] + event. If you are using `.set(index, value)`, you should make sure to use `.get(index)` + when reading values from the array. If you use `.splice()`, you can use `list[index]` + to read values from the array. + + @param {Number} index A numeric position in the list. + @param {*} value The value to add to the list. + @return {can-define/list/list} The list instance. + + +@signature `list.set(prop, value)` + +Sets the property at `prop`. This should be used when the property + isn't already defined. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + list.set("count",1000); + + console.log(list.get("count")); //-> 1000 + ``` + @codepen + + @param {Number} prop A property name. + @param {} value The value to add to the list. + @return {can-define/list/list} The list instance. + +@signature `list.set(newProps)` + +
+
+

Deprecated 3.10.1

+
+

Passing an {Object} to .set has been deprecated in favor of assign or update. list.set(index, value) is not deprecated.

+
+
+
+ + Updates the properties on the list with `newProps`. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + list.set({count: 1000, skip: 2}); + + console.log(list.get("count")); //-> 1000 + ``` + @codepen + + @param {Object} newProps An object of properties and values to set on the list. + @return {can-define/list/list} The list instance. diff --git a/list/docs/prototype.shift.md b/list/docs/prototype.shift.md new file mode 100644 index 0000000..f118fc4 --- /dev/null +++ b/list/docs/prototype.shift.md @@ -0,0 +1,36 @@ +@function can-define/list/list.prototype.shift shift +@parent can-define/list/list.prototype + +@description Remove an item from the front of a list. +@signature `list.shift()` + + `shift` removes an element from the beginning of a DefineList. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(['Alice','Adam']); + + console.log(list.shift()); //-> 'Alice' + console.log(list.shift()); //-> 'Adam' + console.log(list.shift()); //-> undefined + ``` + @codepen + + @return {*} The element just shifted off the DefineList, or `undefined` if the DefineList is empty + +@body + +## Use + +`shift` is the opposite action from `[can-define/list/list::unshift unshift]`: + +## Events + +`pop` causes _remove_ and _length_ events to be fired if the DefineList is not empty +when it is called. + +## See also + +`shift` has a counterpart in [can-define/list/list::unshift unshift], or you may be +looking for [can-define/list/list::push push] and its counterpart [can-define/list/list::pop pop]. diff --git a/list/docs/prototype.slice.md b/list/docs/prototype.slice.md new file mode 100644 index 0000000..d631da8 --- /dev/null +++ b/list/docs/prototype.slice.md @@ -0,0 +1,41 @@ +@function can-define/list/list.prototype.slice slice +@parent can-define/list/list.prototype + +@description Make a copy of a part of a DefineList. +@signature `list.slice([start[, end]])` + + `slice` creates a copy of a portion of the DefineList. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["Alice", "Bob", "Charlie", "Daniel", "Eve"]); + const newList = list.slice(1, 4); + + console.log(newList.get()); //-> ["Bob", "Charlie", "Daniel"] + ``` + @codepen + + @param {Number} [start=0] The index to start copying from. Defaults to `0`. + + @param {Number} [end] The first index not to include in the copy + If _end_ is not supplied, `slice` will copy until the end of the list. + + @return {can-define/list/list} A new `DefineList` with the extracted elements. + +@body + +## Use + +`slice` is the simplest way to copy a DefineList: + +```js +import {DefineList} from "can"; + +const list = new DefineList(["Alice", "Bob", "Eve"]); +const copy = list.slice(); + +console.log(copy.get()); //-> ["Alice", "Bob", "Eve"] +console.log(list === copy); //-> false +``` +@codepen diff --git a/list/docs/prototype.some.md b/list/docs/prototype.some.md new file mode 100644 index 0000000..d25a063 --- /dev/null +++ b/list/docs/prototype.some.md @@ -0,0 +1,56 @@ +@function can-define/list/list.prototype.some some +@parent can-define/list/list.prototype + +Return true if at least one item in a list matches a predicate. + +@signature `list.some( callback [,thisArg] )` + + Tests each item in `list` by calling `callback` on it. If `callback` returns truthy for some element in + `list`, `some` returns `true`. + + ```js + import {DefineList} from "can"; + + const names = new DefineList(["alice","adam","zack","zeffer"]); + const aNames = names.some((name) => { + return name[0] === "a"; + }); + + console.log(aNames); //-> true + ``` + @codepen + + @param {function(*, Number, can-define/list/list)} callback(item, index, list) A + function to call with each element of the DefineList. The three parameters that callback gets passed are: + - item (*) - the element at index. + - index (Integer) - the index of the current element of the list. + - list (DefineList) - the DefineList the elements are coming from. + + If `callback` returns a falsy result, `some` will evaluate the callback on the next element. Otherwise, `some` + will return `true`. + + @param {Object} thisArg What `this` should be in the `callback`. + @return {Boolean} `false` if calling the callback on some element in `list` returns a falsy value, `true` otherwise. + +@signature `list.some( props )` + + Tests each item in `list` by comparing its properties to `props`. If `props` match for some element in + `list`, `some` returns `true`. + + ```js + import {DefineList} from "can"; + + const todos = new DefineList([ + {name: "dishes", complete: false}, + {name: "lawn", complete: true} + ]); + + const complete = todos.some({complete: true}); + + console.log(complete); //-> true + ``` + @codepen + + @param {Object} props An object of key-value properties. Each key and value in + `props` must be present on an `item` for the `item` to match. + @return {Boolean} `false` if every element in `list` fails to match `props`, `true` otherwise diff --git a/list/docs/prototype.sort.md b/list/docs/prototype.sort.md new file mode 100644 index 0000000..fcdcc5a --- /dev/null +++ b/list/docs/prototype.sort.md @@ -0,0 +1,49 @@ +@function can-define/list/list.prototype.sort sort +@parent can-define/list/list.prototype + +@description Sort the properties of a list. + +@signature `list.sort([compareFunction])` + + Sorts the elements of a list in place and returns the list. The API is the + same as the native JavaScript `Array.prototype.sort` API. + + ```js + import {DefineList} from "can"; + + const accounts = new DefineList([ + { name: "Savings", amount: 20.00 }, + { name: "Checking", amount: 103.24 }, + { name: "Kids Savings", amount: 48155.13 } + ]); + + accounts.sort((a, b) => { + if (a.name < b.name) { + return -1; + } else if (a.name > b.name){ + return 1; + } else { + return 0; + } + }); + + console.log(accounts[0].name); //-> "Checking" + console.log(accounts[1].name); //-> "Kids Savings" + console.log(accounts[2].name); //-> "Savings" + ``` + @codepen + + @param {function(a, b)} compareFunction Specifies a function that defines the sort order. + + If `compareFunction` is supplied, the list elements are sorted according to the return + value of the compare function. If `a` and `b` are two elements being compared, then: + + - If `compareFunction(a, b)` returns a value less than 0, `a` will be sorted to + a lower index than `b`, so `a` will now come first. + - If `compareFunction(a, b)` returns 0, the order of the two values will not be changed. + - If `compareFunction(a, b)` returns a value greater than 0, `a` will be sorted to + a higher index than `b`, so `b` will now come first. + + @return {can-define/list/list} The list instance. +@body +``` diff --git a/list/docs/prototype.splice.md b/list/docs/prototype.splice.md new file mode 100644 index 0000000..ab87693 --- /dev/null +++ b/list/docs/prototype.splice.md @@ -0,0 +1,45 @@ +@function can-define/list/list.prototype.splice splice +@parent can-define/list/list.prototype + +@parent can-define/list/list.prototype +@description Insert and remove elements from a DefineList. +@signature `list.splice(index[, howMany[, ...newItems]])` + + Removes `howMany` items at `index` and adds `newItems` in their place. + + @param {Number} index Where to start removing or inserting elements. + + @param {Number} [howMany] The number of elements to remove + If _howMany_ is not provided, `splice` will remove all elements from `index` to the end of the DefineList. + + @param {*} newItems Items to insert into the DefineList + + @return {Array} The elements removed by `splice`. + +@body + +## Use + +`splice` lets you remove elements from and insert elements into a DefineList. + +This example demonstrates how to do surgery on a list of numbers: + +```js +import {DefineList} from "can"; + +const list = new DefineList([0, 1, 2, 3]); + +// starting at index 2, remove one element and insert 'Alice' and 'Bob': +list.splice(2, 1, 'Alice', 'Bob'); +console.log(list.get()); //-> [0, 1, 'Alice', 'Bob', 3] +``` +@codepen + +## Events + +`splice` causes the DefineList it's called on to emit +_add_ events, _remove_ events, and _length_ events. If there are +any elements to remove, a _remove_ event, and a +_length_ event will be fired. If there are any elements to insert, a +separate _add_ event, and a separate _length_ event +will be fired. diff --git a/list/docs/prototype.unshift.md b/list/docs/prototype.unshift.md new file mode 100644 index 0000000..856cbc7 --- /dev/null +++ b/list/docs/prototype.unshift.md @@ -0,0 +1,48 @@ +@function can-define/list/list.prototype.unshift unshift +@parent can-define/list/list.prototype + +@description Add items to the beginning of a DefineList. +@signature `list.unshift(...items)` + + `unshift` adds items onto the beginning of a DefineList. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(['Alice']); + + list.unshift('Bob', 'Eve'); + console.log(list.get()); //-> ['Bob', 'Eve', 'Alice'] + ``` + @codepen + + @param {*} items The items to add to the DefineList. + + @return {Number} The new length of the DefineList. + +@body + +## Use + +If you have an array you want to concatenate to the beginning +of the DefineList, you can use `apply`: + +```js +import {DefineList} from "can"; + +const names = ['Bob', 'Eve']; +const list = new DefineList(['Alice']); + +list.unshift.apply(list, names); +console.log(list.get()); //-> ['Bob', 'Eve', 'Alice'] +``` +@codepen + +## Events + +`unshift` causes _add_ and _length_ events to be fired. + +## See also + +`unshift` has a counterpart in [can-define/list/list::shift shift], or you may be +looking for [can-define/list/list::push push] and its counterpart [can-define/list/list::pop pop]. diff --git a/list/docs/prototype.update.md b/list/docs/prototype.update.md new file mode 100644 index 0000000..d78d812 --- /dev/null +++ b/list/docs/prototype.update.md @@ -0,0 +1,40 @@ +@function can-define/list/list.prototype.update update +@parent can-define/list/list.prototype + +Updates a list with new values or new property values. + +@signature `list.update(newItems)` + + If `newItems` [can-reflect.isListLike is list like] the values in `newItems` will replace all values in `list`. For example: + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + + list.update( ["a"] ); + console.log( list.serialize() ); //-> ["a"] + ``` + @codepen + + If `newItems` is an object, `newItem`'s properties and values will be used to overwrite + `list`'s properties and values. Any enumerable properties on `list` that are + not in `newItems` will be removed. + + ```js + import {DefineList} from "can"; + + const list = new DefineList(["A","B"]); + + list.update( {count: 1000, skip: 2} ); + + list.update( {count: 99} ) + console.log( list.skip ); //-> undefined + ``` + @codepen + + > NOTE: Use [can-define/list/list.prototype.assign .assign()] to only add properties + from `newItems` and not delete missing items. + + @param {Array|Object} newItems A list or array of values, or an object of properties. + @return {can-define/list/list} The list instance. diff --git a/list/docs/prototype.updateDeep.md b/list/docs/prototype.updateDeep.md new file mode 100644 index 0000000..7637a5b --- /dev/null +++ b/list/docs/prototype.updateDeep.md @@ -0,0 +1,46 @@ +@function can-define/list/list.prototype.updateDeep updateDeep +@parent can-define/list/list.prototype + +Recursively updates a list with new values or new property values. + +@signature `list.updateDeep(newItems)` + + Similar to [can-define/list/list.prototype.update .update()], `.updateDeep()` will + overwrite values within `list` with values from `newItems`. Where `update()` will replace + values or properties one level deep, `.updateDeep()` will overwrite values or + properties on objects and lists recursively. + + The following will: + + - remove `payal` from `people`, + - set `justin`'s `name` to `"JUSTIN"`, and + - remove `justin`'s `age` property: + + ```js + import {DefineMap, DefineList} from "can"; + + const justin = new DefineMap({name: "Justin", age: 35}), + payal = new DefineMap({name: "Payal", age: 35}); + + const people = new DefineList([justin, payal]); + + people.updateDeep([ + {name: "JUSTIN"} + ]); + + console.log( justin.serialize(), payal.serialize() ); + //-> {name: "JUSTIN"}, {age: 35, name: "Payal"} + console.log( people.serialize() ) //-> [ + // {name: "JUSTIN"} + // ] + ``` + @codepen + + Use [can-define/list/list.prototype.assignDeep .assignDeep()] if you want recursive updating that doesn't remove properties. Use [can-diff/merge-deep/merge-deep] + if you want recursive updating that is [can-reflect.getIdentity identity] aware. + + + @param {Array|Object} newItems A list or array of values, or an object of property values. + If an object is passed, the properties of the list will be updated with the values + in `newItems`. + @return {can-define/list/list} The list instance. diff --git a/list/list.js b/list/list.js index ce421ba..b92c778 100644 --- a/list/list.js +++ b/list/list.js @@ -166,62 +166,7 @@ var DefineList = Construct.extend("DefineList", target: this }, [ newVal, oldVal ]); } - }, - /** - * @function can-define/list/list.prototype.get get - * @parent can-define/list/list.prototype - * - * Gets an item or all items from a DefineList. - * - * @signature `list.get()` - * - * Returns the list converted into a plain JS array. Any items that also have a - * `get` method will have their `get` method called and the resulting value will be used as item value. - * - * This can be used to recursively convert a list instance to an Array of other plain JavaScript objects. - * Cycles are supported and only create one object. - * - * `get()` can still return other non-plain JS objects like Dates. - * Use [can-define/map/map.prototype.serialize] when a form proper for `JSON.stringify` is needed. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.get() //-> ["A","B"] - * ``` - * - * @return {Array} A plain JavaScript `Array` that contains each item in the list. - * - * @signature `list.get(index)` - * - * Gets the item at `index`. `list.get(index)` should be used instead of - * `list[index]` if the list's items are going to be updated via [can-define/list/list.prototype.set list.set(index, value)] - * (as opposed to [can-define/list/list.prototype.splice] which is the better way). - * - * ```js - * var list = new DefineList(["A","B"]); - * list.get(1) //-> "B" - * ``` - * - * @param {Number} index A numeric position in the list. - * - * @return {*} The value at index. - * - * @signature `list.get(prop)` - * - * Gets the property at `prop` if it might not have already been defined. - * - * - * ```js - * var list = new DefineList(["A","B"]); - * list.set("count",1000) - * list.get("count") //-> 1000 - * ``` - * - * @param {String} prop A property on the list. - * - * @return {*} The value at `prop`. - */ get: function(index) { if (arguments.length) { if(isNaN(index)) { @@ -234,69 +179,6 @@ var DefineList = Construct.extend("DefineList", return canReflect.unwrap(this, Map); } }, - /** - * @function can-define/list/list.prototype.set set - * @parent can-define/list/list.prototype - * - * @deprecated {3.10.1} Using .set with {Object} `props` has been deprecated in favour of `assign` and `update` - * - * @description Sets an item or property or items or properties on a list. - * - * @signature `list.set(prop, value)` - * - * Sets the property at `prop`. This should be used when the property - * isn't already defined. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.set("count",1000); - * list.get("count") //-> 1000; - * ``` - * - * @param {Number} prop A property name. - * @param {*} value The value to add to the list. - * @return {can-define/list/list} The list instance. - * - * @signature `list.set(newProps)` - * - * Updates the properties on the list with `newProps`. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.set({count: 1000, skip: 2}); - * list.get("count") //-> 1000 - * ``` - * - * @param {Object} newProps An object of properties and values to set on the list. - * @return {can-define/list/list} The list instance. - * - * @signature `list.set(index, value)` - * - * Sets the item at `index`. Typically, [can-define/list/list::splice] should be used instead. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.set(2,"C"); - * ``` - * - * @param {Number} index A numeric position in the list. - * @param {*} value The value to add to the list. - * @return {can-define/list/list} The list instance. - * - * @signature `list.set(newItems [,replaceAll])` - * - * Replaces items in the list with `newItems` - * - * ```js - * var list = new DefineList(["A","B"]); - * list.set(["c"]) //-> DefineList["c","B"] - * list.set(["x"], true) //-> DefineList["x"] - * ``` - * - * @param {Array} newItems Items used to replace existing items in the list. - * @param {Boolean} [replaceAll] If true, will remove items at the end of the list. - * @return {can-define/list/list} The list instance. - */ set: function(prop, value) { // if we are setting a single value if (typeof prop !== "object") { @@ -343,24 +225,6 @@ var DefineList = Construct.extend("DefineList", } return this; }, - /** - * @function can-define/list/list.prototype.assign assign - * @parent can-define/list/list.prototype - * - * Sets items or properties on a list. - * - * @signature `list.assign(newProps)` - * - * Assigns the properties on the list with `newProps`. Properties not present in `newProps` will be left unchanged. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.assign({count: 1000, skip: 2}); - * list.get("count") //-> 1000 - * ``` - * @param {Array} newProps Properties that need to be assigned to the list instance - * @return {can-define/list/list} The list instance. - */ assign: function(prop) { if (canReflect.isListLike(prop)) { canReflect.assignList(this, prop); @@ -369,26 +233,6 @@ var DefineList = Construct.extend("DefineList", } return this; }, - /** - * @function can-define/list/list.prototype.update update - * @parent can-define/list/list.prototype - * - * Sets an item or property or items or properties on a list. - * - * @signature `list.update(newProps)` - * - * Updates the properties on the list with `newProps`. Properties not in `newProps` will be set to `undefined`. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.assign({count: 0, skip: 2}); - * list.update({count: 1000}); - * list.get("count") //-> 1000 - * list.get("skip") //-> undefined - * ``` - * @param {Array} newProps Properties that need to be updated to the list instance - * @return {can-define/list/list} The list instance. - */ update: function(prop) { if (canReflect.isListLike(prop)) { canReflect.updateList(this, prop); @@ -397,29 +241,6 @@ var DefineList = Construct.extend("DefineList", } return this; }, - /** - * @function can-define/list/list.prototype.assignDeep assignDeep - * @parent can-define/list/list.prototype - * - * Sets an item or property or items or properties on a list. - * - * @signature `list.assignDeep(newProps)` - * - * Updates the properties on the list with `newProps`. Properties not in `newProps` will be left unchanged. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.assign({count: 1, skip: 2}); - * list.get("count") //-> 1 - * - * list.assignDeep({count: 1000}); - * list.get("count") //-> 1000 - * list.get("skip") //-> 2 - * ``` - * - * @param {Array} newProps Properties that need to be assigned to the list instance - * @return {can-define/list/list} The list instance. - */ assignDeep: function(prop) { if (canReflect.isListLike(prop)) { canReflect.assignDeepList(this, prop); @@ -428,28 +249,6 @@ var DefineList = Construct.extend("DefineList", } return this; }, - /** - * @function can-define/list/list.prototype.updateDeep updateDeep - * @parent can-define/list/list.prototype - * - * Sets an item or property or items or properties on a list. - * - * @signature `list.updateDeep(newProps)` - * - * Recursively updates the properties on the list with `newProps`. Properties not in `newProps` will be set to `undefined`. - * - * ```js - * var list = new DefineList(["A","B"]); - * list.assign({count: 0, skip: 2, foo: {bar: 'zed', a: 'b'}}); - * list.updateDeep({foo: {bar: 'yay'}}); - * - * list.get("count") //-> undefined - * list.get("skip") //-> undefined - * list.get("foo") // -> {bar: 'yay', a: undefined} - * ``` - * @param {Array} newProps Properties that need to be updated on the list instance - * @return {can-define/list/list} The list instance. - */ updateDeep: function(prop) { if (canReflect.isListLike(prop)) { canReflect.updateDeepList(this, prop); @@ -470,52 +269,6 @@ var DefineList = Construct.extend("DefineList", callback(this[i], i); } }, - - /** - * @function can-define/list/list.prototype.splice splice - * @parent can-define/list/list.prototype - * @description Insert and remove elements from a DefineList. - * @signature `list.splice(index[, howMany[, ...newItems]])` - * - * Removes `howMany` items at `index` and adds `newItems` in their place. - * - * - * - * @param {Number} index Where to start removing or inserting elements. - * - * @param {Number} [howMany] The number of elements to remove - * If _howMany_ is not provided, `splice` will remove all elements from `index` to the end of the DefineList. - * - * @param {*} newItems Items to insert into the DefineList - * - * @return {Array} The elements removed by `splice`. - * - * @body - * - * ## Use - * - * `splice` lets you remove elements from and insert elements into a DefineList. - * - * This example demonstrates how to do surgery on a list of numbers: - * - * ``` - * var list = new DefineList([0, 1, 2, 3]); - * - * // starting at index 2, remove one element and insert 'Alice' and 'Bob': - * list.splice(2, 1, 'Alice', 'Bob'); - * list.get(); // [0, 1, 'Alice', 'Bob', 3] - * ``` - * - * ## Events - * - * `splice` causes the DefineList it's called on to emit - * _add_ events, _remove_ events, and _length_ events. If there are - * any elements to remove, a _remove_ event, and a - * _length_ event will be fired. If there are any elements to insert, a - * separate _add_ event, and a separate _length_ event - * will be fired. - * - */ splice: function(index, howMany) { var args = canReflect.toArray(arguments), added = [], @@ -567,28 +320,6 @@ var DefineList = Construct.extend("DefineList", }, /** - * @function can-define/list/list.prototype.serialize serialize - * @parent can-define/list/list.prototype - * - * Returns the a serialized version of this list. - * - * @signature `list.serialize()` - * - * Goes through each item in the list and gets its serialized - * value and returns them in a plain Array. - * - * Each items serialized value is the result of calling `.serialize()` - * on the item or if the item doesn't have a `serialize` method, - * the item itself. - * - * ``` - * var list = new DefineList(["first", {foo: "bar"}]); - * var serializedList = list.serialize(); - * - * serializedList //-> ["first", {foo: "bar"}] - * ``` - * - * @return {Array} An array with each item's serialied value. */ serialize: function() { return canReflect.serialize(this, Map); @@ -624,101 +355,7 @@ var getArgs = function(args) { }; // Create `push`, `pop`, `shift`, and `unshift` canReflect.eachKey({ - /** - * @function can-define/list/list.prototype.push push - * @description Add elements to the end of a list. - * @signature `list.push(...elements)` - * - * `push` adds elements onto the end of a DefineList. - * - * ``` - * var names = new DefineList(['Alice']); - * names.push('Bob', 'Eve'); - * names //-> DefineList['Alice','Bob', 'Eve'] - * ``` - * - * @param {*} elements the elements to add to the DefineList - * - * @return {Number} the new length of the DefineList - * - * @body - * - * ## Use - * - * `push` adds elements onto the end of a DefineList here is an example: - * - * ``` - * var list = new DefineList(['Alice']); - * - * list.push('Bob', 'Eve'); - * list.get(); // ['Alice', 'Bob', 'Eve'] - * ``` - * - * If you have an array you want to concatenate to the end - * of the DefineList, you can use `apply`: - * - * ``` - * var names = ['Bob', 'Eve'], - * list = new DefineList(['Alice']); - * - * list.push.apply(list, names); - * list.get(); // ['Alice', 'Bob', 'Eve'] - * ``` - * - * ## Events - * - * `push` causes _add_, and _length_ events to be fired. - * - * ## See also - * - * `push` has a counterpart in [can-define/list/list::pop pop], or you may be - * looking for [can-define/list/list::unshift unshift] and its counterpart [can-define/list/list::shift shift]. - */ push: "length", - /** - * @function can-define/list/list.prototype.unshift unshift - * @description Add items to the beginning of a DefineList. - * @signature `list.unshift(...items)` - * - * `unshift` adds items onto the beginning of a DefineList. - * - * ``` - * var list = new DefineList(['Alice']); - * - * list.unshift('Bob', 'Eve'); - * list; // DefineList['Bob', 'Eve', 'Alice'] - * ``` - * - * @param {*} items The items to add to the DefineList. - * - * @return {Number} The new length of the DefineList. - * - * @body - * - * ## Use - * - * - * - * If you have an array you want to concatenate to the beginning - * of the DefineList, you can use `apply`: - * - * ``` - * var names = ['Bob', 'Eve'], - * list = new DefineList(['Alice']); - * - * list.unshift.apply(list, names); - * list.get(); // ['Bob', 'Eve', 'Alice'] - * ``` - * - * ## Events - * - * `unshift` causes _add_ and _length_ events to be fired. - * - * ## See also - * - * `unshift` has a counterpart in [can-define/list/list::shift shift], or you may be - * looking for [can-define/list/list::push push] and its counterpart [can-define/list/list::pop pop]. - */ unshift: 0 }, // Adds a method @@ -757,78 +394,7 @@ canReflect.eachKey({ }); canReflect.eachKey({ - /** - * @function can-define/list/list.prototype.pop pop - * @description Remove an element from the end of a DefineList. - * @signature `list.pop()` - * - * `pop` removes an element from the end of a DefineList. - * - * ```js - * var names = new DefineList(['Alice', 'Bob', 'Eve']); - * names.pop() //-> 'Eve' - * ``` - * - * @return {*} The element just popped off the DefineList, or `undefined` if the DefineList was empty - * - * @body - * - * ## Use - * - * `pop` is the opposite action from [can-define/list/list::push push]: - * - * ``` - * var list = new DefineList(['Alice', 'Bob', 'Eve']); - * - * list.pop(); // 'Eve' - * list.pop(); // 'Bob' - * list.pop(); // 'Alice' - * list.pop(); // undefined - * ``` - * - * ## Events - * - * `pop` causes _remove_ and _length_ events to be fired if the DefineList is not empty - * when it is called. - * - * ## See also - * - * `pop` has its counterpart in [can-define/list/list::push push], or you may be - * looking for [can-define/list/list::unshift unshift] and its counterpart [can-define/list/list::shift shift]. - */ pop: "length", - /** - * @function can-define/list/list.prototype.shift shift - * @description Remove an item from the front of a list. - * @signature `list.shift()` - * - * `shift` removes an element from the beginning of a DefineList. - * - * ``` - * var list = new DefineList(['Alice','Adam']); - * list.shift(); //-> 'Alice' - * list.shift(); //-> 'Adam' - * list.shift(); //-> undefined - * ``` - * - * @return {*} The element just shifted off the DefineList, or `undefined` if the DefineList is empty - * - * @body - * - * ## Use - * - * `shift` is the opposite action from `[can-define/list/list::unshift unshift]`: - * - * ## Events - * - * `pop` causes _remove_ and _length_ events to be fired if the DefineList is not empty - * when it is called. - * - * ## See also - * - * `shift` has a counterpart in [can-define/list/list::unshift unshift], or you may be - * looking for [can-define/list/list::push push] and its counterpart [can-define/list/list::pop pop]. - */ shift: 0 }, // Creates a `remove` type method @@ -866,262 +432,11 @@ canReflect.eachKey({ }); canReflect.eachKey({ - /** - * @function can-define/list/list.prototype.map map - * @description Map the values in this list to another list. - * - * @signature `list.map(callback[, thisArg])` - * - * Loops through the values of the list, calling `callback` for each one until the list - * ends. The return values of `callback` are used to populate the returned list. - * - * ```js - * var todos = new DefineList([ - * {name: "dishes", complete: false}, - * {name: "lawn", complete: true} - * ]); - * var names = todos.map(function(todo){ - * return todo.name; - * }); - * names //-> DefineList["dishes","lawn"] - * ``` - * - * @param {function(item, index, list)} callback A function to call with each element of the DefineList. - * The three parameters that callback gets passed are: - * - item (*) - the element at index. - * - index (Integer) - the index of the current element of the list. - * - list (DefineList) - the `DefineList` the elements are coming from. - * - * The return value of `callback`, including `undefined` values are used to populate the resulting list. - * - * @param {Object} [thisArg] The object to use as `this` inside the callback. - * @return {can-define/list/list} a new `DefineList` with the results of the map transform. - * @body - * - */ "map": 3, - /** - * @function can-define/list/list.prototype.filter filter - * - * Filter a list to a new list of the matched items. - * - * @signature `list.filter( callback [,thisArg] )` - * - * Filters `list` based on the return value of `callback`. - * - * ``` - * var names = new DefineList(["alice","adam","zack","zeffer"]); - * var aNames = names.filter(function(name){ - * return name[0] === "a" - * }); - * aNames //-> DefineList["alice","adam"] - * ``` - * - * @param {function(*, Number, can-define/list/list)} callback(item, index, list) A - * function to call with each element of the DefineList. The three parameters that callback gets passed are: - * - item (*) - the element at index. - * - index (Integer) - the index of the current element of the list. - * - list (DefineList) - the `DefineList` the elements are coming from. - * - * If `callback` returns a truthy result, `item` will be added to the result. Otherwise, the `item` will be - * excluded. - * - * @param {Object} thisArg What `this` should be in the `callback`. - * @return {can-define/list/list} A new instance of this `DefineList` (may be a subclass), containing the items that passed the filter. - * - * @signature `list.filter( props )` - * - * Filters items in `list` based on the property values in `props`. - * - * ``` - * var todos = new DefineList([ - * {name: "dishes", complete: false}, - * {name: "lawn", complete: true} - * ]); - * var complete = todos.filter({complete: true}); - * complete //-> DefineList[{name: "lawn", complete: true}] - * ``` - * - * @param {Object} props An object of key-value properties. Each key and value in - * `props` must be present on an `item` for the `item` to be in the returned list. - * @return {can-define/list/list} A new `DefineList` of the same type. - */ "filter": 3, - /** - * @function can-define/list/list.prototype.reduce reduce - * @description Map the values in this list to a single value - * - * @signature `list.reduce(callback, initialValue, [, thisArg])` - * - * Loops through the values of the list, calling `callback` for each one until the list - * ends. The return value of `callback` is passed to the next iteration as the first argument, - * and finally returned by `reduce`. - * - * ```js - * var todos = new DefineList([ - * {name: "dishes", complete: false}, - * {name: "lawn", complete: true} - * ]); - * var todosAsOneObject = todos.reduce(function(todos, todo){ - * todos[todo.name] = todo.complete; - * return todos; - * }, {}); - * todosAsOneObject //-> { dishes: false, lawn: true } - * ``` - * - * @param {function(item, index, list)} callback A function to call with each element of the DefineList. - * The four parameters that callback gets passed are: - * - current (*) - the current aggregate value of reducing over the list -- the initial value if the first iteration - * - item (*) - the element at index. - * - index (Integer) - the index of the current element of the list. - * - list (DefineList) - the `DefineList` the elements are coming from. - * - * The return value of `callback` is passed to the next iteration as the first argument, and returned from - * `reduce` if the last iteration. - * - * @param {*} [initialValue] The initial value to use as `current` in the first iteration - * @param {Object} [thisArg] The object to use as `this` inside the callback. - * @return {*} The result of the final call of `callback` on the list. - * @body - * - */ "reduce": 4, - /** - * @function can-define/list/list.prototype.reduceRight reduceRight - * @description Map the values in this list to a single value from right to left - * - * @signature `list.reduceRight(callback, initialValue, [, thisArg])` - * - * Loops through the values of the list in reverse order, calling `callback` for each one until the list - * ends. The return value of `callback` is passed to the next iteration as the first argument, - * and finally returned by `reduce`. - * - * ```js - * var todos = new DefineList([ - * {name: "dishes", complete: false}, - * {name: "lawn", complete: true} - * ]); - * var todosAsOneObject = todos.reduce(function(todos, todo){ - * todos[todo.name] = todo.complete; - * return todos; - * }, {}); - * todosAsOneObject //-> { dishes: false, lawn: true } - * ``` - * - * @param {function(item, index, list)} callback A function to call with each element of the DefineList. - * The four parameters that callback gets passed are: - * - current (*) - the current aggregate value of reducing over the list -- the initial value if the first iteration - * - item (*) - the element at index. - * - index (Integer) - the index of the current element of the list. - * - list (DefineList) - the `DefineList` the elements are coming from. - * - * The return value of `callback` is passed to the next iteration as the first argument, and returned from - * `reduce` if the last iteration. - * - * @param {*} [initialValue] The initial value to use as `current` in the first iteration - * @param {Object} [thisArg] The object to use as `this` inside the callback. - * @return {*} The result of the final call of `callback` on the list. - * @body - * - */ "reduceRight": 4, - /** - * @function can-define/list/list.prototype.every every - * - * Return true if every item in a list matches a predicate. - * - * @signature `list.every( callback [,thisArg] )` - * - * Tests each item in `list` by calling `callback` on it. If `callback` returns truthy for every element in - * `list`, `every` returns `true`. - * - * ``` - * var names = new DefineList(["alice","adam","zack","zeffer"]); - * var aNames = names.every(function(name){ - * return name[0] === "a" - * }); - * aNames //-> false - * ``` - * - * @param {function(*, Number, can-define/list/list)} callback(item, index, list) A - * function to call with each element of the DefineList. The three parameters that callback gets passed are: - * - item (*) - the element at index. - * - index (Integer) - the index of the current element of the list. - * - list (DefineList) - the `DefineList` the elements are coming from. - * - * If `callback` returns a truthy result, `every` will evaluate the callback on the next element. Otherwise, `every` - * will return `false`. - * - * @param {Object} thisArg What `this` should be in the `callback`. - * @return {Boolean} `true` if calling the callback on every element in `list` returns a truthy value, `false` otherwise. - * - * @signature `list.every( props )` - * - * Tests each item in `list` by comparing its properties to `props`. If `props` match for every element in - * `list`, `every` returns `true`. - * - * ``` - * var todos = new DefineList([ - * {name: "dishes", complete: false}, - * {name: "lawn", complete: true} - * ]); - * var complete = todos.every({complete: true}); - * complete //-> false - * ``` - * - * @param {Object} props An object of key-value properties. Each key and value in - * `props` must be present on an `item` for the `item` to match. - * @return {Boolean} `true` if every element in `list` matches `props`, `false` otherwise. - */ "every": 3, - /** - * @function can-define/list/list.prototype.some some - * - * Return true if at least one item in a list matches a predicate. - * - * @signature `list.some( callback [,thisArg] )` - * - * Tests each item in `list` by calling `callback` on it. If `callback` returns truthy for some element in - * `list`, `some` returns `true`. - * - * ``` - * var names = new DefineList(["alice","adam","zack","zeffer"]); - * var aNames = names.some(function(name){ - * return name[0] === "a" - * }); - * aNames //-> false - * ``` - * - * @param {function(*, Number, can-define/list/list)} callback(item, index, list) A - * function to call with each element of the DefineList. The three parameters that callback gets passed are: - * - item (*) - the element at index. - * - index (Integer) - the index of the current element of the list. - * - list (DefineList) - the DefineList the elements are coming from. - * - * If `callback` returns a falsy result, `some` will evaluate the callback on the next element. Otherwise, `some` - * will return `true`. - * - * @param {Object} thisArg What `this` should be in the `callback`. - * @return {Boolean} `false` if calling the callback on some element in `list` returns a falsy value, `true` otherwise. - * - * @signature `list.some( props )` - * - * Tests each item in `list` by comparing its properties to `props`. If `props` match for some element in - * `list`, `some` returns `true`. - * - * ``` - * var todos = new DefineList([ - * {name: "dishes", complete: false}, - * {name: "lawn", complete: true} - * ]); - * var complete = todos.some({complete: true}); - * complete //-> false - * ``` - * - * @param {Object} props An object of key-value properties. Each key and value in - * `props` must be present on an `item` for the `item` to match. - * @return {Boolean} `false` if every element in `list` fails to match `props`, `true` otherwise - */ "some": 3 }, function a(fnLength, fnName) { @@ -1155,28 +470,7 @@ function a(fnLength, fnName) { }; }); - assign(DefineList.prototype, { - /** - * @function can-define/list/list.prototype.indexOf indexOf - * @description Look for an item in a DefineList. - * @signature `list.indexOf(item)` - * - * `indexOf` finds the position of a given item in the DefineList. - * - * ``` - * var list = new DefineList(['Alice', 'Bob', 'Eve']); - * list.indexOf('Alice'); // 0 - * list.indexOf('Charlie'); // -1 - * ``` - * - * @param {*} item The item to find. - * - * @return {Number} The position of the item in the DefineList, or -1 if the item is not found. - * - * @body - * - */ indexOf: function(item, fromIndex) { for (var i = fromIndex || 0, len = this.length; i < len; i++) { if (this.get(i) === item) { @@ -1185,27 +479,6 @@ assign(DefineList.prototype, { } return -1; }, - - /** - * @function can-define/list/list.prototype.lastIndexOf lastIndexOf - * @description Look for an item in a DefineList starting from the end. - * @signature `list.lastIndexOf(item)` - * - * `lastIndexOf` finds the last position of a given item in the DefineList. - * - * ``` - * var list = new DefineList(['Alice', 'Bob', 'Alice', 'Eve']); - * list.lastIndexOf('Alice'); // 2 - * list.lastIndexOf('Charlie'); // -1 - * ``` - * - * @param {*} item The item to find. - * - * @return {Number} The position of the item in the DefineList, or -1 if the item is not found. - * - * @body - * - */ lastIndexOf: function(item, fromIndex) { fromIndex = typeof fromIndex === "undefined" ? this.length - 1: fromIndex; for (var i = fromIndex; i >= 0; i--) { @@ -1215,127 +488,21 @@ assign(DefineList.prototype, { } return -1; }, - - /** - * @function can-define/list/list.prototype.join join - * @description Join a DefineList's elements into a string. - * @signature `list.join(separator)` - * - * `join` turns a DefineList into a string by inserting _separator_ between the string representations - * of all the elements of the DefineList. - * - * ``` - * var list = new DefineList(['Alice', 'Bob', 'Eve']); - * list.join(', '); // 'Alice, Bob, Eve' - * ``` - * - * @param {String} separator The string to seperate elements. - * - * @return {String} The joined string. - * - */ join: function() { ObservationRecorder.add(this, "length"); return [].join.apply(this, arguments); }, - - /** - * @function can-define/list/list.prototype.reverse reverse - * @description Reverse the order of a DefineList. - * @signature `list.reverse()` - * - * Reverses the elements of the DefineList in place. - * - * ``` - * var list = new DefineList(['Alice', 'Bob', 'Eve']); - * var reversedList = list.reverse(); - * - * reversedList; //-> DefineList['Eve', 'Bob', 'Alice']; - * list === reversedList; // true - * ``` - * - * @return {can-define/list/list} The DefineList, for chaining. - * - * @body - * - */ reverse: function() { // this shouldn't be observable var list = [].reverse.call(this._items()); return this.replace(list); }, - - /** - * @function can-define/list/list.prototype.slice slice - * @description Make a copy of a part of a DefineList. - * @signature `list.slice([start[, end]])` - * - * `slice` creates a copy of a portion of the DefineList. - * - * ```js - * var list = new DefineList(['Alice', 'Bob', 'Charlie', 'Daniel', 'Eve']); - * var newList = list.slice(1, 4); - * newList //-> DefineList['Bob', 'Charlie', 'Daniel'] - * ``` - * - * @param {Number} [start=0] The index to start copying from. Defaults to `0`. - * - * @param {Number} [end] The first index not to include in the copy - * If _end_ is not supplied, `slice` will copy until the end of the list. - * - * @return {can-define/list/list} A new `DefineList` with the extracted elements. - * - * @body - * - * ## Use - * - * `slice` is the simplest way to copy a DefineList: - * - * ``` - * var list = new DefineList(['Alice', 'Bob', 'Eve']); - * var copy = list.slice(); - * - * copy //-> DefineList['Alice', 'Bob', 'Eve'] - * list === copy; //-> false - * ``` - */ slice: function() { // tells computes to listen on length for changes. ObservationRecorder.add(this, "length"); var temp = Array.prototype.slice.apply(this, arguments); return new this.constructor(temp); }, - - /** - * @function can-define/list/list.prototype.concat concat - * @description Merge many collections together into a DefineList. - * @signature `list.concat(...args)` - * - * Returns a `DefineList` with the `list`'s items and the additional `args`. - * - * @param {Array|can-define/list/list|*} args Any number of arrays, Lists, or values to add in - * For each parameter given, if it is an Array or a DefineList, each of its elements will be added to - * the end of the concatenated DefineList. Otherwise, the parameter itself will be added. - * - * @return {can-define/list/list} A DefineList of the same type. - * - * @body - * - * ## Use - * - * `concat` makes a new DefineList with the elements of the DefineList followed by the elements of the parameters. - * - * ``` - * var list = new DefineList(); - * var newList = list.concat( - * 'Alice', - * ['Bob', 'Charlie']), - * new DefineList(['Daniel', 'Eve']), - * {f: 'Francis'} - * ); - * newList.get(); // ['Alice', 'Bob', 'Charlie', 'Daniel', 'Eve', {f: 'Francis'}] - * ``` - */ concat: function() { var args = []; // Go through each of the passed `arguments` and @@ -1361,43 +528,6 @@ assign(DefineList.prototype, { // list constructor to make it back into a list return new this.constructor(Array.prototype.concat.apply(canReflect.toArray(this), args)); }, - - /** - * @function can-define/list/list.prototype.forEach forEach - * @description Call a function for each element of a DefineList. - * @signature `list.forEach(callback[, thisArg])` - * - * Loops through the values of the list, calling `callback` for each one until the list ends - * or `false` is returned. - * - * ``` - * list.forEach(function(item, index, list){ ... }) - * ``` - * - * @param {function(item, index, list)} callback A function to call with each element of the DefineList. - * The three parameters that callback gets passed are: - * - item - the element at index. - * - index - the current element of the list. - * - list - the DefineList the elements are coming from. - * - * If the callback returns `false` the looping stops. - * - * @param {Object} [thisArg] The object to use as `this` inside the callback. - * @return {can-define/list/list} The list instance. - * @body - * - * ## Use - * - * `forEach` calls a callback for each element in the DefineList. - * - * ``` - * var list = new DefineList([1, 2, 3]); - * list.forEach(function(element, index, list) { - * list.get(index, element * element); - * }); - * list.get(); // [1, 4, 9] - * ``` - */ forEach: function(cb, thisarg) { var item; for (var i = 0, len = this.length; i < len; i++) { @@ -1408,33 +538,6 @@ assign(DefineList.prototype, { } return this; }, - - /** - * @function can-define/list/list.prototype.replace replace - * @description Replace all the elements of a DefineList. - * @signature `list.replace(collection)` - * - * Replaces every item in the list with `collection`. - * - * ``` - * var names = new DefineList(["alice","adam","eve"]); - * names.replace(["Justin","Xena"]); - * names //-> DefineList["Justin","Xena"] - * ``` - * - * @param {Array|can-define/list/list} collection The collection of items that will be in `list`. - * @return {can-define/list/list} Returns the `list`. - * - * @body - * - * ## Use - * - * `replace` is essentially a shortcut for [can-define/list/list.prototype.splice]. - * - * ## Events - * - * `replace` causes _remove_, _add_, and _length_ events. - */ replace: function(newList) { var patches = diff(this, newList); @@ -1449,50 +552,6 @@ assign(DefineList.prototype, { return this; }, - /** - * @function can-define/list/list.prototype.sort sort - * @description Sort the properties of a list. - * - * @signature `list.sort([compareFunction])` - * - * Sorts the elements of a list in place and returns the list. The API is the - * same as the native JavaScript `Array.prototype.sort` API. - * - * ```js - * var accounts = new Account.List([ - * { name: "Savings", amount: 20.00 }, - * { name: "Checking", amount: 103.24 }, - * { name: "Kids Savings", amount: 48155.13 } - * ]); - * accounts.sort(function(a, b){ - * if (a.name < b.name) { - * return -1; - * } else if (a.name > b.name){ - * return 1; - * } else { - * return 0; - * } - * }); - * accounts[0].name === "Checking" - * accounts[1].name === "Kids Savings" - * accounts[2].name === "Savings" - * ``` - * - * @param {function(a, b)} compareFunction Specifies a function that defines the sort order. - * - * If `compareFunction` is supplied, the list elements are sorted according to the return - * value of the compare function. If `a` and `b` are two elements being compared, then: - * - * - If `compareFunction(a, b)` returns a value less than 0, `a` will be sorted to - * a lower index than `b`, so `a` will now come first. - * - If `compareFunction(a, b)` returns 0, the order of the two values will not be changed. - * - If `compareFunction(a, b)` returns a value greater than 0, `a` will be sorted to - * a higher index than `b`, so `b` will now come first. - * - * @return {can-define/list/list} The list instance. - * @body - * ``` - */ sort: function(compareFunction) { var sorting = Array.prototype.slice.call(this); Array.prototype.sort.call(sorting, compareFunction); @@ -1501,7 +560,6 @@ assign(DefineList.prototype, { } }); - // Add necessary event methods to this object. for (var prop in define.eventsProto) { DefineList[prop] = define.eventsProto[prop]; diff --git a/test/test-list-and-map.js b/test/test-list-and-map.js index 37cbd6e..f58a7b3 100644 --- a/test/test-list-and-map.js +++ b/test/test-list-and-map.js @@ -387,3 +387,19 @@ QUnit.test('Deep updating a map', function() { QUnit.equal(obj.list[0], 'something', 'the first element of the list should be updated'); }); + +QUnit.test("assignDeep", function(){ + var justin = new DefineMap({name: "Justin", age: 35}), + payal = new DefineMap({name: "Payal", age: 35}); + + var people = new DefineList([justin, payal]); + + people.assignDeep([ + {age: 36} + ]); + + QUnit.deepEqual(people.serialize(), [ + {name: "Justin", age: 36}, + {name: "Payal", age: 35} + ], "assigned right"); +});