@maccesar/titools 2.2.12 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +255 -713
  2. package/bin/titools.js +1 -1
  3. package/lib/commands/update.js +5 -6
  4. package/lib/config.js +1 -0
  5. package/lib/downloader.js +10 -0
  6. package/package.json +1 -1
  7. package/skills/alloy-guides/SKILL.md +46 -48
  8. package/skills/alloy-guides/references/CONTROLLERS.md +4 -6
  9. package/skills/alloy-guides/references/MODELS.md +340 -184
  10. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +3 -4
  11. package/skills/alloy-guides/references/VIEWS_STYLES.md +44 -46
  12. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +4 -5
  13. package/skills/alloy-guides/references/VIEWS_XML.md +51 -17
  14. package/skills/alloy-guides/references/WIDGETS.md +1 -1
  15. package/skills/alloy-howtos/SKILL.md +12 -13
  16. package/skills/alloy-howtos/references/cli_reference.md +40 -41
  17. package/skills/alloy-howtos/references/samples.md +3 -4
  18. package/skills/purgetss/SKILL.md +369 -356
  19. package/skills/purgetss/references/EXAMPLES.md +24 -25
  20. package/skills/purgetss/references/animation-advanced.md +555 -0
  21. package/skills/purgetss/references/animation-system.md +395 -995
  22. package/skills/purgetss/references/apply-directive.md +111 -141
  23. package/skills/purgetss/references/arbitrary-values.md +206 -480
  24. package/skills/purgetss/references/class-categories.md +277 -0
  25. package/skills/purgetss/references/class-index.md +1 -420
  26. package/skills/purgetss/references/cli-commands.md +446 -556
  27. package/skills/purgetss/references/configurable-properties.md +163 -599
  28. package/skills/purgetss/references/custom-rules.md +33 -76
  29. package/skills/purgetss/references/customization-deep-dive.md +319 -518
  30. package/skills/purgetss/references/dynamic-component-creation.md +33 -37
  31. package/skills/purgetss/references/grid-layout.md +42 -371
  32. package/skills/purgetss/references/icon-fonts.md +82 -475
  33. package/skills/purgetss/references/installation-setup.md +159 -331
  34. package/skills/purgetss/references/migration-guide.md +54 -109
  35. package/skills/purgetss/references/opacity-modifier.md +25 -222
  36. package/skills/purgetss/references/performance-tips.md +2 -2
  37. package/skills/purgetss/references/platform-modifiers.md +21 -407
  38. package/skills/purgetss/references/tikit-components.md +237 -104
  39. package/skills/purgetss/references/titanium-resets.md +20 -21
  40. package/skills/purgetss/references/ui-ux-design.md +171 -1702
  41. package/skills/ti-api/SKILL.md +109 -0
  42. package/skills/ti-api/references/api-android.md +675 -0
  43. package/skills/ti-api/references/api-app-platform.md +636 -0
  44. package/skills/ti-api/references/api-core.md +764 -0
  45. package/skills/ti-api/references/api-data-network.md +641 -0
  46. package/skills/ti-api/references/api-media.md +655 -0
  47. package/skills/ti-api/references/api-modules-ble-bluetooth.md +657 -0
  48. package/skills/ti-api/references/api-modules-coremotion-urlsession.md +411 -0
  49. package/skills/ti-api/references/api-modules-map.md +632 -0
  50. package/skills/ti-api/references/api-modules-nfc.md +725 -0
  51. package/skills/ti-api/references/api-modules-social-misc.md +526 -0
  52. package/skills/ti-api/references/api-services.md +700 -0
  53. package/skills/ti-api/references/api-ui-android.md +499 -0
  54. package/skills/ti-api/references/api-ui-extras.md +702 -0
  55. package/skills/ti-api/references/api-ui-ios-animator.md +378 -0
  56. package/skills/ti-api/references/api-ui-ios.md +756 -0
  57. package/skills/ti-api/references/api-ui-lists.md +581 -0
  58. package/skills/ti-api/references/api-ui-text-input.md +607 -0
  59. package/skills/ti-api/references/api-ui-views.md +572 -0
  60. package/skills/ti-api/references/api-ui-windows-navigation.md +676 -0
  61. package/skills/ti-api/references/api-xml-global.md +743 -0
  62. package/skills/ti-expert/SKILL.md +46 -45
  63. package/skills/ti-expert/references/adaptive-layouts.md +414 -0
  64. package/skills/ti-expert/references/alloy-builtins.md +16 -20
  65. package/skills/ti-expert/references/alloy-structure.md +40 -42
  66. package/skills/ti-expert/references/anti-patterns.md +34 -0
  67. package/skills/ti-expert/references/code-conventions.md +5 -3
  68. package/skills/ti-expert/references/error-handling.md +14 -7
  69. package/skills/ti-expert/references/examples.md +4 -2
  70. package/skills/ti-expert/references/performance-optimization.md +26 -24
  71. package/skills/ti-expert/references/security-device.md +17 -14
  72. package/skills/ti-expert/references/security-fundamentals.md +60 -101
  73. package/skills/ti-expert/references/state-management.md +15 -14
  74. package/skills/ti-expert/references/testing-e2e-ci.md +30 -21
  75. package/skills/ti-expert/references/theming.md +12 -20
  76. package/skills/ti-guides/SKILL.md +13 -17
  77. package/skills/ti-guides/references/advanced-data-and-images.md +30 -10
  78. package/skills/ti-guides/references/application-frameworks.md +3 -3
  79. package/skills/ti-guides/references/coding-best-practices.md +31 -2
  80. package/skills/ti-guides/references/commonjs-advanced.md +46 -4
  81. package/skills/ti-guides/references/hello-world.md +9 -13
  82. package/skills/ti-guides/references/hyperloop-native-access.md +4 -1
  83. package/skills/ti-guides/references/javascript-primer.md +13 -5
  84. package/skills/ti-guides/references/resources.md +0 -2
  85. package/skills/ti-guides/references/style-and-conventions.md +1 -0
  86. package/skills/ti-guides/references/tiapp-config.md +0 -32
  87. package/skills/ti-howtos/SKILL.md +43 -45
  88. package/skills/ti-howtos/references/buffer-codec-streams.md +25 -3
  89. package/skills/ti-howtos/references/debugging-profiling.md +14 -25
  90. package/skills/ti-howtos/references/google-maps-v2.md +3 -3
  91. package/skills/ti-howtos/references/ios-map-kit.md +8 -1
  92. package/skills/ti-howtos/references/notification-services.md +0 -1
  93. package/skills/ti-howtos/references/webpack-build-pipeline.md +3 -0
  94. package/skills/ti-ui/SKILL.md +47 -49
  95. package/skills/ti-ui/references/application-structures.md +3 -2
  96. package/skills/ti-ui/references/orientation.md +17 -9
  97. package/skills/ti-ui/references/platform-ui-ios.md +63 -0
  98. package/skills/ti-ui/references/scrolling-views.md +39 -0
