--- title: ContextAwareness API category: Infusion --- The ContextAwareness API of Infusion provides a powerful suite of grades and utilities that allow a component to be responsive to aspects of its [context](Contexts.md) in a flexible and open-ended way. A component can name particular kinds of _adaptations_ (dimensions) that it is capable of, and for each of these adaptations, specify a list of environmental _checks_ to be made in a particular order, which will result in particular adaptations being chosen. These adaptations are expressed through the addition of extra [grade names](ComponentGrades.md) to the component during its construction. ### When and how to apply `fluid.contextAware` For lightweight cases of context adaptation, the [`distributeOptions`](IoCSS.md) scheme suffices, in that it enables a component to be responsive to broadcasts "advising" it from around the component tree in a free-form and controllable away. However, when a component needs to take a clearer role in responding to potentially many kinds of requests for adaptation, where these can be organised around two or more "axes" or "dimensions" of adaptation that can be clearly named and identified, it should derive from the `fluid.contextAware` grade and advertise some of its dimensions of adaptations in its own options. These dimensions themselves can always be extended by further contributions to the component's options from all the usual sources - direct options, subcomponent options, and options distributions from elsewhere in the tree. Any component derived from `fluid.contextAware` will advertise an area of its options named `contextAwareness` which organises the rules for its adaptation in a hierarchical way - at the top level by "adaptation" and then at the nested level by "checks". ### Structure of this API This page describes how various features of the framework and the ContextAwareness API cooperate together. These consist of: * The [`fluid.contextAware`](#adaptationrecord-members-in-a-contextawareness-record) grade and the `contextAwareness` area of options that it responds to to produce adaptations * The [`fluid.contextAware.makeChecks`](#making-contexts-visible-and-removing-them-with-fluidcontextawaremakechecks-and-fluidcontextawareforgetchecks) API for converting aspects of the actual context or environment (e.g. capabilities of the browser, user's requirements or purpose of the application) into context names which `contextAwareness` can respond to * The [`fluid.contextAware.forgetChecks`](#making-contexts-visible-and-removing-them-with-fluidcontextawaremakechecks-and-fluidcontextawareforgetchecks) API for eliminating checks created by `fluid.contextAware.makeChecks` * The [`fluid.contextAware.makeAdaptation`](#defining-and-broadcasting-a-fresh-adaptation-in-one-operation-with-fluidcontextawaremakeadaptation) API which can be used by 3rd parties to broadcast `contextAwareness` records into implementation components that they which to make (more) adaptable ## Simple example - speech API-aware component This simple example invokes the `fluid.textToSpeech.isSupported` feature detector, which returns `true` if the current browser supports the [HTML5 Speech API](https://wicg.github.io/speech-api/). We use the `fluid.contextAware.makeChecks` function to assign the result of this feature detection to a _context_ named `fluid.supportsTTS`. We can then use this context to conditionally switch in an extra [grade name](ComponentGrades.md), `examples.myComponent.speechAware` into the `examples.myComponent` component: ```javascript fluid.contextAware.makeChecks({ "fluid.supportsTTS": "fluid.textToSpeech.isSupported" }); fluid.defaults("examples.myComponent", { gradeNames: ["fluid.component", "fluid.contextAware"], contextAwareness: { speechAware: { checks: { speechAware: { contextValue: "{fluid.supportsTTS}", gradeNames: "examples.myComponent.speechAware" } }, defaultGradeNames: "examples.myComponent.nonSpeechAware" } } }); ``` The options within `contextAwareness` could be contributed by any integrator, not necessarily the component's original author, and have a layout that makes it easy to target and override parts of the existing structure with updated options. ## `adaptationRecord` members in a `contextAwareness` record Each component implementing `fluid.contextAware` accepts a top-level record in its options at the path named `contextAwareness`. The top level structure of the `contextAwareness` record consists of a free hash of `adaptationName` strings to `adaptationRecord` structures: ```snippet { : , : , ... } ``` The `adaptationName` strings are considered as namespaces for the purposes of [priority](Priorities.md) resolution (see the priority entry in the following table). The elements of the `adaptationRecord` are described in the following table:
Members of an adaptationRecord entry within the contextAwareness block of a fluid.contextAware component< /th>
Member Type Description
checks (optional) Hash of checkNamespace to checkRecord A free hash of namespace names for checks, to entries describing how a context check is to be made, and what gradeNames should result if the check is successful. (See Structure of members in a checkRecord below for details.)
defaultGradeNames (optional) String or Array of String One or more gradeNames to be the result if none of the checks entries matches
priority (optional) Priority value - see Priorities for a full explanation The priority (if any) that the gradeNames resulting from this dimension should have over those resulting from any other dimension. This should be an entry of the form before:adaptationName or after:adaptationName for one of the other dimensions attached to this component within contextAwareness
The result of the `contextAwareness` record is that a number of the elements within `checks` will be evaluated in the visible context, and result in a number of `gradeNames` which will then be contributed into the `gradeNames` of the instantiating component in a particular order. This order is governed by both the `priority` entry at the adaptation level as well as at the check level. ## `checkRecord` members in an `adaptationRecord` The `checkRecord` structure which is used in the first row of the table above is described now:
Members of a checkRecord entry within a adaptationRecord block of a fluid.contextAware component
Member Type Description
contextValue String IoC reference A standard IoC reference, either consisting of a bare context reference such as {contextName} or to a precise value such as {contextName}.further.path which should be sought by this check. If a bare context name is supplied, the checked path will default to options.value. If the context name does not match, the expression will evaluate to undefined
equals (optional) String, Number or Boolean A value with which the context value fetched from contextValue should be checked. If omitted, this defaults to true. The check will pass if the context value referenced in contextValue can be found, and matches any value supplied in equals (or the default of true).
gradeNames (optional) String or Array of String One or more gradeNames that will be returned out to the contextAwareness system if this check passes.
priority (optional) Priority value - see Priorities for a full explanation The priority (if any) that the gradeNames resulting from this dimension should have over those resulting from any other dimension. This should be an entry of the form before:adaptationName or after:adaptationName for one of the other dimensions attached to this component within contextAwareness
### Example `contextAwareness` record The most adaptable component in the framework is currently the [Uploader](UploaderAPI.md) which currently can respond to three "dimensions" of adaptation. Two of these, `technology` and `liveness`, are advertised in its own `contextAwareness` record: ```javascript fluid.defaults("fluid.uploader", { gradeNames: ["fluid.viewComponent", "fluid.contextAware"], contextAwareness: { technology: { defaultGradeNames: "fluid.uploader.singleFile" }, liveness: { priority: "before:technology", checks: { localDemoOption: { contextValue: "{uploader}.options.demo", gradeNames: "fluid.uploader.demo" } }, defaultGradeNames: "fluid.uploader.live" } } }); ``` `technology` refers to the implementation technology of the uploader. Although all technologies other than a modern HTML5 engine have been removed from the current framework image, the basic architecture to support other engines still exists and could be contributed to in future. The `liveness` adaptation relates to the mocking infrastructure for the Uploader which exists at two levels. Firstly, there is the "demo uploader" which mocks all of the engine-side implementation, and secondly the uploader can be run in various styles of integration tests which only mock the transport level which actually performs the file upload. ### Example of dynamically broadcasting a fresh adaptation Finally, a third dimension of adaptation is supported by the Uploader's capability to be configured in a way that it will respond to previous instances of its own API - in particular that delivered for Infusion 1.2, released in April 2010, and Infusion 1.3, released in November 2010. This is implemented by allowing a dynamic contribution of a fresh dimension to the uploader's `contextAwareness` record from separate implementation files: ```javascript fluid.defaults("fluid.uploader.compatibility.distributor.1_3", { distributeOptions: { record: { "1_2": { contextValue: "{fluid.uploader.requiredApi}.options.value", equals: "fluid_1_2", gradeNames: "fluid.uploader.compatibility.1_2" } }, target: "{/ fluid.uploader}.options.contextAwareness.apiCompatibility.checks" } }); // Actually construct a component instance performing the options broadcast into all uploaders fluid.constructSingle([], { singleRootType: "fluid.uploader.compatibility.distributor", type: "fluid.uploader.compatibility.distributor.1_3" }); // The grade that contextAwareness ends up contributing into the uploader, if the rule is activated fluid.defaults("fluid.uploader.compatibility.1_2", { transformOptions: { transformer: "fluid.model.transformWithRules", config: fluid.compat.fluid_1_2.uploader.optionsRules } }); ``` The defaults block `fluid.uploader.compatibility.distributor.1_3` contains an options distribution which causes a third dimension to be allocated in the uploader's `contextAwareness`, named `apiCompatibility` — this can be done simply by arranging to broadcast the appropriate options into it. Once we have defined this options distribution, we actually need to construct a component instance which holds and operates them — this is done via the `fluid.constructSingle` line. This utility automatically arranges for a singleton instance, uniquified at the component tree's top level by the type `singleRootType` which has a very similar function to the option of the same name consumed by the `fluid.resolveRootSingle` grade described in the documentation on [Contexts](Contexts.md#global-components-fluidresolveroot-and-fluidresolverootsingle). Having shown the basic operation of the _receiver_ of contextual information, we'll now describe the group of utilities, including `fluid.constructSingle` that we just met, which can be used by integrators and implementors to coordinate the visibility of context names and distributions from them. Note that the combined effect of the first two defaults blocks shown in this example can be achieved "all-in-one" by a single call to the dedicated utility [`fluid.contextAware.makeAdaptation`](#defining-and-broadcasting-a-fresh-adaptation-in-one-operation-with-fluidcontextawaremakeadaptation). ## Making contexts visible and removing them with `fluid.contextAware.makeChecks` and `fluid.contextAware.forgetChecks` The `checkRecord` structures described in the table above, by default reference context paths which hold values at an option named value (by default holding the boolean `true`) which are compared against a value held equals (also defaulting to `true`). The `ContextAwareness` API includes two helper functions to assist integrators to construct components matching contexts of this form, and removing them when they are no longer required. These contexts can be issued with a call of the form: ```javascript fluid.contextAware.makeChecks(checkStructure); ``` The `checkStructure` argument holds a hash of `contextName` strings to `checkEntry` records, of the form ```snippet { : , : , ... } ``` which is described in the following table:
Members of a checkEntry record supplied as an argument to fluid.contextAware.makeChecks
Member Type Description
func/funcName String IoC reference or global function name A function name or IoC reference to a function to be evaluated to produce the context value
value String, Number or Boolean The value to be supplied at the value path in the options tructure of the constructed context
You must supply exactly one of `func`, `funcName` or `value`. ### Example of `fluid.contextAware.makeChecks` ```javascript fluid.contextAware.makeChecks({ "fluid.browser.supportsBinaryXHR": { funcName: "fluid.enhance.supportsBinaryXHR" }, "fluid.browser.supportsFormData": { funcName: "fluid.enhance.supportsFormData" } }); ``` In the above example, the two global functions `fluid.enhance.supportsBinaryXHR` and `fluid.enhance.supportsFormData` will be executed, and their return values added into contexts with the names `fluid.browser.supportsBinaryXHR` and `fluid.browser.supportsFormData`. The contexts registered by `fluid.contextAware.makeChecks` can be erased from the system by the use of the call ```snippet fluid.contextAware.forgetChecks(); ``` Here, `contextNames` is can hold either a `String` or `Array of String` holding the keys from the structures previously supplied to `fluid.contextAware.makeChecks` ### Example of `fluid.contextAware.forgetChecks` For example, the checks registered in the above example `fluid.contextAware.makeChecks` call could be erased by a call to ```javascript fluid.contextAware.forgetChecks(["fluid.browser.supportsBinaryXHR", "fluid.browser.supportsFormData"]); ``` ## Defining and broadcasting a fresh adaptation in one operation with `fluid.contextAware.makeAdaptation` A very common use case is to define an adaptation (that is, a `distributeOptions` block which targets the `contextAwareness` area of a collection of components in the tree), and then to create an instance of a single, well-known component which actually broadcasts the adaptation. This was what we did in two steps (`fluid.defaults` plus `fluid.constructSingle`) in the above [example `contextAwareness` broadcast](#example-of-dynamically-broadcasting-a-fresh-adaptation) * this can be done in a single step using the `fluid.contextAware.makeAdaptation` API. ```snippet fluid.contextAware.makeAdaptation(); ``` This accepts a single structure `adaptationRecord` with a number of required fields:
Members of a adaptationRecord record supplied as an argument to fluid.contextAware.makeAdaptation
Member Type Description
distributionName String A grade name — the name to be given to the fabricated grade which performs the broadcast
targetName String A grade name — the name of the grade to receive the adaptation
adaptationName String The name of the contextAwareness record (the top-level adaptationRecord) to receive the broadcast record — this will be a simple string
checkName String The name of the checkRecord record (within the adaptationRecord) to receive the broadcast record — this will be a simple string
record Object (checkRecord) The checkRecord which is to be broadcast — containing fields contextValue, gradeNames etc. as described above
### Example of calling `fluid.contextAware.makeAdaptation` For example, the pair of calls in the above [example `contextAwareness` broadcast](#example-of-dynamically-broadcasting-a-fresh-adaptation) could be achieved by the following single call to `fluid.contextAware.makeAdaptation`: ```javascript fluid.contextAware.makeAdaptation({ distributionName: "fluid.uploader.compatibility.distributor.1_3", targetName: "fluid.uploader", adaptationName: "apiCompatibility", checkName: "1_2", record: { contextValue: "{fluid.uploader.requiredApi}.options.value", equals: "fluid_1_2", gradeNames: "fluid.uploader.compatibility.1_2" } }); ```