@@ -890,12 +890,15 @@ function getExtendProperties(gd, update, indices, maxPoints) {
890
890
target = prop . get ( ) ;
891
891
insert = update [ key ] [ j ] ;
892
892
893
- if ( ! Array . isArray ( insert ) ) {
893
+ if ( ! Lib . isArrayOrTypedArray ( insert ) ) {
894
894
throw new Error ( 'attribute: ' + key + ' index: ' + j + ' must be an array' ) ;
895
895
}
896
- if ( ! Array . isArray ( target ) ) {
896
+ if ( ! Lib . isArrayOrTypedArray ( target ) ) {
897
897
throw new Error ( 'cannot extend missing or non-array attribute: ' + key ) ;
898
898
}
899
+ if ( target . constructor !== insert . constructor ) {
900
+ throw new Error ( 'cannot extend array with an array of a different type: ' + key ) ;
901
+ }
899
902
900
903
/*
901
904
* maxPoints may be an object map or a scalar. If object select the key:value, else
@@ -931,64 +934,43 @@ function getExtendProperties(gd, update, indices, maxPoints) {
931
934
* @param {Object } update
932
935
* @param {Number[] } indices
933
936
* @param {Number||Object } maxPoints
934
- * @param {Function } lengthenArray
935
- * @param {Function } spliceArray
937
+ * @param {Function } updateArray
936
938
* @return {Object }
937
939
*/
938
- function spliceTraces ( gd , update , indices , maxPoints , lengthenArray , spliceArray ) {
939
-
940
+ function spliceTraces ( gd , update , indices , maxPoints , updateArray ) {
940
941
assertExtendTracesArgs ( gd , update , indices , maxPoints ) ;
941
942
942
- var updateProps = getExtendProperties ( gd , update , indices , maxPoints ) ,
943
- remainder = [ ] ,
944
- undoUpdate = { } ,
945
- undoPoints = { } ;
946
- var target , prop , maxp ;
943
+ var updateProps = getExtendProperties ( gd , update , indices , maxPoints ) ;
944
+ var undoUpdate = { } ;
945
+ var undoPoints = { } ;
947
946
948
947
for ( var i = 0 ; i < updateProps . length ; i ++ ) {
948
+ var prop = updateProps [ i ] . prop ;
949
+ var maxp = updateProps [ i ] . maxp ;
949
950
950
- /*
951
- * prop is the object returned by Lib.nestedProperties
952
- */
953
- prop = updateProps [ i ] . prop ;
954
- maxp = updateProps [ i ] . maxp ;
955
-
956
- target = lengthenArray ( updateProps [ i ] . target , updateProps [ i ] . insert ) ;
957
-
958
- /*
959
- * If maxp is set within post-extension trace.length, splice to maxp length.
960
- * Otherwise skip function call as splice op will have no effect anyway.
961
- */
962
- if ( maxp >= 0 && maxp < target . length ) remainder = spliceArray ( target , maxp ) ;
963
-
964
- /*
965
- * to reverse this operation we need the size of the original trace as the reverse
966
- * operation will need to window out any lengthening operation performed in this pass.
967
- */
968
- maxp = updateProps [ i ] . target . length ;
969
-
970
- /*
971
- * Magic happens here! update gd.data.trace[key] with new array data.
972
- */
973
- prop . set ( target ) ;
951
+ // return new array and remainder
952
+ var out = updateArray ( updateProps [ i ] . target , updateProps [ i ] . insert , maxp ) ;
953
+ prop . set ( out [ 0 ] ) ;
974
954
955
+ // build the inverse update object for the undo operation
975
956
if ( ! Array . isArray ( undoUpdate [ prop . astr ] ) ) undoUpdate [ prop . astr ] = [ ] ;
976
- if ( ! Array . isArray ( undoPoints [ prop . astr ] ) ) undoPoints [ prop . astr ] = [ ] ;
977
-
978
- /*
979
- * build the inverse update object for the undo operation
980
- */
981
- undoUpdate [ prop . astr ] . push ( remainder ) ;
957
+ undoUpdate [ prop . astr ] . push ( out [ 1 ] ) ;
982
958
983
- /*
984
- * build the matching maxPoints undo object containing original trace lengths.
985
- */
986
- undoPoints [ prop . astr ] . push ( maxp ) ;
959
+ // build the matching maxPoints undo object containing original trace lengths
960
+ if ( ! Array . isArray ( undoPoints [ prop . astr ] ) ) undoPoints [ prop . astr ] = [ ] ;
961
+ undoPoints [ prop . astr ] . push ( updateProps [ i ] . target . length ) ;
987
962
}
988
963
989
964
return { update : undoUpdate , maxPoints : undoPoints } ;
990
965
}
991
966
967
+ function concatTypedArray ( arr0 , arr1 ) {
968
+ var arr2 = new arr0 . constructor ( arr0 . length + arr1 . length ) ;
969
+ arr2 . set ( arr0 ) ;
970
+ arr2 . set ( arr1 , arr0 . length ) ;
971
+ return arr2 ;
972
+ }
973
+
992
974
/**
993
975
* extend && prepend traces at indices with update arrays, window trace lengths to maxPoints
994
976
*
@@ -1009,24 +991,55 @@ function spliceTraces(gd, update, indices, maxPoints, lengthenArray, spliceArray
1009
991
Plotly . extendTraces = function extendTraces ( gd , update , indices , maxPoints ) {
1010
992
gd = Lib . getGraphDiv ( gd ) ;
1011
993
1012
- var undo = spliceTraces ( gd , update , indices , maxPoints ,
994
+ function updateArray ( target , insert , maxp ) {
995
+ var newArray , remainder ;
1013
996
1014
- /*
1015
- * The Lengthen operation extends trace from end with insert
1016
- */
1017
- function ( target , insert ) {
1018
- return target . concat ( insert ) ;
1019
- } ,
997
+ if ( Lib . isTypedArray ( target ) ) {
998
+ if ( maxp < 0 ) {
999
+ var none = new target . constructor ( 0 ) ;
1000
+ var both = concatTypedArray ( target , insert ) ;
1020
1001
1021
- /*
1022
- * Window the trace keeping maxPoints, counting back from the end
1023
- */
1024
- function ( target , maxPoints ) {
1025
- return target . splice ( 0 , target . length - maxPoints ) ;
1026
- } ) ;
1002
+ if ( maxp < 0 ) {
1003
+ newArray = both ;
1004
+ remainder = none ;
1005
+ } else {
1006
+ newArray = none ;
1007
+ remainder = both ;
1008
+ }
1009
+ } else {
1010
+ newArray = new target . constructor ( maxp ) ;
1011
+ remainder = new target . constructor ( target . length + insert . length - maxp ) ;
1012
+
1013
+ if ( maxp === insert . length ) {
1014
+ newArray . set ( insert ) ;
1015
+ remainder . set ( target ) ;
1016
+ } else if ( maxp < insert . length ) {
1017
+ var numberOfItemsFromInsert = insert . length - maxp ;
1018
+
1019
+ newArray . set ( insert . subarray ( numberOfItemsFromInsert ) ) ;
1020
+ remainder . set ( target ) ;
1021
+ remainder . set ( insert . subarray ( 0 , numberOfItemsFromInsert ) , target . length ) ;
1022
+ } else {
1023
+ var numberOfItemsFromTarget = maxp - insert . length ;
1024
+ var targetBegin = target . length - numberOfItemsFromTarget ;
1027
1025
1028
- var promise = Plotly . redraw ( gd ) ;
1026
+ newArray . set ( target . subarray ( targetBegin ) ) ;
1027
+ newArray . set ( insert , numberOfItemsFromTarget ) ;
1028
+ remainder . set ( target . subarray ( 0 , targetBegin ) ) ;
1029
+ }
1030
+ }
1031
+ } else {
1032
+ newArray = target . concat ( insert ) ;
1033
+ remainder = ( maxp >= 0 && maxp < newArray . length ) ?
1034
+ newArray . splice ( 0 , newArray . length - maxp ) :
1035
+ [ ] ;
1036
+ }
1037
+
1038
+ return [ newArray , remainder ] ;
1039
+ }
1029
1040
1041
+ var undo = spliceTraces ( gd , update , indices , maxPoints , updateArray ) ;
1042
+ var promise = Plotly . redraw ( gd ) ;
1030
1043
var undoArgs = [ gd , undo . update , indices , undo . maxPoints ] ;
1031
1044
Queue . add ( gd , Plotly . prependTraces , undoArgs , extendTraces , arguments ) ;
1032
1045
@@ -1036,24 +1049,54 @@ Plotly.extendTraces = function extendTraces(gd, update, indices, maxPoints) {
1036
1049
Plotly . prependTraces = function prependTraces ( gd , update , indices , maxPoints ) {
1037
1050
gd = Lib . getGraphDiv ( gd ) ;
1038
1051
1039
- var undo = spliceTraces ( gd , update , indices , maxPoints ,
1052
+ function updateArray ( target , insert , maxp ) {
1053
+ var newArray , remainder ;
1040
1054
1041
- /*
1042
- * The Lengthen operation extends trace by appending insert to start
1043
- */
1044
- function ( target , insert ) {
1045
- return insert . concat ( target ) ;
1046
- } ,
1055
+ if ( Lib . isTypedArray ( target ) ) {
1056
+ if ( maxp <= 0 ) {
1057
+ var none = new target . constructor ( 0 ) ;
1058
+ var both = concatTypedArray ( insert , target ) ;
1047
1059
1048
- /*
1049
- * Window the trace keeping maxPoints, counting forward from the start
1050
- */
1051
- function ( target , maxPoints ) {
1052
- return target . splice ( maxPoints , target . length ) ;
1053
- } ) ;
1060
+ if ( maxp < 0 ) {
1061
+ newArray = both ;
1062
+ remainder = none ;
1063
+ } else {
1064
+ newArray = none ;
1065
+ remainder = both ;
1066
+ }
1067
+ } else {
1068
+ newArray = new target . constructor ( maxp ) ;
1069
+ remainder = new target . constructor ( target . length + insert . length - maxp ) ;
1070
+
1071
+ if ( maxp === insert . length ) {
1072
+ newArray . set ( insert ) ;
1073
+ remainder . set ( target ) ;
1074
+ } else if ( maxp < insert . length ) {
1075
+ var numberOfItemsFromInsert = insert . length - maxp ;
1076
+
1077
+ newArray . set ( insert . subarray ( 0 , numberOfItemsFromInsert ) ) ;
1078
+ remainder . set ( insert . subarray ( numberOfItemsFromInsert ) ) ;
1079
+ remainder . set ( target , numberOfItemsFromInsert ) ;
1080
+ } else {
1081
+ var numberOfItemsFromTarget = maxp - insert . length ;
1054
1082
1055
- var promise = Plotly . redraw ( gd ) ;
1083
+ newArray . set ( insert ) ;
1084
+ newArray . set ( target . subarray ( 0 , numberOfItemsFromTarget ) , insert . length ) ;
1085
+ remainder . set ( target . subarray ( numberOfItemsFromTarget ) ) ;
1086
+ }
1087
+ }
1088
+ } else {
1089
+ newArray = insert . concat ( target ) ;
1090
+ remainder = ( maxp >= 0 && maxp < newArray . length ) ?
1091
+ newArray . splice ( maxp , newArray . length ) :
1092
+ [ ] ;
1093
+ }
1056
1094
1095
+ return [ newArray , remainder ] ;
1096
+ }
1097
+
1098
+ var undo = spliceTraces ( gd , update , indices , maxPoints , updateArray ) ;
1099
+ var promise = Plotly . redraw ( gd ) ;
1057
1100
var undoArgs = [ gd , undo . update , indices , undo . maxPoints ] ;
1058
1101
Queue . add ( gd , Plotly . extendTraces , undoArgs , prependTraces , arguments ) ;
1059
1102
0 commit comments