-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathUniversal_Inventory_System.txt
1038 lines (827 loc) · 136 KB
/
Universal_Inventory_System.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
*** Look into whether <<nobr>> or the "nobr" tag break how <<UInvSet>> works.
*** Make a way to add static items by type and/or tag?
*** Update linear-gradient stuff:
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2D2D2D), color-stop(100%, #6b6b6b));
background-image: -ms-linear-gradient(top, #C4CACC 0%, #2D2D2D 2px, #6b6b6b 100%);
background-image: -o-linear-gradient(top, #C4CACC 0%, #2D2D2D 2px, #6b6b6b 100%);
background-image: -moz-linear-gradient(top, #C4CACC 0%, #2D2D2D 2px, #6b6b6b 100%);
background-image: -webkit-linear-gradient(top, #C4CACC 0%, #2D2D2D 2px, #6b6b6b 100%);
background-image: linear-gradient(to bottom, #C4CACC 0%, #2D2D2D 2px, #6b6b6b 100%);
Universal Inventory System (UInv)
=================================
♦ fully unit tested and regression test available
+ written and tested
* written and tested, but incomplete
/ written, but incomplete and not tested
- written, but not tested
x needs to be updated to handle pockets properly
A needs to be modified to support ItemTag arrays
Bag functions: (BagName must be unique. BagPropertyName must be unique for its bag.)
--------------
+ AddBag(BagName, [DefaultBagType] {, StartDepth, CurrentDepth})
♦ AddToBagPropertyValue(BagName, BagPropertyName, Amount)
♦ BagExists(BagName/Array) = t/f
- BagHasAllProperties(BagName, BagPropertyNameArray) = t/f if all of the bag's properties are listed in BagPropertyNameArray
♦ BagHasProperty(BagName, BagPropertyName/Array) = t/f
- BagMatchesDefault(BagName) = t/f depending on whether it is an exact match for its default bag type
♦ BagPropertyCount(BagName) = number of BagName's properties, or undefined if there was an error.
- CopyAllItemsToBag(SourceBagName, DestinationBagName) Copies all items from source to destination.
+ CopyBag(ExistingBagName, NewBagName)
♦ CopyBagProperty(SourceBagName, DestinationBagName, BagPropertyName/Array) overwrites existing properties
♦ CreateBag(BagName) (Sets UInvTouched to false)
+ DeleteBag(BagName/Array)
♦ DeleteBagProperty(BagName, BagPropertyName)
♦ EmptyBag(BagName)
♦ GetBagByProperty(BagPropertyName) = get a random BagName that has property BagPropertyName
♦ GetBagCount() = the number of bags
♦ GetBagCountByDefaultType() = the number of unique bag types, bags with no default bag type count as unique bag types
+ GetBagObject(BagName) = the full bag object (including UInvDefaultBagType)
♦ GetBagPropertyArray(BagName) = array of all properties a bag has.
♦ GetBagPropertyObject(BagName) = object of all properties/values a bag has.
♦ GetBagPropertyValue(BagName, BagPropertyName) [alias: GetBagProp] !!! add more aliases !!!
♦ GetBagsArrayByProperty(BagPropertyName, [BagNameArray]) = array of BagNames that have property BagPropertyName (within the set of BagNameArray if parameter is included)
♦ GetBagsArray() = an array of all bag names [alias: BagArray]
♦ GetBagsArrayWherePropertyEquals(BagPropertyName, Value) = array of BagNames where BagPropertyName value == Value
♦ GetBagsArrayWherePropertyGreaterThan(BagPropertyName, Value) = array of BagNames where BagPropertyName value > Value
♦ GetBagsArrayWherePropertyLessThan(BagPropertyName, Value) = array of BagNames where BagPropertyName value < Value
- GetBagsArrayWithAllProperties(BagPropertyNameArray) = array of all bags which have all of the properties in BagPropertyNameArray (per the ArrayHasAllBagProperties function)
- GetBagsArrayWithItem(ItemName, [BagArray]) = array of BagNames that have item (limited to items in BagArray bags if BagArray is passed to function)
♦ GetBagsDefaultType(BagName)
♦ GetBagWherePropertyEquals(BagPropertyName, Value) = BagName (get a random BagName where BagPropertyName == Value)
♦ GetBagWherePropertyGreaterThan(BagPropertyName, Value) = BagName (get a random BagName where BagPropertyName > Value)
♦ GetBagWherePropertyLessThan(BagPropertyName, Value) = BagName (get a random BagName where BagPropertyName < Value)
♦ GetBagWithHighestPropertyValue(BagPropertyName, [BagNameArray]) = BagName (bags without BagPropertyName are ignored); randomly pick one of the highest if multiple bags are tied for highest
♦ GetBagWithLowestPropertyValue(BagPropertyName, [BagNameArray]) = BagName (bags without BagPropertyName are ignored); randomly pick one of the lowest if multiple bags are tied for lowest
♦ GetCurrentBagName() Gets the current bag name if there is one, otherwise returns "".
+ GetDefaultBagObject(DefaultBagType, [PropertiesOnly]) (if PropertiesOnly is true, only return the default properties)
- GetTotalBagPropertyValue(BagPropertyName, [BagNameArray]) gets the total value of BagPropertyName across all bags, or across all bags in BagNameArray
+ GetUniqueBagName() returns a name not used by any bag currently ("bag0ffd39" 0-255 in hex * 3)
- MergeBags(SourceBagName, DestinationBagName) Moves all items from source to destination and deletes source.
- MoveAllItemsToBag(SourceBagName/Array, DestinationBagName) Moves all items from source(s) to destination.
- MoveBagPropertyValueToBag(SourceBagName, SourceBagPropertyName, DestinationBagName, [DestinationBagPropertyName], [Amount], [MinimumValue], [MaximumValue], [DeletionValue], [DeletionType])
- MoveItemPropertyValueToBag(SourceBagName, SourceItemName, SourceItemPropertyName, DestinationBagName, [DestinationBagPropertyName], [Amount], [MinimumValue], [MaximumValue], [DeletionValue], [DeletionType])
+ RenameBag(CurrentBagName, NewBagName)
♦ SetCurrentBagName(BagName)
♦ SetBagPropertyValue(BagName/Array, BagPropertyName, Value) [alias: SetBagValue] add property if it doesn't exist
♦ SetBagsDefaultType(BagName, DefaultBagType)
♦ SetBagTouched(BagName/Array) sets bag(s) as touched.
♦ SetBagUntouched(BagName/Array) sets bag(s) as untouched.
♦ WasTouched(BagName) = Whether items in bag have changed since creation or since Untouched was last set.
Complete!!! (49 functions)
Add item blacklists and whitelists?
Add maximum capacities? (the sum of property X on all items maxes out at Y, then no more may be added)
Add some sort of "Try" functionality to support the two above items?
*** Do the following in more BagName/Array functions to eliminate wasting time on duplicate bags???:
BagName = UInv.getUniqueArray(BagName);
Pocket/Container functions: (These are bags/pockets which are "inside" items/containers.)
---------------------------
- AddExistingBagAsPocket(BagName, ItemName, PocketName, PocketBagName) (avoids recursion)
+ AddPocket(BagName, ItemName, PocketName, [DefaultBagType] {, StartDepth, CurrentDepth}) adds a pocket named PocketName of a particular bag type to an item
- BagHasSpecificItem(MainBagName, ItemBagName, ItemName) = whether MainBagName contains ItemBagName+ItemName, or undefined on error. (Only needed if you're using pockets.)
- BagIsPocket(BagName) = number of items it's a pocket for (uses GetPocketContainerArray)
- ContainerHasItem(ContainerBagName, ContainerName, ItemName) = number of items named ItemName in all of container's pockets (does not include the container itself in that count)
- ContainerHasPocketBag(ContainerBagName, ContainerName, BagName) = returns whether BagName exists anywhere within the container, or undefined on error
- CreatePocket(BagName, ItemName, PocketName) creates an empty pocket named PocketName attached to an item
- DeletePocket(BagName, ItemName, PocketName) deletes the pocket named PocketName on an item
- GetAllBagPockets(BagName/Array, [NoSourceBag]) = array of all pockets' and sub-pockets's BagNames, plus BagName (unless NoSourceBag == true), or undefined on error (all BagNames returned in the array will be unique within that array)
- GetAllContainerPockets(ContainerBagName, ContainerName) = array of all pockets' and sub-pockets's BagNames, or undefined on error (all BagNames returned in the array will be unique within that array)
- GetContainerIndex(BagName, PocketName) = Index of container in a bag's UInvContainer array, -1 if not found, -999 on error.
- GetItemPocketBagArray(BagName, ItemName) = an array of bag names which the item has as pockets, returns [] if it has none, or undefined on error.
+ GetItemPocketBagName(BagName, ItemName, [PocketName]) = bag name of PocketName in an item, or a random pocket bag name if PocketName isn't specified
- GetItemPocketNameArray(BagName, ItemName) = an array of pocket names which the item has as pockets, returns [] if it has none, or undefined on error.
- GetItemPocketObject(BagName, ItemName) = an object of { "PocketName": "BagName", ... } from item
- GetPocketBagContainerArray(PocketBagName) = array of { BagName : "name", ItemName : "name", PocketName : "name" } -or- [] if it's not a pocket
- GetPocketBagsPocketName(BagName, ItemName, PocketBagName) = PocketName
- GetPocketDepth(BagName) = 0 if it's a bag, 1 if it's a pocket, 2 if it's a pocket within a pocket, etc... or undefined on error.
+ ItemHasPocket(BagName, ItemName, [PocketName]) = number of pockets directly on item (uses GetItemPocketArray) -or- if item has a pocket named PocketName (if the PocketName parameter is set)
- MoveItemFromPocket(ContainerBagName, ContainerItemName, PocketName, ItemName, DestinationBagName, [Quantity])
+ MoveItemToPocket(SourceBagName, SourceItemName, DestinationBagName, DestinationItemName, DestinationPocketName, [Quantity])
- MovePocket(SourceBagName, SourceItemName, SourcePocketName, DestinationBagName, DestinationItemName, [DestinationPocketName])
- UnlinkPocketBagFromContainer(BagName, ContainerName, PocketBagName) Unlinks a bag from the given container item.
- UnlinkPocketFromContainer(BagName, ContainerName, [PocketName]) Unlinks a pocket from its container item, or all pockets if PocketName isn't set.
In pocket/container functions: ("pockets" are bags connected to "containers", "containers" are items that are connected to "pockets")
• the UInvQuantity must be 1 to have a pocket, if it's stacked it will become unstacked when a pocket is added
• items with pockets do not stack and cannot be merged
• recursive pockets are not allowed (you can't put a container inside its own pocket, directly or indirectly)
• automatically handles deleted containers and pockets
• checking the contents of bags should also check item pockets (?)
• getting something from a bag should check pockets if it's not in the bag itself (?)
• "hidden" tags on pockets? (So that a list of all items won't include/affect items in hidden pockets.)
• check all functions to make sure the relationship between containers and pockets aren't broken
• mark bags as touched if added/removed pockets have any contents
• prevent created items and bags from having pockets greater depth than MaximumPocketDepth (i.e. keep a suit item from having a default pocket which has a suit in it, and that suit has a pocket with a suit in it, ... ad infinitum)
Item gets: UInvPocket object = { "PocketName": "BagName", ... }
Bag gets: UInvContainer array = [ { ContainerBagName: "name", ContainerName: "name", PocketName: "name" }, ... ]
(Trigger bag "touched" events? Should "touched" events trickle up from pockets?)
(How to deal with quantities in AddItem and CopyItem?)
(Add find by DefaultType and Property as well? - Make sure existing functions can do this?)
(Figure out a way to combine items that all have empty pockets?)
*** Make sure that UInvQuantity can't be increased on items with pockets
Complete!!! (24 functions)
Item functions: (ItemName must be unique within a bag and in the GetDefaultItemObject function.)
---------------
+ AddItem(BagName, ItemType, [Quantity], [NewItemName] {, StartDepth, CurrentDepth}) pulls item from GetDefaultItemObject, default Quantity = 1
AddItemCapped(BagName, ItemType, [MaxItems], [Quantity], [NewItemName]) adds items up to MaxItems; default MaxItems and Quantity = 1; returns current item quantity
- AddItems(BagName, ItemArray)
- AddToAllItemsPropertyValue(BagName, ItemPropertyName, Amount) adds amount to property's value for all items that have ItemPropertyName
+ AddToItemPropertyValue(BagName, ItemName, ItemPropertyName, Amount) adds amount to property's value
- BagHasAllItems(BagName/Array, ItemNameArray) = t/f if bag/s has/have all of the items in ItemNameArray
- BagHasAnyItem(BagName/Array, ItemNameArray) = t/f if bag/s has/have any of the items in ItemNameArray
+ BagHasItem(BagName/Array, ItemName) = Quantity [alias: GetItemQuantity, HasItem, ItemQuantity]
+ CopyItem(SourceBagName, DestinationBagName, ItemName, [Quantity], [NewItemName]) Quantity = amount to add, default to same quantity, NewItemName must be used if source and destination bags are the same
- CopyItemsByProperty(SourceBagName, DestinationBagName, ItemProperty, [Value]) copy all items in bag that have the ItemProperty, or ItemProperty === Value if Value is passed
- CreateItem(BagName, ItemName, [Quantity]) create new item instead of pulling from GetDefaultItemObject function
+ DeleteItem(BagName, ItemName/Array, [Quantity]) if no Quantity then remove all.
+ DeleteItemProperty(BagName/Array, ItemName, [ItemPropertyName]) cannot delete ItemPropertyName "UInvQuantity", "UInvDefaultItemType", or "UInvPocket", also deleting a property of a default item will return that property to its default value
- DeleteItemsByProperty(BagName, ItemProperty, [Value]) delete all items in bag that have the ItemProperty, or ItemProperty === Value if Value is passed
- GetAllPropertyValues(BagName, ItemPropertyName) = [ array of all unique values that property has ]
- GetBagItemArrayWhereItemPropertyEquals(BagNameArray, ItemPropertyName, Value) = array of [[BagName, ItemName], ...] where the item's ItemPropertyName property == Value
+ GetCurrentItemName(ItemName) Gets the current item name if there is one, otherwise returns "".
+ GetDefaultItemObject(ItemType) = item object
- GetDefaultItemPropertyValue(ItemName, ItemPropertyName) = default value for item's property
- GetItemByProperty(BagName, ItemPropertyName) = get a random ItemName that has property ItemPropertyName
+ GetItemByType(BagName, ItemType) = get a random ItemName that is of type ItemType
+ GetItemCount(BagName/Array) = the number of unique items in each bag (ignores Quantity)
- GetItemCountByDefaultType(BagName/Array) = the number of unique item types in each bag (ignores Quantity), items with a default item type of "-" are each counted as separate unique item types
- GetItemCountByFunction(BagName/Array, CountFunction) = returns the sum of the values returned by function (function is passed BagName)
- GetItemCountFull(BagName/Array) = the total number of items in bag(s) (Quantity included)
- GetItemCountFullByDefaultType(BagName/Array, DefaultItemType) = the total number of items in bag(s) (Quantity included) of that DefaultItemType
- GetItemCountWherePropertyEquals(BagName/Array, ItemPropertyName, Value)
- GetItemCountWherePropertyGreaterThan(BagName/Array, ItemPropertyName, Value)
- GetItemCountWherePropertyLessThan(BagName/Array, ItemPropertyName, Value)
+ GetItemObject(BagName, ItemName) = item object
+ GetItemPropertiesArray(BagName, ItemName) = Array of all properties on item in bag
+ GetItemPropertyCount(BagName, ItemName) = number of ItemPropertyNames ItemName has (inc. quantity)
- GetItemPropertyValue(BagName, ItemName, ItemPropertyName) = Value, undefined if PropertyName doesn't exist
- GetItemPropertyValueObject(BagName, ItemPropertyName) = { ItemName : ItemPropertyName's value, ... } (items that don't have ItemPropertyName are ignored)
- GetItemsAndQuantitiesObject(BagName) = { item1: quantity1, item2: quantity2, etc... } in a bag
+ GetItemsArray(BagName) = array of item objects' names
- GetItemsArrayByFunction(BagName, SelectionFunction) = array of items where function is true (function is passed BagName and ItemName strings)
- GetItemsArrayByProperty(BagName, ItemPropertyName) = array of ItemNames that have property ItemPropertyName
- GetItemsArrayByType(BagName, ItemType) = array of ItemNames that are of type ItemType
- GetItemsArraySortedByFunction(BagName, SortFunction) returns an array of ItemNames sorted by the function.
- GetItemsArraySortedByProperty(BagName, [ItemPropertyName]) returns an array of ItemNames sorted by the items' names unless ItemPropertyName parameter is used, in which case it's sorted by that property's value (if the property exists; only sorting by numbers and strings are supported for that)
- GetItemsArrayWhereItemNameContains(BagName, SubString) = array of ItemNames where item's name contains the substring; use RegExp matching?
- GetItemsArrayWherePropertyEquals(BagName, ItemPropertyName, Value) = array of ItemNames where property == Value
- GetItemsArrayWherePropertyGreaterThan(BagName, ItemPropertyName, Amount) = array of ItemNames where property value > Amount
- GetItemsArrayWherePropertyLessThan(BagName, ItemPropertyName, Amount) = array of ItemNames where property value < Amount
- GetItemsArrayWherePropertyValueContains(BagName, ItemPropertyName, SubString, [CaseSensitive]) = array of ItemNames where property contains the substring; CaseSensitive defaults to false; use RegExp matching?
- GetItemsArrayWithAllProperties(BagName, ItemPropertyNameArray) = array of all items which have all of the properties in ItemPropertyNameArray (per the ArrayHasAllItemProperties function)
- GetItemsArrayWithoutProperties(BagName, ItemPropertyName/Array) = an array of ItemNames in BagName that do not have any ItemPropertyName/Array as any of their properties
- GetItemsDefaultType(BagName, ItemName) Returns item's default item type if it has one, "-" if it doesn't, or undefined on error.
- GetItemWherePropertyEquals(BagName, ItemPropertyName, Value) = get a random ItemName where property == Value, if ItemPropertyName points to an array, see if Value is in that array, returns "" if none found
- GetItemWherePropertyGreaterThan(BagName, ItemPropertyName, Amount) = random ItemName where property value > Amount
- GetItemWherePropertyLessThan(BagName, ItemPropertyName, Amount) = random ItemName where property value < Amount
- GetItemWithHighestPropertyValue(BagName, ItemPropertyName) = ItemName (items without ItemPropertyName are ignored)
- GetItemWithLowestPropertyValue(BagName, ItemPropertyName) = ItemName (items without ItemPropertyName are ignored)
- GetMatchingItemsArray(BagName, ItemName, SearchBag, [PropertyExceptionArray]) = array of all items in SearchBag that match ItemName (per the ItemsMatch function), not including excluded property names
- GetObjectOfItemPropertyValues(BagName, ItemPropertyName) return { ItemName : ItemPropertyName's value, ... }
- GetRandomItem(BagName) = random ItemName in BagName
- GetRandomItemPropertyValue(BagName, ItemPropertyName) = value of the ItemProperty for a random item in BagName
- GetRandomItemValue(BagName, ItemPropertyName) = a random value of an item's ItemPropertyName in a bag if it has that property. Sets that item as the current item
- GetTotalItemPropertyValue(BagName, ItemPropertyName) = total of all items' ItemPropertyName values (multiplied by UInvQuantity) added together (all values must be numbers; items without ItemPropertyName are treated as having a value of zero)
+ GetUniqueItemName() returns a name not used by any item currently ("item0ffd39" 0-255 in hex * 3)
- GetUniqueItemPropertyValuesArray(BagName/Array, ItemPropertyName) returns an array of unique values for all items with ItemPropertyName in all bags in BagName/Array (use GetUniqueItemTagsArray instead for properties which have array values)
+ ItemExists(ItemName) = t/f, checks GetDefaultItemObject function and all bags for ItemName
- ItemHasAllProperties(BagName, ItemName, ItemPropertyNameArray) = t/f if all of the item's properties are listed in ItemPropertyNameArray
- ItemHasAnyProperties(BagName, ItemName, ItemPropertyNameArray) = t/f if any of the item's properties are listed in ItemPropertyNameArray
+ ItemHasProperty(BagName, ItemName, ItemPropertyName) = t/f
- ItemPropertyHasValue(BagName, ItemName, ItemPropertyName, Value) = t/f if item's property ==/contains Value
+ ItemsMatch(BagName1, ItemName1, BagName2, ItemName2, [PropertyExceptionArray]) = t/f if all properties exist and match, except quantity, UInvDefaultItemType, and UInvCell, plus any properties in PropertyExceptionArray if included
+ MoveItem(SourceBagName, DestinationBagName, ItemName, [Quantity], [NewItemName]) if no Quantity parameter then move all
MoveItems(SourceBagName, DestinationBagName, ItemNameArray, [Quantity]) moves all items in the item array (or Quantity of each item) from source to destination, skipping any items that don't exist in the source, returns number of item types moved(?)
- MoveBagPropertyValueToItem(SourceBagName, SourceBagPropertyName, DestinationBagName, DestinationItemName, [DestinationItemPropertyName], [Amount], [MinimumValue], [MaximumValue], [DeletionValue], [DeletionType])
- MoveItemPropertyValueToItem(SourceBagName, SourceItemName, SourceItemPropertyName, DestinationBagName, DestinationItemName, [DestinationItemPropertyName], [Amount], [MinimumValue], [MaximumValue], [DeletionValue], [DeletionType])
- MoveItemsByProperty(SourceBagName, DestinationBagName, ItemProperty, [Value]) move all items in bag that have the ItemProperty, or ItemProperty === Value if Value is passed
+ RenameItem(BagName, CurrentItemName, NewItemName, [Quantity]) Quantity for partial stacks of items, copy in default item properties
- RenameItemProperty(BagName, ItemName, CurrentItemPropertyName, NewItemPropertyName) Renames item property. Returns true if it succeeds. Bag is not touched.
- ResetItemProperties(BagName/Array, ItemName, [DefaultItemName]) removes all properties then loads default
+ RestackItems(BagName) Attempts to restack any items that may be stacked incorrectly.
+ SetCurrentItemName(ItemName)
+ SetItemPropertyValue(BagName, ItemName, ItemPropertyName, Value) add property if it doesn't exist
- SetItemPropertyValues(BagName, ItemName, ValuesObject) Updates and/or adds values to multiple properties on an item
- SetItemQuantity(BagName, ItemName, Quantity) Quantity must be a positive integer
- SetItemsDefaultType(BagName, ItemName, DefaultItemType)
- SetItemsPropertyValue(BagName, ItemPropertyName, Value) sets the value of ItemPropertyName on all items in a bag
+ SwapItems(BagName1, ItemName1, BagName2, ItemName2, [ExceptItemPropertyName/array]) swaps two items, optionally keeps certain item properties un-swapped
- SwapItemsProperties(BagName1, ItemName1, BagName2, ItemName2, ItemPropertyName/array) Swaps the given properties of two items. Returns true on success, false on error.
"Bind" functions, so that changing one property value on one item, changes another value on another item?
Have the "Bind" functions call a function/widget and tell it what property changed, what it changed from, and what it changed to
Do not trigger a "Bind" call if the value was "set" but not changed. (So they don't loop back and forth.)
(option to "copy-and-link" items, so that any property changes to one will happen to all linked items, so that all stay identical?)
(make more ...CountFull... functions? Or add a parameter to existing functions instead?)
(add the ability to test by date? e.g. is property X > someDate + days + hours + minutes?)
2 more to complete! (85 functions)
Tag functions:
--------------
- AddBagTag(BagName/Array, BagPropertyName, BagTag/Array)
- AddItemTag(BagName/Array, ItemName, ItemPropertyName, ItemTag/Array)
- ArrayHasAllItemTags(BagName, ItemName, ItemPropertyName, ItemTagArray) = t/f if all of the item's tags exist in ItemTagArray
- BagHasAllBagTags(BagName, BagPropertyName, BagTagArray) = t/f
- BagHasAllItemTags(BagName, ItemPropertyName, ItemTagArray) = t/f
- BagHasAnyBagTag(BagName, BagPropertyName, BagTagArray) = t/f
- BagHasAnyItemTag(BagName, ItemPropertyName, ItemTagArray) = t/f
- BagHasItemByBagTag(BagPropertyName, BagTag, ItemName) = true if any bags with BagPropertyName/BagTag have item
- BagHasAllItemsByBagTag(BagPropertyName, BagTag, ItemNameArray) = t/f if any bag with BagPropertyName/BagTag has all of the items in ItemNameArray
- BagHasAnyItemByBagTag(BagPropertyName, BagTag, ItemNameArray) = t/f if any bag with BagPropertyName/BagTag has any of the items in ItemNameArray
A BagHasItemByItemTag(BagName, ItemPropertyName, ItemTag) = t/f
- BagHasItemWithAllItemTags(BagName, ItemPropertyName, ItemTag/Array) = t/f
- BagHasItemWithAnyItemTag(BagName, ItemPropertyName, ItemTag/Array) = t/f
- BagHasItemWithoutAllItemTags(BagName, ItemPropertyName, ItemTag/Array) = t/f
- BagHasItemWithoutAnyItemTags(BagName, ItemPropertyName, ItemTag/Array) = t/f
- BagHasTag(BagName, BagPropertyName, BagTag) = t/f
A CopyItemsByItemTag(SourceBagName, DestinationBagName, ItemPropertyName, ItemTag) copy all items in bag that have the ItemTag
- DeleteBagTag(BagName/Array, BagPropertyName, BagTag/Array)
A DeleteItemsByItemTag(BagName, ItemPropertyName, ItemTag) delete all items in bag that have the ItemTag
- DeleteItemTag(BagName/Array, ItemName, ItemPropertyName, ItemTag/Array)
- GetAllUniqueItemTagsArray(BagName, ItemPropertyName) = array of all unique item tags in the ItemPropertName property for all items in bag
- GetBagsArrayByBagTag(BagPropertyName, BagTag) = array of bag names that have BagTag in BagPropertyName
- GetBagsArrayWithBothBagTags(BagPropertyName1, BagTag1, BagPropertyName2, BagTag2) = array of bag names
- GetBagsArrayWithItemByBagTag(BagPropertyName, BagTag, ItemName) = array of bag names from bags with tag and item
- GetBagTagQuantityObject(BagName, BagPropertyName) = { "UniqueBagTag1" : QuantityOfBagTag1, ... }
- GetFullItemCountByAllItemTags(BagName, ItemPropertyName, TagArray) = full number of items with all tags in that property
- GetFullItemCountByAnyItemTag(BagName, ItemPropertyName, TagArray) = full number of items with any of those tags in that property
- GetItemsArrayByAllItemTags(BagName, ItemPropertyName, ItemTagArray) = array of item names with all tags
- GetItemsArrayByAnyItemTag(BagName, ItemPropertyName, ItemTagArray) = array of item names with any tags
A GetItemsArrayByItemTag(BagName, ItemPropertyName, ItemTag) = array of item names that have tag
- GetItemsArrayWithAllItemTags(BagName, ItemPropertyName, ItemTagArray) = array of all items which have all of their tags in ItemTagArray (per the ArrayHasAllItemTags function)
A GetItemsArrayWithBothItemTags(BagName, ItemPropertyName1, ItemTag1, ItemPropertyName2, ItemTag2) = array of item names
- GetItemsArrayWithMostItemTags(BagName, ItemPropertyName, ItemTagArray) = array of all items that are tied for the most ItemTags in ItemPropertyName
- GetItemsArrayWithoutAllItemTags(BagName, ItemPropertyName, ItemTagArray) = array of item names without all of these tags
- GetItemsArrayWithoutAnyItemTags(BagName, ItemPropertyName, ItemTagArray) = array of item names without any of these tags
A GetItemTagCount(BagName, ItemName, ItemPropertyName, Tag) = the number of times Tag is found in that tag array
- GetItemTagQuantityObject(BagName, ItemName, ItemPropertyName) = { "UniqueItemTag1" : QuantityOfItemTag1, ... }
- GetMissingBagTagsArray(BagName, BagPropertyName, BagTagArray) returns an array of all tags in BagTagArray which were not found on the BagPropertyName for that bag
- GetMissingItemTagsArray(BagName, ItemName, ItemPropertyName, ItemTagArray) returns an array of all tags in ItemTagArray which were not found on the items' ItemPropertyName in that bag
- GetRandomBagTagFromRange(BagName, BagPropertyName, HighIndex, [LowIndex = 0]) Returns a random tag from LowIndex to HighIndex (inclusive)
- GetRandomItemTagFromRange(BagName, ItemName, ItemPropertyName, HighIndex, [LowIndex = 0]) Returns a random tag from LowIndex to HighIndex (inclusive)
- GetUniqueBagTagsArray(BagPropertyName, [BagName/Array]) = [ "UniqueTag1", ... ]
- GetUniqueItemTagsArray(ItemPropertyName, [BagName/Array]) = [ "UniqueTag1", ... ]
- ItemHasAllTags(BagName, ItemName, ItemPropertyName, ItemTagArray) = t/f
- ItemHasAnyTag(BagName, ItemName, ItemPropertyName, ItemTagArray) = t/f
A ItemHasTag(BagName, ItemName, ItemPropertyName, ItemTag) = t/f
A MoveItemsByItemTag(SourceBagName, DestinationBagName, ItemPropertyName, ItemTag) move all items in bag that have the ItemTag
- SetBagTag(BagName/Array, BagPropertyName, BagTag/Array, Enabled) adds or removes all tags based on Enabled
- SetItemTag(BagName/Array, ItemName, ItemPropertyName, ItemTag/Array, Enabled) adds or removes all tags based on Enabled
*** Have any "sort" functions sort numbers first, then strings
(add options to shuffle around or sort tags)
8(?) functions to modify (49 functions)
Display functions and elements:
-------------------------------
- AddEventHandler(Group, Event, Handler, [Options]) Adds an event handler. If that exact handler already exists it returns the existing HandleID, otherwise returns a new HandleID on success, or "false" on error.
- CallEventHandler(Group, Event, Values) The same as CallEventHandlerEx, but all handler returns are combined into a single generic object.
- CallEventHandlerEx(Group, Event, Values) Triggers any matching event handlers and passes the Values object to them. Returns an array of results from all triggered handlers (results will either be generic objects or undefined), returns "false" on error.
- DecrementUpdateLock() Reduces the LockCount by 1
- DeleteEventHandler(Group, Event, Handler/HandlerID, [Options]) Deletes any matching event handlers. Returns the number of deleted handlers, or false on error.
- DisplayArray(YourArray, [EmptyString], [SeparatorString], [ConjunctionString], [UseAPNumbers])
* DisplayItemList(BagName, [PluralItemPropertyName], [EmptyString], [SeparatorString], [ConjunctionString], [SingleItemPropertyName])
- DisplayRadialMenu(WedgeItems, Position, Handler, Options)
- FixTableCells(BagName, UInvTable) Makes sure each item is assigned a unique cell.
GetElementVisibility(element) = % visible (use Intersection Observer API https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API )
- GetEventHandlerByID(Group, Event, HandlerID) Returns a UInvEventHandler object if one exists, or "null" if none exist, or "undefined" on error.
- GetMatchingEventHandlersArray(Group, Event, [Options], [Handler]) Returns an array of the handler ID of all handlers that match the parameters passed in (Handler and/or Options are optional), or "false" on error.
+ GetUpdateLocks() = the number of locks on updates. Does not prevent manual updates via. UInv.UpdateDisplay().
- IncrementUpdateLock() Increases the LockCount by 1
- UpdateDisplay([Container]) Updates the display of any UInv HTML elements, such as tables.
- UpdatesAreLocked() Returns whether automatic display updates are locked or not.
<<UInvDisplay>> (see below)
Clothing Mannequin
Dropdown List
Health Bars/Status Indicator (show icon and bar indicating various stats for things like health and mana bars)
Item Property Slider (BagName, Item, ItemPropertyName, MinVal, MaxVal, [Increment])
* Radial Menu
* Table (see "Tables:" notes below)
Toolbar (show a toolbar for triggering various things, such as showing the inventory, etc...)
Image rotation and mirroring?
etc...
9? items remaining. (16 functions + 8 display elements; 15 functions written + 2 display elements) (total will probably be 16-20 functions + 1 macro + 7 display elements)
<<UInvDisplay>>
Inventory:
^For:BagName:"backpack"
^Prop:"UInvQuantity" - ^Prop:"name" ^Link:Drop 1:DeleteItem(^Bag, ^Item, 1):ItemHasTag(^Bag, ^Item, "type", "undroppable"):
^/For
<</UInvDisplay>>
The above would loop through backpack, showing the quantity and name for each item, plus a link saying "Drop 1" which would delete 1 of that item as long as it didn't have "undroppable" in the array in its "type" property.
(Make it easy to do in table format. Make adding images easy.)
Display bugs:
• Radial menu in wrong location in IE 11.
• Table displayed slightly wrong in iPhone and iPad devices.
• On Android/Chrome the table is displayed behind UI bar and items can't be dragged.
• Laptops with touchscreen won't drag items in Firefox (but it works in Edge).
• Look into preventing console error spam.
(Tables: Make searchable (text search), sortable, filter by type, grouped on tabs by type, max-stacks/weight/slots? (individual or global max-stack; for max-weight show a bar which indicates how "full" the bag is))
(Tables: Make single or multiple items selectable. Make tables able to gain/lose focus. Event handling for keypresses based on table focus and selected items, so the developer can, for example, allow multiple items to be deleted using a keypress.)
(add a function to "equip/unequip"/"pickup/drop" items with text links)
(make a way to easily represent comparisons between items of the same type, e.g. show which weapon stats are better and/or worse than the currently equipped weapon)
(add item "health bars" for table)
(add a "shop" display; limited and unlimited stores)
(add a "clothing mannequin" for dressing and equipping characters: modal window overlay, left-hand box shows character info, property names are plain text with their values in boxes; right-hand box shows the "clothing mannequin" but with an arrow button that can be pressed/toggled to swap to a text description)
(have a way to add additional tabs to the sidebar to show various content (inventory, stats, skills, settings, etc..) without changing the active passage)
(If you move an item to a filled slot, have an option to swap items or destroy the destination item (with warning).)
(During testing: Make sure that the UpdateDisplay function is only called once when performing any change.)
$UInvEventHandlers groups and events:
All events: (the below properties are included in all other events)
-----------
+ Event
.eventGroup = this event's Group type
.eventType = this event's Event type
.handlerID = HandlerID which is triggering this event
"general" events:
-----------------
- MouseDown (sends MouseDown event)
> See: https://developer.mozilla.org/en-US/docs/Web/Events/mousedown
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
+ Event
(no additional properties besides .eventGroup, .eventType, and .handlerID)
+ Return
= { stopPropagation: true } (prevents event from further propagating)
> See: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
- MouseUp (sends MouseUp event)
> See: https://developer.mozilla.org/en-US/docs/Web/Events/mouseup
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
+ Event
(no additional properties besides .eventGroup, .eventType, and .handlerID)
+ Return
= { stopPropagation: true } (prevents event from further propagating)
> See: https://developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation
"bag" events:
-------------
- Touched (sends generic object) [handle multi-touch Start and Stop events?]
+ Event
.bagName = name of bag which is being marked as touched
.lockCount = the current display update "lock count"
+ Return
= { ignoreTouch: true } (prevents bag from being marked as Touched)
"table" events:
---------------
- Accept (sends element to be dropped)
NOTE: The table Accept event gets called many times during drag-and-drop actions.
It gets called once for each droppable element after DragStart and before DragStop,
plus once on each DragOver and DragOut event.
Any event handlers for this event should finish as quickly as possible.
+ Event
.srcBag = name of the bag the item was dragged from
.draggedItem = name of the dragged item
.destBag = name of the bag it's being dropped into
.droppedOnItem = if it's being dropped on another item it's the item's name, otherwise it's "" (an empty string)
.newCellNo = the UInvCell number in destBag that item is being dropped on
.acceptVal = the current choice of whether to accept or reject the drop
+ Return
= { acceptVal: true/false } (prevents allows/prevents drop action)
- DragStart (sends DragStart event)
+ Event
.srcBag = name of the bag the item was dragged from
.draggedItem = name of the dragged item
.ui = the DragStart event's UI object
+ Return (none)
- DragStop (sends DragStop event)
+ Event
.srcBag = name of the bag the item was dragged from
.draggedItem = name of the dragged item
.ui = the DragStop event's UI object
+ Return (none)
- Drop (sends Drop event)
+ Event
.srcBag = name of the bag the item was dragged from
.draggedItem = name of the dragged item
.oldCellNo = the UInvCell number in srcBag that the item was dragged from
.destBag = name of the bag it's being dropped into
.droppedOnItem = if it's being dropped on another item it's the item's name, otherwise it's "" (an empty string)
.newCellNo = the UInvCell number in destBag that item is being dropped on
.pos = { x: mouseLeft, y: mouseTop }
.ui = the Drop event's UI object
+ Return
= { overrideDefaultAction: true } (prevents default drop action)
= { openRadialMenu: true } (opens the radial menu, overrides the default drop action; requires .radialMenuWedgeItems and .radialMenuHandler)
= { radialMenuWedgeItems: UInvRadialWedgeItems } (see DisplayRadialMenu)
= { radialMenuHandler: Handler } (see DisplayRadialMenu)
= { radialMenuOptions: UInvRadialOptions } (see DisplayRadialMenu)
ToDo: add ItemClick and ItemDoubleClick events
"radialMenu" events:
--------------------
- Open (sends radial menu div element)
+ Event
.radialMenuWedgeItems = WedgeItems;
.radialMenuHandler = Handler;
.radialMenuOptions = Options;
+ Return
= { radialMenuWedgeItems: UInvRadialWedgeItems } (see DisplayRadialMenu)
= { radialMenuHandler: Handler } (see DisplayRadialMenu)
= { radialMenuOptions: UInvRadialOptions } (see DisplayRadialMenu)
- WedgeClick (sends MouseUp event)
+ Event
.wedgeID = The wedge's ID number (0 = center, 1 = top, 2... rotate clockwise)
.wedgeData = The wedge's data string
.wedgeDisabled = false
.srcBag = name of the bag the item was dragged from
.draggedItem = name of the dragged item
.oldCellNo = the UInvCell number in srcBag that the item was dragged from
.destBag = name of the bag it's being dropped into
.droppedOnItem = if it's being dropped on another item it's the item's name, otherwise it's "" (an empty string)
.newCellNo = the UInvCell number in destBag that item is being dropped on
.radialMenuWedgeItems = current radialMenuWedgeItems values
.pos = { x: radial menu center X position, y: radial menu center y position }
.radialMenuHandler = current radialMenuHandler value
.radialMenuOptions = current radialMenuOptions values
+ Return
= { keepOpen: true } (don't close radial menu)
= { overrideDefaultAction: true } (prevents default click action)
= { radialMenuWedgeItems: UInvRadialWedgeItems } (see DisplayRadialMenu)
= { radialMenuHandler: Handler } (see DisplayRadialMenu)
= { radialMenuOptions: UInvRadialOptions } (see DisplayRadialMenu)
- DisabledWedgeClick (sends MouseUp event)
+ Event
.wedgeID = The wedge's ID number (0 = center, 1 = top, 2... rotate clockwise)
.wedgeData = The wedge's data string
.wedgeDisabled = true
.srcBag = name of the bag the item was dragged from
.draggedItem = name of the dragged item
.oldCellNo = the UInvCell number in srcBag that the item was dragged from
.destBag = name of the bag it's being dropped into
.droppedOnItem = if it's being dropped on another item it's the item's name, otherwise it's "" (an empty string)
.newCellNo = the UInvCell number in destBag that item is being dropped on
+ Return
= { keepOpen: false } (close radial menu)
= { radialMenuWedgeItems: UInvRadialWedgeItems } (see DisplayRadialMenu)
= { radialMenuHandler: Handler } (see DisplayRadialMenu)
= { radialMenuOptions: UInvRadialOptions } (see DisplayRadialMenu)
- Cancel (sends :passagerender event for "NewPassage", otherwise sends MouseDown/Up event)
+ Event
.cancelType = "NewPassage", "MouseDown", or "MouseUp"
> See: http://www.motoslave.net/sugarcube/2/docs/#navigation-event-passagerender
http://www.motoslave.net/sugarcube/2/docs/#passage-api
https://developer.mozilla.org/en-US/docs/Web/Events/mousedown
https://developer.mozilla.org/en-US/docs/Web/Events/mouseup
https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent
+ Return
= { keepOpen: true } (don't close radial menu)
"cacheImages" events:
---------------------
- Loaded (triggered on "load" events)
> See: https://developer.mozilla.org/en-US/docs/Web/Events/load
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload
+ Event
.path = image's path
.filename = image's filename
.URL = image's URL (= .path + .filename)
.tries = the number of times the image has tried to load
.src = image's source URL
.imageGroup = (optional) if the handler was set using UInv.cacheImages, this is a unique group ID
+ Return (none)
- Error (triggered on "error" and "abort" events)
> See: https://developer.mozilla.org/en-US/docs/Web/Events/error
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onerror
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onabort
+ Event
.path = image's path
.filename = image's filename
.URL = image's URL (= .path + .filename)
.tries = the number of times the image has tried to load
.src = image's source URL
.imageGroup = (optional) if the handler was set using UInv.cacheImages, this is a unique group ID
+ Return
= { retryLoad: true } (retry loading this image)
- Idle (triggered after the last image in the cache has been processed)
+ Event
.complete = The total number of images that have either successfully loaded or failed to load.
.loaded = The total number of images that have successfully loaded.
.errors = The total number of images that have failed to load.
+ Return (none)
"visibility" events:
--------------------
Use Intersection Observer API and Page Visibility API to trigger events based on changing visibility of elements.
https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
Radial menus:
https://codepen.io/thomasbaldry/pen/RLaxoP
https://codepen.io/lenymo/pen/rwmBGq
https://codepen.io/web-tiki/pen/ZYmZoV
https://codepen.io/Fernker/pen/Ikjdq
fa-sync-alt = swap items
fa-plus-square = drop all items
plus-half_white.svg = drop half of items (round down)
plus-quarter_white.svg = drop a quarter of items (round down)
plus-one_white.svg = drop one item
minus-one_white.svg = pick up one item
fa-times-circle = cancel radial menu
Visual Inventory Designer (VID) sample code:
https://codepen.io/Prebyter/pen/ggVxWo
https://codepen.io/cjonasw/pen/Jiqdj
https://codepen.io/101Computing/pen/vdPoMw (Minecraft style)
https://codepen.io/MadLittleMods/pen/vmhLF (Inventory System - Drag and Drop Resizable Grid)
https://codepen.io/TLJens/pen/RPWBvY (inset boxes)
https://css-tricks.com/creating-a-parking-game-with-the-html-drag-and-drop-api/
https://www.w3schools.com/html/html5_draganddrop.asp
https://www.w3schools.com/html/tryit.asp?filename=tryhtml5_draganddrop2
https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API
https://twinery.org/questions/10028/how-to-have-a-drag-and-drop-div-list-its-contents
https://twinery.org/questions/1021/using-drag-and-drop-to-set-variables
https://developer.mozilla.org/en-US/docs/Web/CSS/border-image
http://designwithpc.com/Plugins/ddSlick
https://stackoverflow.com/questions/623172/how-to-get-image-size-height-width-using-javascript
https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
(Allow them to be in translucent boxes over the text? Collapseable inventory?)
(Allow user to store "themes" in designer.)
(Allow drag-drop blacklists and/or whitelists + function checks(?))
(Browser pre-caching of images?)
Class stuff:
http://api.jquery.com/addClass/
https://stackoverflow.com/questions/16086201/jquery-changing-style-of-html-element
https://stackoverflow.com/questions/11474430/change-css-class-properties-with-jquery
https://api.jqueryui.com/draggable/
https://api.jqueryui.com/droppable/
Other UInv functions and macros:
--------------------------------
+ ClearErrors() Clears error message.
+ GetLastError([Clear]) = last error message, also clears the error messages if Clear is set to true
+ GetUserAlerts()
+ Initialize([DisplayErrors]) create and set global variables
+ SetUserAlerts(ErrorSetting, ErrorStringAddendum) Enables/disables display of error message dialog boxes with Text addendum. (This can be used for debugging and/or to let users know how to report this error.)
+ SetMergeItemMethod(MergeMethod) call this to determine how items will be merged if source and destination items do not match (other than UInvQuantity)
+ Version() = version info
- <<UInvSet>><</UInvSet>>
- <<UInvTry CodeString>><<Fail>><</UInvTry>>
Complete!!! (9 functions/macros)
(Store error messages in a separate file to allow translations?)
(Add cheat detection? Enable/disable with password, store hash of password.)
Utility functions:
------------------
+ addArticle(WordIn, Caps) Returns "a " or "an " followed by the string passed in, based on the first word passed to it.
- arrayObjectIncludes(ArrayOfGenericObjects, ObjProperty, Value) Returns whether the array has any objects with the property ObjProperty that has a matching value.
+ arraysAreEqual(Array1, Array2) = t/f
- arrayHasAllTags(Array, TagArray) = t/f (if a tag in TagArray is repeated, Array must have that many or more of that tag in it to count)
- arrayHasAnyTag(Array, TagArray) = t/f (if a tag in TagArray is repeated, Array must have that many or more of that tag in it to count)
+ arrayHasTag(Array, Tag) = number of Tag tags found in array, or undefined on error
+ cacheImages(Path, ImageName/array, [Handler]) Allows you to preload images. You can use the handler to receive notifications about load or error events.
- combineGenericObjects(Obj1, Obj2) Returns a new object that has the combined properties of Obj1 and Obj2, with Obj2's properties preferred when both objects have matching property names. Returns "undefined" on error.
- docHasCSSElement(CSSElement) If document has CSS element "CSSElement", returns the element's CSSStyleDeclaration object, otherwise returns "false".
+ flushAllCachedImages([MaxCache, MaxConcurrent]) Clears out all cached images. Also lets you set the maximum number of images to cache (defaults to 100) and the maximum number of images do download concurrently (defaults to 5). Returns true on success and false on error.
- flushCachedImages(Path, ImageName/array) Allows you to manually unload previously cached images.
- getArraySortedByOtherArray(UnsortedArray, ArrayToSortBy, [RemoveDuplicates = false]) = UnsortedArray sorted based on ArrayToSortBy and subsorted by UnsortedArray value, if RemoveDuplicates is true, remove any elements with the same values across both arrays
- getArrayReverseSortedByOtherArray(UnsortedArray, ArrayToSortBy, [RemoveDuplicates = false]) = UnsortedArray reverse sorted based on ArrayToSortBy and subsorted by UnsortedArray value, if RemoveDuplicates is true, remove any elements with the same values across both arrays
- getCachedImageObject(Path, ImageName) Returns a copy of the cached image object. This way you can access properties like .naturalWidth and .naturalHeight on it. Returns "null" if image not in cache or "undefined" on error.
+ getObjectProperties(Object, [Ext]) Returns all of the properties and values of an object as a string. Non-objects get returned unchanged.
+ getRandomHexString() Returns a random hexidecimal string of 6 characters.
- getUniqueArray(Array) = an array so that all elements of the original array are now unique, or undefined on error.
- integerToOrdinal(Value, [Options]) = an ordinal string (e.g. "first", "11th", "1,000th", etc...), or same value if Value isn't an integer. Options = "NoOrdinalText", "UseSuperscript", "Capitalize"
+ isArray(Value) = t/f
+ isArrayOfArrays(Value) = t/f
+ isArrayOfBooleans(Value) = t/f
- isArrayOfDates(Value) = t/f
+ isArrayOfGenericObjects(Value) = t/f
+ isArrayOfIntegers(Value) = t/f
- isArrayOfMaps(Value) = t/f
+ isArrayOfNumbers(Value) = t/f
+ isArrayOfObjects(Value) = t/f
- isArrayOfSets(Value) = t/f
+ isArrayOfStrings(Value) = t/f
- isArrayOfType(Value, Type) = t/f
+ isBoolean(Value) = t/f
+ isDate(Value) = t/f
+ isFunction(Value) = t/f
+ isGenericObject(Value) = t/f
+ isInteger(Value) = t/f
+ isMap(Value) = t/f
+ isNumber(Value) = t/f
+ isObject(Value) = t/f
+ isProperty(Obj, Prop) = Returns if Prop is a property of the object Obj.
+ isRegExp(Value) = t/f
+ isSet(Value) = t/f
+ isString(Value) = t/f
+ isUndefined(Value) = t/f
+ mapsAreEqual(Map1, Map2) = t/f
♦ numberToAPString(Value) = returns the number as an AP style formatted string
+ objectsAreEqual(Object1, Object2) = t/f
sanitizeString(String) = String minus any code stuff ("$", "_", "@@", "&#", "[[", "[", "<<", "<", + URLDecoded versions of same (repeat URLDecode until string stops changing; also add ";" for any that start with "&#"(?).))
+ setsAreEqual(Set1, Set2) = t/f
+ setsMatch(Set1, Set2) = if two sets contain matches for all values in any order.
+ spread(Value, Funct) = Returns a Map, Set, or String converted to an array. If the second parameter is an Array, Map, Set, or String, then the two objects are spread and returned as a single array. If a function is passed as the second parameter, this calls the function with the spread array as parameters and returns that functions value.
+ valuesAreEqual(Var1, Var2) = t/f
+ isAndroid
+ isBlackBerry
+ isBlink
+ isChrome
+ isEdge
+ isFirefox
+ isIE
+ isiOS
+ isMobile
+ isOpera
+ isSafari
+ isTwine
more array functions? (sort, reverse array order, make unique, merge arrays, shuffle, etc. ...)
documentation To-Do list: isMap, isSet, mapsAreEqual, setsAreEqual, setsMatch, spread
1 more to complete! (63 functions)
295+ functions/macros + 8+ display elements planned
291 functions/macros + 2 display elements written
= ~97% complete
Internal-use-only functions:
----------------------------
Available:
+ continueLoadingCache() - Starts loading any waiting images if maxConcurrent images aren't already loading.
♦ GetRawBagObject(BagName) - For testing purposes only: Returns the raw bag object.
♦ GetRawItemObject(BagName, ItemName) - For testing purposes only: Returns the raw item object.
+ initializeImageCache() - Sets up setup.UInvImageCache for image caching.
+ InitializeRadialMenu() - Creates radial menu div element.
Hidden:
♦ deepFreeze(Object) - Freeze everything in an object's property tree.
♦ FixBagName(BagName) - If BagName is an empty string it returns the current bag name (if there is one), otherwise return BagName, unless BagName isn't a string, in which case return false.
- FixContainerReferences(OldBagName, OldItemName, NewBagName, NewItemName) - Fixes pockets on new item so that they refer to the item's new bag and/or item name(s).
♦ FixItemName(ItemName) - If ItemName is an empty string it returns the current item name (if there is one), otherwise return ItemName, unless ItemName isn't a string, in which case return false.
+ RemoveItemObjectsDefaultProperties(Obj, DefaultItemType) - Removes all default properties from Obj. Returns true on success or false on error.
+ TryIntParse(Value) - Attempts to parse strings to integers if Value is a string, returns either a number or undefined if Value isn't a number.
+ UInvError(ErrStr) - Triggers a UInv error message.
- ValidateItemName(ItemName) - Returns validated ItemName or undefined on failure.
(13 internal functions - not counted in total above)
User Notes:
-----------
BagData function stores the list of default bags.
ItemData function stores the list of default items.
*** vv In the ItemData function vv ***
Item names must be unique strings in all lowercase.
Item names cannot be "UInvTouched", "UInvProperties", "UInvDefaultBagType", "UInvContainer", or "".
Property names can be upper and/or lowercase strings.
An item cannot have more than one property with the same name.
An item cannot have a property named "UInvQuantity", "UInvDefaultItemType", "UInvVariableType". "UInvPocket", or "UInvCell".
Property values can be strings, numbers, booleans, arrays, or generic objects.
Functions are unsupported property value types.
Multiple successive case lines with no "break;" between them will be treated as different items with the same properties.
*** ^^ In the ItemData function ^^ ***
New items should be added in the following format:
case "unique-lowercase-item-name-string":
Item = { unique-property-name1-string : property-value1,
unique-property-name2-string : property-value2,
... };
break;
It's recommended that you list your items alphabetically both to help avoid duplicating names and to make them easier to find if you need to modify them later.
Items in the ItemData function with multiple successive "case" lines with no "break;" between them will be treated as different items with all the same properties. You can use this if you want to have a bunch of items that are all identical except for their names.
BagName must be unique across all bags.
BagPropertyName must be unique within any particular bag.
ItemName must be unique both within a bag and in the ItemData function. ItemName also cannot be "UInvProperties" or "UInvTouched".
ItemPropertyNames must be unique within any item and cannot be "UInvQuantity".
UInvQuantity exists on all items and must be a positive integer. If <= 0 then the item gets deleted from the bag.
Modified properties of items are kept between saves, but unmodified properties will be pulled from the GetDefaultItemObject function. This means that if you change an item property in different versions of your code, players will only see that property change if the item was using the default item properties. Use ResetItemProperties to get the default properties.
CreateItem is not recommended, since it can cause you to have duplicate ItemNames. For the same reason, ChangeItem should be used with caution. If two different items in two different bags have the same ItemName, and you move the item from one bag to another, the version in the receiving bag will be used and its Quantity will be incremented.
You can set "touched" to false on a bag, and if any changes are made to the number of items in that bag, "touched" will be set to true. You can use this if you need to determine whether a bag needs to be reset or not. For example, if a store needs to be restocked at the end of the day or not. Changing the bag's properties or an item's properties within that bag does NOT change the bag to touched.
Q: Why not have AddItem (or some function) automatically create the bag if it doesn't already exist?
A: Because it makes it harder for you to discover errors. If the bag name you put in had a typo in it, then no error would be thrown because the typo bag would be created, and you would probably waste a lot of time trying to figure out where the missing item went. That is, once you finally noticed it was missing. Having an error thrown makes noticing bugs and debugging them much easier.
It should be noted that, because the data is stored in objects, the order that you may get values from objects after they've changed can be (though usually isn't) quite different. Do not rely on getting the same order of output twice from an object unless it's sorted in some way.
Bags are created in $UInvBags / State.variables.UInvBags as below:
$UInvBags {
BagName : {
[ UInvTouched : true/false, ] (unless it's true)
UInvProperties : {
[ UInvVariableType : "", ] (if a bag's DefaultBagType is variable)
property object for bag ... (done in "BagPropertyName : value" format)
},
[ UInvDefaultBagType : "DefaultBagTypeString", ] (only if it's based on a default type)
[ UInvContainer : [ { BagName : "name", ItemName : "name", PocketName : "name" }, ... ], ] (only if it's a pocket)
ItemName : {
[ UInvQuantity : positive integer, ] (unless the quantity == 1)
[ UInvDefaultItemType : "DefaultItemTypeString", ] (only if it's based on a default type)
[ UInvVariableType : "", ] (if an item's DefaultItemType is variable)
[ UInvPocket : { "PocketName" : "BagName", ... } ] (only if it has pockets)
[ UInvCell : positive integer, ] (only if it's in a table)
property object for item ... (done in "ItemPropertyName : value" format)
},
next item in bag ... (ItemName format)
},
next bag ... (BagName format)
}
BagTouched = UInvBags[BagName]["UInvTouched"] *
BagPropertyObject = UInvBags[BagName]["UInvProperties"] * (unless bag has no properties)
BagPropertyValue = UInvBags[BagName]["UInvProperties"][BagPropertyName] * (if it's not a default value)
DefaultBagType = UInvBags[BagName]["UInvDefaultBagType"] * (if it exists)
ItemQuantity = UInvBags[BagName][ItemName]["UInvQuantity"] * (= 1 if it doesn't exist)
DefaultItemType = UInvBags[BagName][ItemName]["UInvDefaultItemType"] (if it exists)
ItemPropertyValue = UInvBags[BagName][ItemName][ItemPropertyName] (if it's not a default value)
$UInvCurrentBagName = last BagName used *
$UInvCurrentItemName = last ItemName used *
$UInvShowAlerts = false or 1..15 *
$UInvLastErrorMessage = last error message
$UInvErrorStringAddendum = text to add to the end of error messages *
$UInvMergeItemMethod = method for handling item collision in some functions (see MERGE_... values below)
$UInvUpdatesAreLocked = a positive integer if automatic display updates are locked *
$UInvEventHandlers = stores various event handlers
setup.UInvImageCache = { loading: 0, complete: 0, loaded: 0, errors: 0, waiting: 0, total: 0, maxConcurrent: 5, maxCache: 100, images: [] }; *
(*: May be undefined. Use the Get or Set functions to check or modify these.)
If a bag's DefaultBagType is variable, then "UInvVariableType" must be among its UInvProperties.
If an item's DefaultItemType is variable, then "UInvVariableType" must be among its properties.
UInv "setup" objects:
• setup.ImagePath (fix this? or document it?)
• setup.UInvImageCache
• setup.UInvRadialMenuData
• setup.UInvUserAlertsDebug
• setup.UInvUserAlertsBackup
Not using:
• setup.Path
• setup.SoundPath
UInvEventHandler object:
• handler: a string which represents the setup function's or widget's name
• type: "function" or "widget"; tells you whether the handler name triggers a setup function or a widget
• options: (optional) a generic object containing properties and values which are matched with properties from the event's Event object
Values for $UInvShowAlerts, used with SetUserAlerts (values can be added together except for ERROR_NONE):
ERROR_NONE = false
Do not display any error messages to users.
ERROR_SHOW_PASSAGE_NAME = 1
Displays the current passage name in any error messages.
ERROR_SHOW_ALERT = 2
Displays a modal dialog box for each error message and pauses execution.
ERROR_THROW_ERROR = 4
Throws traditional Twine/SugarCube error messages, instead of silently returning a value which indicates that a UInv error occurred.
ERROR_TO_CONSOLE = 8
Outputs any error messages to the console window.
Values for UInvMergeItemMethod and UInv.SetMergeItemMethod to determine how UInv handles item collision:
UInv.MERGE_USE_ONLY_DESTINATION_PROPERTIES = 1
Ignore source properties, just increment destination's quantity. (default)
UInv.MERGE_USE_ONLY_SOURCE_PROPERTIES = 2
Delete the destination's properties, replace with the source's properties and values, and increment the quantity.
UInv.MERGE_PREFER_DESTINATION_PROPERTIES = 3
Keep the properties and values in the destination, add any properties and values the source had but the destination didn't, and increment the quantity.
UInv.MERGE_PREFER_SOURCE_PROPERTIES = 4
Keep the properties and values in the source, add any properties and values the destination had but source the didn't, and increment the quantity.
UInv.MERGE_RENAME_SOURCE_ITEMNAME = 5
Rename the source's unique identifier so that it's stored separately in the destination bag. This causes the function to return the new item name.
UInv.MERGE_FAIL_WITH_ERROR = 6
Fail with an error.
Functions which can cause item collision: CopyAllItemsToBag, MoveAllItemsToBag, MergeBags, AddItem, AddItems, CopyItem, MoveItem, RenameItem
NOTE: If BagName or ItemName = "" when passed to a function, then UInvCurrentBagName or UInvCurrentItemName will be used instead, respectively.
Notes to self:
--------------
*** Make sure that UInvCurrentItemName and UInvCurrentBagName only get set if the function doesn't throw an error. ***
Be careful of possible single or double quotes inside of strings you may display to make sure that they don't prematurely end another string.
Make sure that BagTouched is set properly for all functions that affect item quantities!!!
Make sure that default property values are always deleted!!! (i.e. if a value is changed, see if it matches the default, and if it does, delete it and use the default instead.)
Create either an item editor or a "sanity checker" for the GetDefaultIemObject function's items.
Keep track of "root" functions. (e.g. CopyItem is a "root" function for handling item merging.)
-- CopyItem, SetItemPropertyValue
UInvCurrentBagName and UInvCurrentItemName should get destination bag and destination item names if there are source and destination parameters in the function.
Auto-compress frequently used property names by using shorter aliases?
Work on better/more consistent handling of optional parameters (e.g. the Quantity parameter in AddItem, don't throw error on "" value?).
Show sample code that displays an inventory screen without leaving the passage so that an author using UInv can display an inventory screen without having to worry about re-triggering code. (use a Display function)
Allow "array of X" parameters whenever it makes sense.
Look at various inventory pictures on Google Image and make sure UInv can do that.
Don't use UInv.GetItemsArray in the *Has* functions when you could just be checking if the property is undefined on the object or not, e.g. (State.variables.UInvBags[BagName][ItemName] !== undefined)
Try to use .filter() to get subsets of arrays from arrays? (compare speeds with for loops):
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
Trap value overflows? e.g. Number.MAX_SAFE_INTEGER + 1 (9,007,199,254,740,991 + 1) (note: Number.MAX_SAFE_INTEGER not supported in IE)
Do more "GetObjectOf..." functions?
Minecraft-style item creation functions?
(delete A & B -> create C) { source : [ "itemA", "itemB" ], result : [ "itemC" ] }
Make a "synonym" function that pulls from a list of non-recently used synonyms.
Optimize function calling?
Support multi-threading? (i.e. "lock" all other functions until an executing function is complete to make it thread safe)
Add a "tree shaking" application which you could feed Twee source and it would spit out a minimal version of UInv?
Function name descriptor format:
Modification: Add / Create / Delete / Copy / Move / Merge / Rename / Empty / Set / Reset
Informational: Get / Match / Sort / Exists
Conditionals: Where / Has / Highest / Lowest / Are / With / Without / By / Unique
Modifiers: Equal(s) / GreaterThan / LessThan / Contains / All / Any / None / Full
Data Categories: Bag(s) / Property(ies) / Item(s) / ItemQuantity(ies)
Data Types: Name(s) / Value(s) / Tag(s) / Array / Object / Count
Display: Display / Fill / List
Possibly problematic property names: ***
Names that the SugarCube parser would change:
SCReparsedNames = ['to', 'eq', 'neq', 'is', 'isnot', 'gt', 'gte', 'lt', 'lte', 'and', 'or', 'not', 'def', 'ndef']; // Names that the SugarCube parser would change.
Probably should prevent entirely:
'prototype', 'constructor', '__proto__', 'await' */
Prevent unquoted property names?:
do|if|in|for|int|new|try|var|byte|case|char|else|enum|goto|long|null|this|true|void|with|break|catch|class|const|false|final|float|short|super|throw|while|delete|
double|export|import|native|public|return|static|switch|throws|typeof|boolean|default|extends|finally|package|private|abstract|continue|debugger|function|volatile|
interface|protected|transient|implements|instanceof|synchronized */
Prevent names that don't start with letters?
Use this? : https://github.com/mathiasbynens/mothereff.in/tree/master/js-properties
Check property names to see if they're functions first?
Documentation:
--------------
Ways to list items in a bag
---------------------------
The classic way:
''List of items in bag "Test":'' <<set _Items = UInv.GetItems("Test")>><<if _Items.length == 0>>(empty)<<else>><<for _i = 0; _i < _Items.length; _i++>>_Items[_i] (<<print UInv.BagHasItem("Test", _Items[_i])>>)<<if _i < _Items.length - 1>>, <</if>><</for>><</if>>
Output = <b>List of items in bag "Test":</b> belt (2), black belt (1), dagger (1)
The easy way:
''List of items in bag "Test":'' <<print UInv.DisplayItemList("Test")>>
Output = <b>List of items in bag "Test":</b> two belt, black belt, and dagger
The fancy way:
''List of items in "Test":'' <<print UInv.DisplayItemList("Test", "plural", "nothing", ",", "and", "singular")>>