@@ -259,9 +259,253 @@ If you want to fire or listen to multiple events, Backbone.js uses spaces to del
259
259
 
260
260
  ## Alloy Data Binding
261
261
 
262
+ ### Introduction
263
+
264
+ When data in the collection changes, you may want to update the view simultaneously to keep information synchronized. This concept is known as data binding. Both Alloy and Backbone provide some mechanisms to bind model data to a view.
265
+
266
+ ### Alloy Binding
267
+
268
+ In Alloy, collection data can be synchronized to a view object, or a single model can be bound to a view component. Alloy monitors the Backbone add, change, destroy, fetch, remove, and reset events to update the data in the view.
269
+
270
+ #### Collection-View Binding
271
+
272
+ To enable collection-view binding, create a global singleton or controller-specific collection using the [Collection tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#collection-element) in the XML markup of the main view, then add the view object you want to bind data to. The following Titanium view objects support binding to a Collection:
273
+
274
+ | View Object | Since Alloy version | Add data binding attributes to... | Repeater Object to map model attributes to view properties |
275
+ | -------------- | ------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------ |
276
+ | ButtonBar | 1.1 | `<Labels>` | `<Label/>` |
277
+ | CoverFlowView | 1.1 | `<Images>` | `<Image/>` |
278
+ | ListView | 1.2 | `<ListSection>` | `<ListItem/>` |
279
+ | Map Module | 1.4 | `<Module module="ti.map" method="createView">` | None, model attributes will be used as params for createAnnotation() directly. |
280
+ | Picker | 1.5 | `<PickerColumn>` or `<Column>` | `<PickerRow/>` or `<Row/>` |
281
+ | ScrollableView | 1.1 | `<ScrollableView>` | `<View/>` May contain children view objects. |
282
+ | TableView | 1.0 | `<TableView>` | `<TableViewRow/>` May contain children view objects. |
283
+ | TabbedBar | 1.1 | `<Labels>` | `<Label/>` |
284
+ | Toolbar | 1.1 | `<Items>` | `<Item/>` |
285
+ | View | 1.0 | `<View>` | Any view object except a top-level container like a Window or TabGroup |
286
+
287
+ You need to specify additional attributes in the markup, which are only specific to collection data binding. The only mandatory attribute is `dataCollection`, which specifies the collection singleton or instance to render. Note that you can only add these attributes to specific XML elements (refer to the table above).
288
+
289
+ * `dataCollection`: specifies the collection singleton or instance to bind to the table. This is the name of the model file for singletons or the ID prefixed with the controller symbol ('$') for instances.
290
+
291
+ * `dataTransform`: specifies an optional callback to use to format model attributes. The passed argument is a model and the return value is a modified model as a JSON object.
292
+
293
+ * `dataFilter`: specifies an optional callback to use to filter data in the collection. The passed argument is a collection and the return value is an array of models.
294
+
295
+ * `dataFunction`: set to an arbitrary identifier (name) for a function call. Use this identifier to call a function in the controller to manually update the view. This is not a declared function in the controller. This attribute creates an alias to access the underlying binding function, which is part of the Alloy data-view binding framework.
296
+
297
+ Next, create a repeater object (refer to the table above) and place it inline with the view object with the `dataCollection` attribute, or place it in a separate view and use the `Require` tag to import it.
298
+
299
+ To map model attributes, enclose the attribute with curly brackets or braces ('{' and '}'). You can map more than one attribute to a repeater object's property. For example, to assign the Label.text property to the model's title and author attributes, use this notation: `<Label text="{title} by {author}" />.` For more complex transformations, use the `dataTransform` callback to create a custom attribute.
300
+
301
+ In the controller code of the repeater object, you can use the special variable `$model` to reference the current model being iterated over. This variable is present only in data bound controllers and is a reference to the currently bound model. For example, to get the title attribute of the current model, use `$model.title` to access it.
302
+
303
+ > **⚠️ ⚠️ Warning**
304
+ > **IMPORTANT:** When using Alloy's data binding in a view-controller, you **MUST** call the `$.destroy()` function when closing a controller to prevent potential memory leaks. The `destroy` function unbinds the callbacks created by Alloy when the collection-view syntax is used. For example:
305
+ >
306
+ > ```javascript
307
+ > $.win.addEventListener("close", () => {
308
+ > $.destroy();
309
+ > });
310
+ > ```
311
+ >
312
+ > For global singletons, to properly release them you should also remove event handlers with `off()` and set the reference to null:
313
+ >
314
+ > ```javascript
315
+ > $.win.addEventListener("close", () => {
316
+ > $.destroy();
317
+ > Alloy.Collections.book.off();
318
+ > Alloy.Collections.book = null;
319
+ > });
320
+ > ```
321
+
322
+ #### Collection-View Binding Example
323
+
324
+ The following example demonstrates how to add basic collection-view binding to an application. The example binds a collection of album models to a ScrollableView. In the ScrollableView, each model has its own view, which displays the album cover, title of the album and the artist. The `artist` and `title` attributes are bound to a Label object and the `cover` attribute is bound to an ImageView object.
325
+
326
+ 1. Add the `<Collection>` tag as a child of the `<Alloy>` tag.
327
+
328
+ **app/views/index.xml**
329
+
330
+ ```xml
331
+ <Alloy>
332
+ <Collection src="album" />
333
+ </Alloy>
334
+ ```
335
+
336
+ 2. Next, add the view object(s) you want to bind the data to. In this example, data will be bound to a ScrollableView object.
337
+
338
+ **app/views/index.xml**
339
+
340
+ ```xml
341
+ <Alloy>
342
+ <Collection src="album" />
343
+ <Window backgroundColor="white" onClose="cleanup">
344
+ <ScrollableView></ScrollableView>
345
+ </Window>
346
+ </Alloy>
347
+ ```
348
+
349
+ 3. Add the `dataCollection` attribute to the appropriate view object. Assign this attribute to the collection you want to use. For a ScrollableView object, add the attribute to the `<ScrollableView>` tag. The element to add the attribute to depends on which view object you want to bind data to.
350
+
351
+ **app/views/index.xml**
352
+
353
+ ```xml
354
+ <Alloy>
355
+ <Collection src="album" />
356
+ <Window backgroundColor="white" onClose="cleanup">
357
+ <ScrollableView dataCollection="album"></ScrollableView>
358
+ </Window>
359
+ </Alloy>
360
+ ```
361
+
362
+ 4. Next, create your repeater object and add model attributes. Enclose the model attributes with curly brackets or braces ('{' and '}'). For a ScrollableView, the repeater object can be a View object with additional children objects. The repeater object depends on which view object you are using.
363
+
364
+ **app/views/index.xml**
365
+
366
+ ```xml
367
+ <Alloy>
368
+ <Collection src="album"/>
369
+ <Window backgroundColor="white" onClose="cleanup">
370
+ <ScrollableView dataCollection="album">
371
+ <View layout="vertical">
372
+ <ImageView image="{cover}" />
373
+ <Label text="{title} by {artist}" />
374
+ </View>
375
+ </ScrollableView>
376
+ </Window>
377
+ </Alloy>
378
+ ```
379
+
380
+ 5. In the controller, call the Collection's `fetch()` method to initialize the collection and sync any stored models to the view. Remember to call the `$.destroy()` method when you close the controller to prevent memory leaks.
381
+
382
+ **app/controllers/index.js**
383
+
384
+ ```javascript
385
+ $.index.open();
386
+ Alloy.Collections.album.fetch();
387
+
388
+ function cleanup() {
389
+ $.destroy();
390
+ }
391
+ ```
392
+
393
+ The application is now setup for basic collection-view binding. When any new data is added to the collection, the ScrollableView will be updated with the new data.
394
+
395
+ #### Model-View Binding
396
+
397
+ To bind a single model to a component, create a global singleton or controller-specific model using the [Model tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#model-element) in the XML markup of the main view and map the model attribute to the view component. To map the attribute to the view component, prefix the model name or id to the attribute, then enclose it with curly brackets or braces ('{' and '}').
398
+
399
+ To do complex transformations on the model attributes, extend the model prototype with a `transform()` function. It should return the modified model as a JSON object.
400
+
401
+ **app/models/album.js**
402
+
403
+ ```javascript
404
+ exports.definition = {
405
+ config: {}, // model definition
406
+ extendModel(Model) {
407
+ _.extend(Model.prototype, {
408
+ transform() {
409
+ const transformed = this.toJSON();
410
+ transformed.artist = transformed.artist.toUpperCase();
411
+ return transformed;
412
+ }
413
+ });
414
+ return Model;
415
+ }
416
+ };
417
+ ```
418
+
419
+ A global singleton instance is a single instance of a particular model that is available for use anywhere in your application. When using global instances, they will be in memory for the duration of your application unless you manually release them. The process of manually releasing them should include:
420
+
421
+ * If any controllers are using data binding that relies on the global instance, they should call their own destroy() function: `$.destroy()`
422
+ * Any other event handlers added to the global instance should be removed with the [off()](http://backbonejs.org/#Events-off) function
423
+ * Set the reference of the model to null: `Alloy.Models.nameOfModel = null;`
424
+
425
+ Note that you need to call the `$.destroy()` function when closing the controller to prevent potential memory leaks. The `destroy` function unbinds the callbacks created by Alloy when the model-view syntax is used.
426
+
427
+ #### Model-View Binding Example
428
+
429
+ The example below demonstrates how to bind a model to view components in the XML markup. Notice that each attribute is prefixed with the model's name and enclosed with braces.
430
+
431
+ ```xml
432
+ <Alloy>
433
+ <Model src="settings"/>
434
+ <Window backgroundColor="white" onClose="cleanup">
435
+ <View layout="vertical">
436
+ <Label text="Text Size" />
437
+ <Slider value="{settings.textsize}" max="5" min="1"/>
438
+ <Label text="Bold"/>
439
+ <Switch value="{settings.bold}" />
440
+ <Label text="Italics"/>
441
+ <Switch value="{settings.italics}" />
442
+ </View>
443
+ </Window>
444
+ </Alloy>
445
+ ```
446
+
447
+ #### Collection Example
448
+
449
+ The example below demonstrates how to display all book models in the collection by the author Mark Twain. It also demonstrates how to use each of the data binding attributes.
450
+
451
+ **app/views/index.xml**
452
+
453
+ ```xml
454
+ <Alloy>
455
+ <Collection src="book" />
456
+ <Window class="container">
457
+ <TableView dataCollection="book"
458
+ dataTransform="transformFunction"
459
+ dataFilter="filterFunction"
460
+ dataFunction="updateUI"
461
+ onDragEnd="refreshTable">
462
+ <!-- Also can use Require -->
463
+ <TableViewRow title="{title}" />
464
+ </TableView>
465
+ </Window>
466
+ </Alloy>
467
+ ```
468
+
469
+ **app/controllers/index.js**
470
+
471
+ ```javascript
472
+ $.index.open();
473
+
474
+ // Encase the title attribute in square brackets
475
+ function transformFunction(model) {
476
+ // Need to convert the model to a JSON object
477
+ const transform = model.toJSON();
478
+ transform.title = '[' + transform.title + ']';
479
+ // Example of creating a custom attribute, reference in the view using {custom}
480
+ transform.custom = transform.title + " by " + transform.author;
481
+ return transform;
482
+ }
483
+
484
+ // Show only book models by Mark Twain
485
+ function filterFunction(collection) {
486
+ return collection.where({author:'Mark Twain'});
487
+ }
488
+
489
+ function refreshTable(){
490
+ // Trigger the binding function identified by the dataFunction attribute
491
+ updateUI();
492
+ }
493
+
494
+ // Trigger the synchronization
495
+ const library = Alloy.Collections.book;
496
+ library.fetch();
497
+
498
+ // Free model-view data binding resources when this view-controller closes
499
+ $.index.addEventListener('close', () => {
500
+ $.destroy();
501
+ });
502
+ ```
503
+
504
+ As the collection is updated, the view reflects the changes made to the models. If you want to suppress an update, specify `{silent: true}` in the `options` parameters when calling Backbone methods to change model data.
505
+
262
506
  ### Collection vs Model Data Binding
263
507
 
264
- You can bind both a collection of models or an individual model. To bind a model attribute the opening curly bracket is first followed by the model name and then the attribute. To bind a collection you add the `dataCollection` attribute to the container using the collection name as value.
508
+ You can bind both a collection of models or an individual model. To bind a model attribute the opening curly bracket is first followed by the model name and then the attribute. To bind a collection you add the `dataCollection` attribute to the container using the collection name as value. The generated code will then loop over the collection and add the child elements to the container for each model.
265
509
 
266
510
  ```xml
267
511
  <Alloy>
@@ -341,9 +585,8 @@ library.on('change:title', e => {
341
585
  });
342
586
  ```
343
587
 
344
- ::: warning ⚠️ Warning
345
- This only works if the Backbone method fires the change event and does not enable `{silent: true}` as an option.
346
- :::
588
+ > **⚠️ ⚠️ Warning**
589
+ > This only works if the Backbone method fires the change event and does not enable `{silent: true}` as an option.
347
590
 
348
591
  If you want to suppress an update, specify `{silent: true}` in the `options` parameters when calling Backbone methods to change model data. The data-bound view will not be updated to reflect the changes.
349
592
 
@@ -380,16 +623,6 @@ You can bind models and properties that use names with special characters like d
380
623
  </Alloy>
381
624
  ```
382
625
 
383
- ### Use $.args Values in XML (CLI 7.1.0+)
384
-
385
- Since CLI 7.1.0, values passed at creation time can be used directly in XML:
386
-
387
- ```xml
388
- <Alloy>
389
- <Label text="$.args.foo" />
390
- </Alloy>
391
- ```
392
-
393
626
  ### Bind Multiple Models to the Same View
394
627
 
395
628
  You have the ability to bind multiple models to the same view:
@@ -436,11 +669,12 @@ exports.definition = {
436
669
  };
437
670
  ```
438
671
 
439
- ::: warning ⚠️ Warning
440
- The `transform` method must return **all** bound properties, not just the transformed ones. Until Alloy 1.8.1, simple collection data binding did not require this and automatically fell back to the model attributes.
441
- :::
672
+ > **⚠️ ⚠️ Warning**
673
+ > The `transform` method must return **all** bound properties, not just the transformed ones. Until Alloy 1.8.1, simple collection data binding did not require this and automatically fell back to the model attributes.
674
+
675
+ ### Tips and Tricks
442
676
 
443
- ### Lazy Transformation (Performance Tip)
677
+ #### Lazy Transformation
444
678
 
445
679
  The advantage of defining transformations in the model is that you don't need to repeat them in every controller. A possible disadvantage is that everywhere you bind the model all transformations are computed where you might only need some.
446
680
 
@@ -470,7 +704,7 @@ exports.definition = {
470
704
  };
471
705
  ```
472
706
 
473
- ### Populating a Model After Data Binding
707
+ #### Populating a Model After Data Binding
474
708
 
475
709
  When Alloy compiles your views and controllers, the generated view code precedes your controller code. Any models you define for data binding in the XML will also be created at that point. Just like you call `fetch()` to populate the collection, you do the exact same thing for the model.
476
710
 
@@ -495,158 +729,14 @@ $.current.fetch({
495
729
  $.index.open();
496
730
  ```
497
731
 
498
- ### Introduction
499
-
500
- When data in the collection changes, you may want to update the view simultaneously to keep information synchronized. This concept is known as data binding. Both Alloy and Backbone provide some mechanisms to bind model data to a view.
501
-
502
- ### Alloy Binding
503
-
504
- In Alloy, collection data can be synchronized to a view object, or a single model can be bound to a view component. Alloy monitors the Backbone add, change, destroy, fetch, remove, and reset events to update the data in the view.
505
-
506
- #### Collection-View Binding
507
-
508
- To enable collection-view binding, create a global singleton or controller-specific collection using the [Collection tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#collection-element) in the XML markup of the main view, then add the view object you want to bind data to. The following Titanium view objects support binding to a Collection:
509
-
510
- | View Object | Since Alloy version | Add data binding attributes to... | Repeater Object to map model attributes to view properties |
511
- | -------------- | ------------------- | ---------------------------------------------- | ------------------------------------------------------------------------------ |
512
- | ButtonBar | 1.1 | `<Labels>` | `<Label/>` |
513
- | CoverFlowView | 1.1 | `<Images>` | `<Image/>` |
514
- | ListView | 1.2 | `<ListSection>` | `<ListItem/>` |
515
- | Map Module | 1.4 | `<Module module="ti.map" method="createView">` | None, model attributes will be used as params for createAnnotation() directly. |
516
- | Picker | 1.5 | `<PickerColumn>` or `<Column>` | `<PickerRow/>` or `<Row/>` |
517
- | ScrollableView | 1.1 | `<ScrollableView>` | `<View/>` May contain children view objects. |
518
- | TableView | 1.0 | `<TableView>` | `<TableViewRow/>` May contain children view objects. |
519
- | TabbedBar | 1.1 | `<Labels>` | `<Label/>` |
520
- | Toolbar | 1.1 | `<Items>` | `<Item/>` |
521
- | View | 1.0 | `<View>` | Any view object except a top-level container like a Window or TabGroup |
522
-
523
- You need to specify additional attributes in the markup, which are only specific to collection data binding. The only mandatory attribute is `dataCollection`, which specifies the collection singleton or instance to render. Note that you can only add these attributes to specific XML elements (refer to the table above).
524
-
525
- * `dataCollection`: specifies the collection singleton or instance to bind to the table. This is the name of the model file for singletons or the ID prefixed with the controller symbol ('$') for instances.
526
- * `dataTransform`: specifies an optional callback to use to format model attributes. The passed argument is a model and the return value is a modified model as a JSON object.
527
- * `dataFilter`: specifies an optional callback to use to filter data in the collection. The passed argument is a collection and the return value is an array of models.
528
- * `dataFunction`: set to an arbitrary identifier (name) for a function call. This is not a declared function in the controller. This attribute creates an alias to access the underlying binding function, which is part of the Alloy data-view binding framework. Use this identifier to call a function in the controller to manually update the view.
529
-
530
- Next, create a repeater object (refer to the table above) and place it inline with the view object with the `dataCollection` attribute, or place it in a separate view and use the `Require` tag to import it.
531
-
532
- To map model attributes, enclose the attribute with curly brackets or braces ('{' and '}'). You can map more than one attribute to a repeater object's property. For example, to assign the Label.text property to the model's title and author attributes, use this notation: `<Label text="{title} by {author}" />.` For more complex transformations, use the `dataTransform` callback to create a custom attribute.
533
-
534
- In the controller code of the repeater object, you can use the special variable `$model` to reference the current model being iterated over. This variable is present only in data bound controllers and is a reference to the currently bound model. For example, to get the title attribute of the current model, use `$model.title` to access it.
535
-
536
- ::: warning ⚠️ Warning
537
- **IMPORTANT:** When using Alloy's data binding in a view-controller, you **MUST** call the `$.destroy()` function when closing a controller to prevent potential memory leaks. The `destroy` function unbinds the callbacks created by Alloy when the collection-view syntax is used. For example:
538
-
539
- ```
540
- $.win.addEventListener("close", () => {
541
- $.destroy();
542
- });
543
- ```
544
-
545
- For global singletons, to properly release them you should also remove event handlers with `off()` and set the reference to null:
546
-
547
- ```javascript
548
- $.win.addEventListener("close", () => {
549
- $.destroy();
550
- Alloy.Collections.book.off();
551
- Alloy.Collections.book = null;
552
- });
553
- ```
554
- :::
555
-
556
- #### Collection-View Binding Example
557
-
558
- The following example demonstrates how to add basic collection-view binding to an application. The example binds a collection of album models to a ScrollableView. In the ScrollableView, each model has its own view, which displays the album cover, title of the album and the artist. The `artist` and `title` attributes are bound to a Label object and the `cover` attribute is bound to an ImageView object.
559
-
560
- 1. Add the `<Collection>` tag as a child of the `<Alloy>` tag.
561
-
562
- **app/views/index.xml**
563
-
564
- ```xml
565
- <Alloy>
566
- <Collection src="album" />
567
- </Alloy>
568
- ```
569
-
570
- 2. Next, add the view object(s) you want to bind the data to.
571
-
572
- **app/views/index.xml**
573
-
574
- ```xml
575
- <Alloy>
576
- <Collection src="album" />
577
- <Window backgroundColor="white" onClose="cleanup">
578
- <ScrollableView></ScrollableView>
579
- </Window>
580
- </Alloy>
581
- ```
582
-
583
- 3. Add the `dataCollection` attribute to the appropriate view object.
584
-
585
- **app/views/index.xml**
586
-
587
- ```xml
588
- <Alloy>
589
- <Collection src="album" />
590
- <Window backgroundColor="white" onClose="cleanup">
591
- <ScrollableView dataCollection="album"></ScrollableView>
592
- </Window>
593
- </Alloy>
594
- ```
595
-
596
- 4. Next, create your repeater object and add model attributes.
597
-
598
- **app/views/index.xml**
599
-
600
- ```xml
601
- <Alloy>
602
- <Collection src="album"/>
603
- <Window backgroundColor="white" onClose="cleanup">
604
- <ScrollableView dataCollection="album">
605
- <View layout="vertical">
606
- <ImageView image="{cover}" />
607
- <Label text="{title} by {artist}" />
608
- </View>
609
- </ScrollableView>
610
- </Window>
611
- </Alloy>
612
- ```
613
-
614
- 5. In the controller, call the Collection's `fetch()` method to initialize the collection and sync any stored models to the view.
615
-
616
- **app/controllers/index.js**
617
-
618
- ```javascript
619
- $.index.open();
620
- Alloy.Collections.album.fetch();
621
-
622
- function cleanup() {
623
- $.destroy();
624
- }
625
- ```
626
-
627
- #### Model-View Binding
628
-
629
- To bind a single model to a component, create a global singleton or controller-specific model using the [Model tag](https://titaniumsdk.com/guide/Alloy_Framework/Alloy_Guide/Alloy_Views/Alloy_XML_Markup.html#model-element) in the XML markup of the main view and map the model attribute to the view component. To map the attribute to the view component, prefix the model name or id to the attribute, then enclose it with curly brackets or braces ('{' and '}').
630
-
631
- To do complex transformations on the model attributes, extend the model prototype with a `transform()` function. It should return the modified model as a JSON object.
632
-
633
- **app/models/album.js**
634
-
635
- ```javascript
636
- exports.definition = {
637
- config: {}, // model definition
638
- extendModel(Model) {
639
- _.extend(Model.prototype, {
640
- transform() {
641
- const transformed = this.toJSON();
642
- transformed.artist = transformed.artist.toUpperCase();
643
- return transformed;
644
- }
645
- });
646
- return Model;
647
- }
648
- };
649
- ```
732
+ > **⚠️ ⚠️ Warning**
733
+ > With the release of CLI 7.1.0, values passed in at creation of a view can be used as values in TSS and XML. For example, if the **foo** property was passed in at creation it can be used on a label:
734
+ >
735
+ > ```xml
736
+ > <Alloy>
737
+ > <Label text="$.args.foo" />
738
+ > </Alloy>
739
+ > ```
650
740
 
651
741
  ## Alloy Sync Adapters and Migrations
652
742
 
@@ -768,16 +858,16 @@ In Alloy, migrations are defined by JavaScript files located in the `app/migrati
768
858
 
769
859
  The migration file contains two functions that need to be implemented: `migration.up(migrator)` and `migration.down(migrator)`, where `migrator` is a special migration object that provides references to the database and table as well as some convenient functions for table operations:
770
860
 
771
- | Key | Description |
772
- | ------------- | ----------------------------------------------------------------------------- |
773
- | `db` | Handle to a `Ti.Database` instance. DO NOT CLOSE THIS HANDLE. |
774
- | `dbname` | Name of the database. |
775
- | `table` | Name of the table. Same as value of the `config.adapter.collection_name` key. |
776
- | `idAttribute` | Name of the columns attribute to use as the primary key. |
777
- | `createTable` | Function to create a table. Required parameter is the `columns` object. |
778
- | `dropTable` | Function to drop the current table from the database. |
779
- | `insertRow` | Function to insert data into the table. Useful for preloading data. |
780
- | `deleteRow` | Function to delete data from the table. |
861
+ | Key | Description |
862
+ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
863
+ | `db` | Handle to a `Ti.Database` instance. Use this handle to execute SQL calls using `db.execute`. DO NOT CLOSE THIS HANDLE OR OPEN A SECOND INSTANCE OF THE DATABASE. |
864
+ | `dbname` | Name of the database. |
865
+ | `table` | Name of the table. Same as value of the `config.adapter.collection_name` key. |
866
+ | `idAttribute` | Name of the columns attribute to use as the primary key. |
867
+ | `createTable` | Function to create a table. Required parameter is the `columns` object. |
868
+ | `dropTable` | Function to drop the current table from the database. |
869
+ | `insertRow` | Function to insert data into the table. Useful for preloading data. |
870
+ | `deleteRow` | Function to delete data from the table. |
781
871
 
782
872
  For example, the migration file below is the initial version of the database that preloads some data in the table.
783
873
 
@@ -996,13 +1086,41 @@ To use Backbone 1.1.2 to support Alloy Model and Collections objects, open the p
996
1086
 
997
1087
  #### Collection APIs
998
1088
 
999
- **Fetch Method Behavior Change**: Backbone Collection objects no longer emit the `reset` event after a `fetch()` call. To use old functionality, pass `{reset: true}` when calling `fetch()` or extend the Collection class.
1089
+ **Fetch Method Behavior Change**: Backbone Collection objects no longer emit the `reset` event after a `fetch()` call, which means data-bound views may not update automatically. **This could break existing apps.** To use old functionality, pass `{reset: true}` when calling `fetch()` or extend the Collection class:
1090
+
1091
+ ```javascript
1092
+ exports.definition = {
1093
+ config: {
1094
+ // Model configuration
1095
+ },
1096
+ extendModel(Model) {
1097
+ _.extend(Model.prototype, {
1098
+ // extended functions and properties go here
1099
+ });
1100
+ return Model;
1101
+ },
1102
+ extendCollection(Collection) {
1103
+ _.extend(Collection.prototype, {
1104
+ // For Backbone v1.1.2, uncomment the following to override the
1105
+ // fetch method to account for a breaking change in Backbone.
1106
+ /*
1107
+ fetch(options) {
1108
+ options = options ? _.clone(options) : {};
1109
+ options.reset = true;
1110
+ return Backbone.Collection.prototype.fetch.call(this, options);
1111
+ }
1112
+ */
1113
+ });
1114
+ return Collection;
1115
+ }
1116
+ };
1117
+ ```
1000
1118
 
1001
1119
  **New Set Method**: To smartly update the contents of a Collection (adding new models, removing missing ones, and merging those already present), call `set()`.
1002
1120
 
1003
1121
  **Return Value for Methods**: The return values of Collection's `add()`, `push()`, `remove()`, `reset()` and `shift()` methods return the changed model or list of models, instead of `this`.
1004
1122
 
1005
- **Add Method**: When invoking `add()` on a collection, passing `{merge: true}` will now cause duplicate models to have their attributes merged in to the existing models.
1123
+ **Add Method**: When invoking `add()` on a collection, passing `{merge: true}` will now cause duplicate models to have their attributes merged in to the existing models. To improve performance, `options.index` will no longer be set in the `add` event callback — use `collection.indexOf(model)` instead.
1006
1124
 
1007
1125
  #### Event APIs
1008
1126
 
@@ -1016,6 +1134,9 @@ To use Backbone 1.1.2 to support Alloy Model and Collections objects, open the p
1016
1134
 
1017
1135
  **Validation**: Model validation is now only enforced with the `save()` method. Previously, models were also validated with the `set()` method. To force validation when the `set()` method is called, pass `{validate: true}` to the method or extend the Model class. Also, validation now occurs even during 'silent' changes (passing `{silent: true}` to methods). Previously, it would not. Failed validations return the `invalid` event. Previously, a failed model validation would return the `error` event.
1018
1136
 
1137
+ > **⚠️ ⚠️ Warning**
1138
+ > To validate Model objects, implement the `validate()` method in the `extendModel` key of the model configuration file.
1139
+
1019
1140
  **Parse Method**: All `parse` methods now run after a `fetch`. You cannot change the `id` of a model during `parse`. The `parse` method receives `options` as a second parameter.
1020
1141
 
1021
1142
  **Other Changes**:
@@ -1025,10 +1146,45 @@ To use Backbone 1.1.2 to support Alloy Model and Collections objects, open the p
1025
1146
  * `url` and `urlRoot` properties may now be passed as options when instantiating a new Model.
1026
1147
  * If you want to maintain current models in a collection when using `fetch` the property has changed from `{add:true}` to `{remove:false}`.
1027
1148
 
1028
- #### Silent Option
1149
+ ### Parse Method
1150
+
1151
+ After fetching a model or a collection, all defined parse methods will now be run. So fetching a collection and getting back new models could cause both the collection to parse the list, and then each model to be parsed in turn, if you have both methods defined. By default, the parse method is a no-op function that directly passes the JSON response object.
1152
+
1153
+ You are no longer permitted to change the `id` of your model during `parse()`. Use `idAttribute` instead.
1154
+
1155
+ The parse function now receives the `options` dictionary as its second parameter. Previously, it would only be passed a raw `response` object.
1156
+
1157
+ ### Silent Option
1029
1158
 
1030
1159
  Passing `{silent:true}` to methods now suppresses the `change:attr` events, thus a data-bound view will not be updated to reflect the changes. The sql sync adapter passed this option by default. It has been updated to no longer pass that option when Backbone 1.1.2 is used (still passed with 0.9.2).
1031
1160
 
1161
+ If you want the new behavior where `change` events are suppressed, you will need to pass this option or extend the Model or Collection class. The following sample code extends the Model `set()` method by forcing the silent option to true:
1162
+
1163
+ ```javascript
1164
+ exports.definition = {
1165
+ config: {
1166
+ // Model configuration
1167
+ },
1168
+ extendModel(Model) {
1169
+ _.extend(Model.prototype, {
1170
+ // Forces silent true option when the model is updated
1171
+ set(attributes, options) {
1172
+ options = options ? _.clone(options) : {};
1173
+ options.silent = true;
1174
+ return Backbone.Model.prototype.set.call(this, attributes, options);
1175
+ }
1176
+ });
1177
+ return Model;
1178
+ },
1179
+ extendCollection(Collection) {
1180
+ _.extend(Collection.prototype, {
1181
+ // extended functions and properties go here
1182
+ });
1183
+ return Collection;
1184
+ }
1185
+ };
1186
+ ```
1187
+
1032
1188
  ### API Changes
1033
1189
 
1034
1190
  #### New APIs
@@ -60,7 +60,7 @@ Before using either method, you need to create class styles in the TSS files, ei
60
60
  }
61
61
  ```
62
62
 
63
- The previous style sheet defines various class and markup element styles for labels, buttons and windows. Alloy assigns a priority for each class, based on its order in the TSS file. Styles listed first receive a lower priority than ones listed afterwards. For example, if both the ldpi and hdpi classes are assigned to a label, since hdpi is after ldpi, the label text is 24 dp not 9 dp.
63
+ The previous style sheet defines various class and markup element styles for labels, buttons and windows. Alloy assigns a priority for each class, based on its order in the TSS file. Styles listed first receive a lower priority than ones listed afterwards. For example, if both the ldpi and hdpi classes are assigned to a label, since hdpi is after ldpi, the label text is 24 dp not 9 dp. Since the Label size of 14 dp is a markup element style and even though it appears after the class styles, it does not have a higher priority number since class styles have higher precedence over markup element styles. The label is still 24 dp not 14 dp. Properties defined inline in the markup and TSS id styles still take precedence over class styles.
64
64
 
65
65
  ## Generate a Dynamic Style
66
66
 
@@ -158,9 +158,8 @@ Note that code outside of the dialog view-controller is using the instance varia
158
158
 
159
159
  To modify the TSS classes of an object that has already been created, use the controller's `addClass`, `removeClass` and `resetClass` methods, which adds, removes or resets the TSS classes of a view object, respectively. As the classes are modified using these API calls, the view is automatically updated. To take advantage of these APIs, you need to enable autostyle for the components or else the view may not update properly.
160
160
 
161
- ::: warning ⚠️ Warning
162
- Using the `Require` or `Widget` elements to include external views in a controller-less view does not work with the `updateViews` method — you can include the external views, but the styles cannot be updated.
163
- :::
161
+ > **⚠️ ⚠️ Warning**
162
+ > Using the `Require` or `Widget` elements to include external views in a controller-less view does not work with the `updateViews` method — you can include the external views, but the styles cannot be updated.
164
163
 
165
164
  Pass a reference to the view object as the first parameter, then pass the classes to add or remove as an array or space-separated string as the second parameter. You can optionally specify inline properties as an optional third parameter.
166
165