11/**
22 * API Bound Models for AngularJS
3- * @version v0.13 .0 - 2014-03-14
3+ * @version v0.14 .0 - 2014-05-19
44 * @link https://github.com/angular-platanus/restmod
55 * @author Ignacio Baixas <[email protected] > 66 * @license MIT License, http://www.opensource.org/licenses/MIT
@@ -443,7 +443,7 @@ angular.module('plRestmod').provider('$restmod', function() {
443443 /**
444444 * @memberof Model
445445 *
446- * @description Returns a model's object private key from model decoded data.
446+ * @description Returns a model's object private key from model raw data.
447447 * If data is not an object, then it is considered to be the primary key value.
448448 *
449449 * The private key is the passed to the $urlFor function to obtain an object's url.
@@ -454,9 +454,9 @@ angular.module('plRestmod').provider('$restmod', function() {
454454 * @param {object } _data decoded object data (or pk)
455455 * @return {mixed } object private key
456456 */
457- Model . $inferKey = function ( _data ) {
458- if ( ! _data || typeof _data [ primaryKey ] === 'undefined' ) return null ;
459- return _data [ primaryKey ] ;
457+ Model . $inferKey = function ( _rawData ) {
458+ if ( ! _rawData || typeof _rawData [ primaryKey ] === 'undefined' ) return null ;
459+ return _rawData [ primaryKey ] ;
460460 } ;
461461
462462 /** Runtime modifiers - private api for now */
@@ -543,14 +543,14 @@ angular.module('plRestmod').provider('$restmod', function() {
543543 /**
544544 * @memberof Model#
545545 *
546- * @description Copyies another object's properties.
546+ * @description Copyies another object's non-private properties.
547547 *
548548 * @param {object } _other Object to merge.
549549 * @return {Model } self
550550 */
551551 $extend : function ( _other ) {
552552 for ( var tmp in _other ) {
553- if ( _other . hasOwnProperty ( tmp ) ) {
553+ if ( _other . hasOwnProperty ( tmp ) && tmp [ 0 ] !== '$' ) {
554554 this [ tmp ] = _other [ tmp ] ;
555555 }
556556 }
@@ -674,7 +674,7 @@ angular.module('plRestmod').provider('$restmod', function() {
674674 */
675675 $decode : function ( _raw , _mask ) {
676676 transform ( _raw , this , '' , _mask || READ_MASK , true , this ) ;
677- if ( ! this . $pk ) this . $pk = Model . $inferKey ( this ) ; // TODO: improve this, warn if key changes
677+ if ( ! this . $pk ) this . $pk = Model . $inferKey ( _raw ) ; // TODO: warn if key changes
678678 callback ( 'after-feed' , this , _raw ) ;
679679 return this ;
680680 } ,
@@ -728,6 +728,8 @@ angular.module('plRestmod').provider('$restmod', function() {
728728 *
729729 * @description Begin a server request to create/update resource.
730730 *
731+ * If resource is new and it belongs to a collection and it hasnt been revealed, then it will be revealed.
732+ *
731733 * The request's promise is provided as the $promise property.
732734 *
733735 * @return {Model } this
@@ -760,6 +762,12 @@ angular.module('plRestmod').provider('$restmod', function() {
760762 return this . $send ( request , function ( _response ) {
761763 var data = _response . data ;
762764 if ( data && ! isArray ( data ) ) this . $decode ( data ) ;
765+
766+ // reveal item (if not yet positioned)
767+ if ( this . $scope . $isCollection && this . $position === undefined && ! this . $preventReveal ) {
768+ this . $scope . $add ( this , this . $revealAt ) ;
769+ }
770+
763771 callback ( 'after-create' , this , _response ) ;
764772 callback ( 'after-save' , this , _response ) ;
765773 } , function ( _response ) {
@@ -794,6 +802,50 @@ angular.module('plRestmod').provider('$restmod', function() {
794802 } , function ( _response ) {
795803 callback ( 'after-destroy-error' , this , _response ) ;
796804 } ) ;
805+ } ,
806+
807+ // Collection related methods.
808+
809+ /**
810+ * @memberof Model#
811+ *
812+ * @description Changes the location of the object in the bound collection.
813+ *
814+ * If object hasn't been revealed, then this method will change the index where object will be revealed at.
815+ *
816+ * @param {integer } _to New object position (index)
817+ * @return {Model } this
818+ */
819+ $moveTo : function ( _to ) {
820+ if ( this . $position !== undefined ) {
821+ // TODO: move item to given index.
822+ // TODO: callback
823+ } else {
824+ this . $revealAt = _to ;
825+ }
826+ return this ;
827+ } ,
828+
829+ /**
830+ * @memberof Model#
831+ *
832+ * @description Reveal in collection
833+ *
834+ * If instance is bound to a collection and it hasnt been revealed (because it's new and hasn't been saved),
835+ * then calling this method without parameters will force the object to be added to the collection.
836+ *
837+ * If this method is called with **_show** set to `false`, then the object wont be revealed by a save operation.
838+ *
839+ * @param {boolean } _show Whether to reveal inmediatelly or prevent automatic reveal.
840+ * @return {Model } this
841+ */
842+ $reveal : function ( _show ) {
843+ if ( _show === undefined || _show ) {
844+ this . $scope . $add ( this , this . $revealAt ) ;
845+ } else {
846+ this . $preventReveal = true ;
847+ }
848+ return this ;
797849 }
798850 } ;
799851
@@ -866,61 +918,42 @@ angular.module('plRestmod').provider('$restmod', function() {
866918 /**
867919 * @memberof ModelCollection#
868920 *
869- * @description Loads a new model instance bound to this context and a given pk.
870- *
871- * ATENTION: this method does not adds the new object to the collection, it is intended to be a base
872- * building method that can be overriden to provide special caching logics.
921+ * @description Builds a new instance of this model, bound to this instance scope, sets its primary key.
873922 *
874923 * @param {mixed } _pk object private key
875924 * @return {Model } New model instance
876925 */
877- $load : function ( _pk ) {
926+ $new : function ( _pk ) {
878927 return new Model ( this , _pk ) ;
879928 } ,
880929
881930 /**
882931 * @memberof ModelCollection#
883932 *
884- * @description Builds a new instance of this model, sets its primary key.
885- *
886- * @param {mixed } _pk object private key
887- * @return {Model } New model instance
888- */
889- $new : function ( _pk ) {
890- var obj = this . $load ( _pk ) ;
891- if ( this . $isCollection ) this . $add ( obj ) ;
892- return obj ;
893- } ,
894-
895- /**
896- * @memberof ModelCollection#
933+ * @description Builds a new instance of this model, does not assign a pk to the created object.
897934 *
898- * @description Builds a new instance of this model
935+ * ATTENTION: item will not show in collection until `$save` is called. To reveal item before than call `$reveal`.
899936 *
900937 * @param {object } _init Initial values
901938 * @return {Model } model instance
902939 */
903940 $build : function ( _init ) {
904- var obj = this . $load ( Model . $inferKey ( _init ) ) ;
905- angular . extend ( obj , _init ) ;
906-
907- if ( this . $isCollection ) this . $add ( obj ) ;
908- return obj ;
941+ return this . $new ( ) . $extend ( _init ) ;
909942 } ,
910943
911944 /**
912945 * @memberof ModelCollection#
913946 *
914- * @description Builds a new instance of this model using undecoded data
947+ * @description Builds a new instance of this model using undecoded data.
948+ *
949+ * ATTENTION: does not automatically reveal item in collection, chain a call to $reveal to do so.
915950 *
916951 * @param {object } _raw Undecoded data
917952 * @return {Model } model instance
918953 */
919954 $buildRaw : function ( _raw ) {
920- var obj = this . $load ( Model . $inferKey ( _raw ) ) ; // TODO: using infer key on raw...
955+ var obj = this . $new ( Model . $inferKey ( _raw ) ) ;
921956 obj . $decode ( _raw ) ;
922-
923- if ( this . $isCollection ) this . $add ( obj ) ;
924957 return obj ;
925958 } ,
926959
@@ -933,7 +966,7 @@ angular.module('plRestmod').provider('$restmod', function() {
933966 * @return {Model } model instance
934967 */
935968 $find : function ( _pk ) {
936- return this . $load ( _pk ) . $fetch ( ) ;
969+ return this . $new ( _pk ) . $fetch ( ) ;
937970 } ,
938971
939972 /**
@@ -1049,7 +1082,9 @@ angular.module('plRestmod').provider('$restmod', function() {
10491082 $feed : function ( _raw ) {
10501083 if ( ! this . $isCollection ) throw new Error ( '$feed is only supported by collections' ) ;
10511084 if ( ! this . $resolved ) this . length = 0 ; // reset contents if not resolved.
1052- forEach ( _raw , this . $buildRaw , this ) ;
1085+ for ( var i = 0 , l = _raw . length ; i < l ; i ++ ) {
1086+ this . $buildRaw ( _raw [ i ] ) . $reveal ( ) ; // build and disclose every item.
1087+ }
10531088 this . $resolved = true ;
10541089 return this ;
10551090 } ,
@@ -1131,12 +1166,13 @@ angular.module('plRestmod').provider('$restmod', function() {
11311166 */
11321167 $add : function ( _obj , _idx ) {
11331168 // TODO: make sure object is f type Model?
1134- if ( this . $isCollection ) {
1135- if ( typeof _idx !== ' undefined' ) {
1169+ if ( this . $isCollection && _obj . $position === undefined ) {
1170+ if ( _idx !== undefined ) {
11361171 this . splice ( _idx , 0 , _obj ) ;
11371172 } else {
11381173 this . push ( _obj ) ;
11391174 }
1175+ _obj . $position = true ; // use true for now, keeping position updated can be expensive
11401176 callback ( 'after-add' , this , _obj ) ;
11411177 }
11421178 return this ;
@@ -1159,6 +1195,7 @@ angular.module('plRestmod').provider('$restmod', function() {
11591195 var idx = this . $indexOf ( _obj ) ;
11601196 if ( idx !== - 1 ) {
11611197 this . splice ( idx , 1 ) ;
1198+ _obj . $position = undefined ;
11621199 callback ( 'after-remove' , this , _obj ) ;
11631200 }
11641201 return this ;
@@ -1284,6 +1321,8 @@ angular.module('plRestmod').provider('$restmod', function() {
12841321 *
12851322 * Primary keys are passed to scope's url methods to generate urls. The default primary key is 'id'.
12861323 *
1324+ * **ATTENTION** Primary keys are extracted from raw data, so _key must use raw api naming.
1325+ *
12871326 * @param {string|function } _key New primary key.
12881327 * @return {ModelBuilder } self
12891328 */
@@ -1689,7 +1728,7 @@ angular.module('plRestmod').provider('$restmod', function() {
16891728 // only reload object if id changes
16901729 if ( _inline )
16911730 {
1692- if ( ! this [ _attr ] || this [ _attr ] . $pk !== _model . $inferKey ( _raw ) ) { // TODO: using infer key on raw...
1731+ if ( ! this [ _attr ] || this [ _attr ] . $pk !== _model . $inferKey ( _raw ) ) {
16931732 this [ _attr ] = _model . $buildRaw ( _raw ) ;
16941733 } else {
16951734 this [ _attr ] . $decode ( _raw ) ;
@@ -1698,7 +1737,7 @@ angular.module('plRestmod').provider('$restmod', function() {
16981737 else
16991738 {
17001739 if ( ! this [ _attr ] || this [ _attr ] . $pk !== _raw ) {
1701- this [ _attr ] = _model . $load ( _raw ) ; // use $new instead of $build
1740+ this [ _attr ] = _model . $new ( _raw ) ; // use $new instead of $build
17021741 if ( _prefetch ) {
17031742 this [ _attr ] . $fetch ( ) ;
17041743 }
0 commit comments