mirror of
https://github.com/pebble-dev/clay.git
synced 2026-09-06 09:07:19 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdcd820f7c | ||
|
|
51a44b18b0 | ||
|
|
64931dabc9 | ||
|
|
b7be587542 | ||
|
|
4508c73de2 | ||
|
|
f804cb0efd | ||
|
|
525a78fc53 | ||
|
|
05c62d466e | ||
|
|
dbf798daff | ||
|
|
b91b45bd23 | ||
|
|
2e447e5cd2 | ||
|
|
9782737256 | ||
|
|
3a4d962a37 | ||
|
|
87d8b91153 | ||
|
|
7bf4117d87 | ||
|
|
35fc64de99 | ||
|
|
de982960e2 | ||
|
|
797fa1d9ab | ||
|
|
4fb8db32da | ||
|
|
aa8409912c | ||
|
|
8e3cd119b8 | ||
|
|
beb623f4fd | ||
|
|
226dd682e0 | ||
|
|
011f40ea0d | ||
|
|
a98b4e69c1 | ||
|
|
0ad931e47c | ||
|
|
f7717dc781 | ||
|
|
2f5f3cc4e8 | ||
|
|
3b9bf842cb | ||
|
|
eb1d336f8f | ||
|
|
d6461e1fb5 | ||
|
|
fa72cfb3a3 | ||
|
|
b50a7dc72d | ||
|
|
7def2f741d | ||
|
|
ca498c6e3c | ||
|
|
060704cb1a | ||
|
|
aa30ef7d7a | ||
|
|
1cd4590691 | ||
|
|
75aaa07048 | ||
|
|
5b2aba4312 | ||
|
|
4584fe5dc5 | ||
|
|
d50ff0a9a4 | ||
|
|
c908e681ad | ||
|
|
8fdd5dad07 | ||
|
|
2169d5334f | ||
|
|
94428b1826 |
@@ -27,3 +27,5 @@ build/Release
|
|||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
tmp
|
tmp
|
||||||
|
|
||||||
|
dist
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Clay
|
# Clay
|
||||||
Clay is a JavaScript library that makes it easy to add offline configuration pages to your Pebble apps. All you need to get started is a couple lines of JavaScript and a JSON file; no servers or HTML required.
|
Clay is a JavaScript library that makes it easy to add offline configuration pages to your Pebble apps. All you need to get started is a couple lines of JavaScript and a JSON file; no servers or HTML required.
|
||||||
|
|
||||||
Clay will by default automatically handle the 'showConfiguration' and 'webviewclosed' events traditionally implemented by developers to relay configuration settings to the watch side of the app. This step is not required when using Clay, since each config item is given the same `appKey` as defined in `appinfo.json` (or PebbleKit JS Message Keys on CloudPebble), and is automatically transmitted once the configuration page is submitted by the user. Developers can override this behavior by implementing a [custom function](#custom-function).
|
Clay will by default automatically handle the 'showConfiguration' and 'webviewclosed' events traditionally implemented by developers to relay configuration settings to the watch side of the app. This step is not required when using Clay, since each config item is given the same `appKey` as defined in `appinfo.json` (or PebbleKit JS Message Keys on CloudPebble), and is automatically transmitted once the configuration page is submitted by the user. Developers can override this behavior by [handling the events manually](#handling-the-showconfiguration-and-webviewclosed-events-manually).
|
||||||
|
|
||||||
**Clay is still in early development and may be missing some features. We would love your feedback! Pease submit any ideas or features via GitHub Issues.**
|
**Clay is still in early development and may be missing some features. We would love your feedback! Pease submit any ideas or features via GitHub Issues.**
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ Clay will by default automatically handle the 'showConfiguration' and 'webviewcl
|
|||||||
|
|
||||||
Clay will eventually be built into the Pebble SDK. However, while it is still in beta you will need to follow the steps shown below:
|
Clay will eventually be built into the Pebble SDK. However, while it is still in beta you will need to follow the steps shown below:
|
||||||
|
|
||||||
1. Download the Clay distribution file from: [dist/clay.js](dist/clay.js).
|
1. Download the **clay.js** distribution file from the [latest release](https://github.com/pebble/clay/releases/latest).
|
||||||
2. Drop `clay.js` in your project's `src/js` directory.
|
2. Drop `clay.js` in your project's `src/js` directory.
|
||||||
3. Create a JSON file called `config.json` and place it in your `src/js` directory.
|
3. Create a JSON file called `config.json` and place it in your `src/js` directory.
|
||||||
4. In order for JSON files to work you may need to change a line in your `wscript` from `ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js'))` to `ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob(['src/js/**/*.js', 'src/js/**/*.json']))`.
|
4. In order for JSON files to work you may need to change a line in your `wscript` from `ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob('src/js/**/*.js'))` to `ctx.pbl_bundle(binaries=binaries, js=ctx.path.ant_glob(['src/js/**/*.js', 'src/js/**/*.json']))`.
|
||||||
@@ -27,7 +27,7 @@ Clay will eventually be built into the Pebble SDK. However, while it is still in
|
|||||||
Clay will eventually be built into CloudPebble. However while it is still in beta, you will need to follow some steps
|
Clay will eventually be built into CloudPebble. However while it is still in beta, you will need to follow some steps
|
||||||
|
|
||||||
1. Create a new JavaScript file called `clay.js`.
|
1. Create a new JavaScript file called `clay.js`.
|
||||||
2. Copy the contents of the Clay distribution file from [dist/clay.js](dist/clay.js) into your newly created `clay.js` file.
|
2. Copy the contents from the **clay.js** distribution file found in the [latest release](https://github.com/pebble/clay/releases/latest) into your newly created `clay.js` file.
|
||||||
3. Create another JavaScript file called `config.js` with the following content. This will act as your config's root array element, from which the rest of the page is built up:
|
3. Create another JavaScript file called `config.js` with the following content. This will act as your config's root array element, from which the rest of the page is built up:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@@ -67,7 +67,7 @@ Your root element **must** be an array. This represents the entire page. Inside
|
|||||||
|
|
||||||
## Components
|
## Components
|
||||||
|
|
||||||

|
<img src="src/images/example.png" width="360" title="Example">
|
||||||
|
|
||||||
### Section
|
### Section
|
||||||
|
|
||||||
@@ -178,6 +178,7 @@ Standard text input field.
|
|||||||
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
||||||
| label | string | The label that should appear next to this item. |
|
| label | string | The label that should appear next to this item. |
|
||||||
| defaultValue | string | The default value of the input field. |
|
| defaultValue | string | The default value of the input field. |
|
||||||
|
| description | string | Optional sub-text to include below the component |
|
||||||
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attributes such as `required` or `type`. |
|
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attributes such as `required` or `type`. |
|
||||||
|
|
||||||
|
|
||||||
@@ -215,6 +216,7 @@ Switch for a single item.
|
|||||||
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
||||||
| label | string | The label that should appear next to this item. |
|
| label | string | The label that should appear next to this item. |
|
||||||
| defaultValue | int\|boolean | The default value of the toggle. Defaults to `false` if not specified. |
|
| defaultValue | int\|boolean | The default value of the toggle. Defaults to `false` if not specified. |
|
||||||
|
| description | string | Optional sub-text to include below the component |
|
||||||
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
||||||
|
|
||||||
|
|
||||||
@@ -249,6 +251,7 @@ A dropdown menu containing multiple options.
|
|||||||
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
||||||
| label | string | The label that should appear next to this item. |
|
| label | string | The label that should appear next to this item. |
|
||||||
| defaultValue | string | The default value of the dropdown menu. Must match a value in the `options` array. |
|
| defaultValue | string | The default value of the dropdown menu. Must match a value in the `options` array. |
|
||||||
|
| description | string | Optional sub-text to include below the component |
|
||||||
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
||||||
| options | array of objects | The options you want to appear in the dropdown menu. Each option is an object with a `label` and `value` property. |
|
| options | array of objects | The options you want to appear in the dropdown menu. Each option is an object with a `label` and `value` property. |
|
||||||
|
|
||||||
@@ -301,6 +304,7 @@ A color picker containing the 64 supported colors on Basalt and Chalk.
|
|||||||
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
||||||
| label | string | The label that should appear next to this item. |
|
| label | string | The label that should appear next to this item. |
|
||||||
| defaultValue | string OR int | The default color. Always use the uncorrected value even if `sunlight` is true. The component will do the conversion internally. |
|
| defaultValue | string OR int | The default color. Always use the uncorrected value even if `sunlight` is true. The component will do the conversion internally. |
|
||||||
|
| description | string | Optional sub-text to include below the component |
|
||||||
| sunlight | boolean | Use the color-corrected sunlight color palette if `true`, else the uncorrected version. Defaults to `true` if not specified. |
|
| sunlight | boolean | Use the color-corrected sunlight color palette if `true`, else the uncorrected version. Defaults to `true` if not specified. |
|
||||||
|
|
||||||
##### Example
|
##### Example
|
||||||
@@ -332,6 +336,7 @@ A list of options allowing the user can only choose one option to submit.
|
|||||||
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
||||||
| label | string | The label that should appear next to this item. |
|
| label | string | The label that should appear next to this item. |
|
||||||
| defaultValue | string | The default selected item. Must match a value in the `options` array. |
|
| defaultValue | string | The default selected item. Must match a value in the `options` array. |
|
||||||
|
| description | string | Optional sub-text to include below the component |
|
||||||
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
||||||
| options | array of objects | The options you want to appear in the radio group. Each option is an object with a `label` and `value` property. |
|
| options | array of objects | The options you want to appear in the radio group. Each option is an object with a `label` and `value` property. |
|
||||||
|
|
||||||
@@ -376,6 +381,7 @@ A list of options where a user may choose more than one option to submit.
|
|||||||
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
| appKey | string (unique) | The AppMessage key matching the `appKey` item defined in your `appinfo.json`. Set this to a unique string to allow this item to be looked up using `Clay.getItemsByAppKey()` in your custom function. You must set this if you wish for the value of this item to be persisted after the user closes the config page. |
|
||||||
| label | string | The label that should appear next to this item. |
|
| label | string | The label that should appear next to this item. |
|
||||||
| defaultValue | array of strings | The default selected items. Each value must match one in the `options` array. |
|
| defaultValue | array of strings | The default selected items. Each value must match one in the `options` array. |
|
||||||
|
| description | string | Optional sub-text to include below the component |
|
||||||
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
| attributes | object | An object containing HTML attributes to set on the input field. You can add basic HTML5 validation this way by setting attribute such as `required`. |
|
||||||
| options | array of objects | The options you want to appear in the checkbox group. Each option is an object with a `label` and `value` property. |
|
| options | array of objects | The options you want to appear in the checkbox group. Each option is an object with a `label` and `value` property. |
|
||||||
|
|
||||||
@@ -443,60 +449,75 @@ The submit button for the page. You **MUST** include this component somewhere in
|
|||||||
|
|
||||||
## Manipulators
|
## Manipulators
|
||||||
|
|
||||||
Each component has a **manipulator**. This is a set of methods used to talk to the item on the page. At a minimum, manipulators must have a `.get()` and `.set(value)` method. When the config page is closed, the `.get()` method is run on all components registered with an `appKey` to construct the object sent to the C app. Many of these methods fire an event when the method is called. You can listen for these events with `ClayItem.on()`.
|
Each component has a **manipulator**. This is a set of methods used to talk to the item on the page.
|
||||||
|
At a minimum, manipulators must have a `.get()` and `.set(value)` method however there are also methods to assist in interactivity such as `.hide()` and `.disable()`.
|
||||||
|
**NOTE:** There is currently no way to disable or hide an entire section. You must disable/hide each item in the section to achieve this effect.
|
||||||
|
When the config page is closed, the `.get()` method is run on all components registered with an `appKey` to construct the object sent to the C app.
|
||||||
|
Many of these methods fire an event when the method is called. You can listen for these events with `ClayItem.on()`.
|
||||||
|
|
||||||
#### html
|
#### html
|
||||||
|
|
||||||
| Method | Returns | Event Fired | Description |
|
| Method | Returns | Event Fired | Description |
|
||||||
|--------|---------|-------------| ------------|
|
|--------|---------|-------------| ------------|
|
||||||
| `.set( [string\|HTML] value)` | `ClayItem` | `change` | Sets the content of this item. |
|
| `.set( [string\|HTML] value)` | `ClayItem` | `change` | Sets the content of this item. |
|
||||||
| `.get()` | `string` | Gets the content of this item. |
|
| `.get()` | `string` | | Gets the content of this item. |
|
||||||
|
| `.hide()` | `ClayItem` | `hide` | Hides the item |
|
||||||
|
| `.show()` | `ClayItem` | `show` | Shows the item |
|
||||||
|
|
||||||
#### val
|
#### val
|
||||||
|
|
||||||
| Method | Returns | Event Fired | Description |
|
| Method | Returns | Event Fired | Description |
|
||||||
|--------|---------|-------------| ------------|
|
|--------|---------|-------------| ------------|
|
||||||
| `.set( [string] value)` | `ClayItem` | `change` | Sets the value of this item. |
|
| `.set( [string] value)` | `ClayItem` | `change` | Sets the value of this item. |
|
||||||
| `.get()` | `string` | Gets the content of this item. |
|
| `.get()` | `string` | | Gets the content of this item. |
|
||||||
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
||||||
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
||||||
|
| `.hide()` | `ClayItem` | `hide` | Hides the item |
|
||||||
|
| `.show()` | `ClayItem` | `show` | Shows the item |
|
||||||
|
|
||||||
#### checked
|
#### checked
|
||||||
|
|
||||||
| Method | Returns | Event Fired | Description |
|
| Method | Returns | Event Fired | Description |
|
||||||
|--------|---------|-------------| ------------|
|
|--------|---------|-------------| ------------|
|
||||||
| `.set( [boolean\|int] value)` | `ClayItem` | `change` | Check/uncheck the state of this item. |
|
| `.set( [boolean\|int] value)` | `ClayItem` | `change` | Check/uncheck the state of this item. |
|
||||||
| `.get()` | `int` | 1 if checked, 0 if not checked |
|
| `.get()` | `int` | | 1 if checked, 0 if not checked |
|
||||||
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
||||||
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
||||||
|
| `.hide()` | `ClayItem` | `hide` | Hides the item |
|
||||||
|
| `.show()` | `ClayItem` | `show` | Shows the item |
|
||||||
|
|
||||||
#### color
|
#### color
|
||||||
|
|
||||||
| Method | Returns | Event Fired | Description |
|
| Method | Returns | Event Fired | Description |
|
||||||
|--------|---------|-------------| ------------|
|
|--------|---------|-------------| ------------|
|
||||||
| `.set( [string\|int] value)` | `ClayItem` | `change` | Sets the color picker to the provided color. If the value is a string, it must be provided in hex notation eg `'FF0000'`. |
|
| `.set( [string\|int] value)` | `ClayItem` | `change` | Sets the color picker to the provided color. If the value is a string, it must be provided in hex notation eg `'FF0000'`. |
|
||||||
| `.get()` | `int` | Get the chosen color. This is returned as a number in order to make it easy to use on the watch side using `GColorFromHEX()`. |
|
| `.get()` | `int` | | Get the chosen color. This is returned as a number in order to make it easy to use on the watch side using `GColorFromHEX()`. |
|
||||||
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
||||||
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
||||||
|
| `.hide()` | `ClayItem` | `hide` | Hides the item |
|
||||||
|
| `.show()` | `ClayItem` | `show` | Shows the item |
|
||||||
|
|
||||||
#### radiogroup
|
#### radiogroup
|
||||||
|
|
||||||
| Method | Returns | Event Fired | Description |
|
| Method | Returns | Event Fired | Description |
|
||||||
|--------|---------|-------------| ------------|
|
|--------|---------|-------------| ------------|
|
||||||
| `.set( [string] value)` | `ClayItem` | `change` | Checks the radio button that corresponds to the provided value. |
|
| `.set( [string] value)` | `ClayItem` | `change` | Checks the radio button that corresponds to the provided value. |
|
||||||
| `.get()` | `string` | Gets the value of the checked radio button in the list. |
|
| `.get()` | `string` | | Gets the value of the checked radio button in the list. |
|
||||||
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
||||||
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
||||||
|
| `.hide()` | `ClayItem` | `hide` | Hides the item |
|
||||||
|
| `.show()` | `ClayItem` | `show` | Shows the item |
|
||||||
|
|
||||||
#### checkboxgroup
|
#### checkboxgroup
|
||||||
|
|
||||||
| Method | Returns | Event Fired | Description |
|
| Method | Returns | Event Fired | Description |
|
||||||
|--------|---------|-------------| ------------|
|
|--------|---------|-------------| ------------|
|
||||||
| `.set( [array] value)` | `ClayItem` | `change` | Checks the checkboxes that corresponds to the provided list of values. |
|
| `.set( [array] value)` | `ClayItem` | `change` | Checks the checkboxes that corresponds to the provided list of values. |
|
||||||
| `.get()` | `Array.<string>` | Gets an array of strings representing the list of the values of the checked items |
|
| `.get()` | `Array.<string>` | | Gets an array of strings representing the list of the values of the checked items |
|
||||||
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
|
||||||
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
|
||||||
|
| `.hide()` | `ClayItem` | `hide` | Hides the item |
|
||||||
|
| `.show()` | `ClayItem` | `show` | Shows the item |
|
||||||
|
|
||||||
# Extending Clay
|
# Extending Clay
|
||||||
|
|
||||||
@@ -591,7 +612,13 @@ module.exports = function(minified) {
|
|||||||
var coolStuffToggle = Clay.getItemByAppKey('cool_stuff');
|
var coolStuffToggle = Clay.getItemByAppKey('cool_stuff');
|
||||||
toggleBackground.call(coolStuffToggle);
|
toggleBackground.call(coolStuffToggle);
|
||||||
coolStuffToggle.on('change', toggleBackground);
|
coolStuffToggle.on('change', toggleBackground);
|
||||||
|
|
||||||
|
// Hide the color picker for aplite
|
||||||
|
if (Clay.meta.activeWatchInfo.platform === 'aplite') {
|
||||||
|
Clay.getItemByAppKey('background').hide();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -607,7 +634,11 @@ This is the main way of talking to your generated config page.
|
|||||||
|----------|------|-------------|
|
|----------|------|-------------|
|
||||||
| `.EVENTS.BEFORE_BUILD` | String | Dispatched prior to building the page. |
|
| `.EVENTS.BEFORE_BUILD` | String | Dispatched prior to building the page. |
|
||||||
| `.EVENTS.AFTER_BUILD` | String | Dispatched after building the page. |
|
| `.EVENTS.AFTER_BUILD` | String | Dispatched after building the page. |
|
||||||
| `.config` | Array | Reference to the config passed to the constructer and used for generating the page. |
|
| `.config` | Array | Reference to the config passed to the constructor and used for generating the page. |
|
||||||
|
| `.meta` | Object | Contains information about the current user and watch |
|
||||||
|
| `.meta.activeWatchInfo` | watchinfo\|null | An object containing information on the currently connected Pebble smartwatch or null if unavailable. Read more [here](https://developer.pebble.com/docs/js/Pebble/#getActiveWatchInfo). |
|
||||||
|
| `.meta.accountToken` | String | A unique account token that is associated with the Pebble account of the current user. Read more [here](https://developer.pebble.com/docs/js/Pebble/#getAccountToken). |
|
||||||
|
| `.meta.watchToken` | String | A unique token that can be used to identify a Pebble device. Read more [here](https://developer.pebble.com/docs/js/Pebble/#getWatchToken). |
|
||||||
|
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
@@ -637,7 +668,7 @@ This is the main way of talking to your generated config page.
|
|||||||
| `.appKey` | String | The ID of the item if provided in the config. |
|
| `.appKey` | String | The ID of the item if provided in the config. |
|
||||||
| `.config` | Object | Reference to the config passed to the constructer. |
|
| `.config` | Object | Reference to the config passed to the constructer. |
|
||||||
| `$element` | $Minified | A Minified list representing the root HTML element of the config item. |
|
| `$element` | $Minified | A Minified list representing the root HTML element of the config item. |
|
||||||
| `$manipulatorTarget` | A Minified list representing the HTML element with **data-manipulator-target** set. This is generally pointing to the main `<input>` element and will be used for binding events. |
|
| `$manipulatorTarget` | $Minified | A Minified list representing the HTML element with **data-manipulator-target** set. This is generally pointing to the main `<input>` element and will be used for binding events. |
|
||||||
|
|
||||||
|
|
||||||
#### Methods
|
#### Methods
|
||||||
|
|||||||
+14
-28
@@ -24,32 +24,31 @@ module.exports = [
|
|||||||
"type": "input",
|
"type": "input",
|
||||||
"appKey": "email",
|
"appKey": "email",
|
||||||
"defaultValue": "",
|
"defaultValue": "",
|
||||||
"label": "Email",
|
"label": "Input Field",
|
||||||
|
"description": "This is a description for the input component. " +
|
||||||
|
"You can add <strong>html</strong> in here too.",
|
||||||
"attributes": {
|
"attributes": {
|
||||||
"placeholder": "eg: name@domain.com",
|
"placeholder": "Placeholder set with attributes"
|
||||||
"limit": 10,
|
|
||||||
"required": "required",
|
|
||||||
type: "email"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "toggle",
|
"type": "toggle",
|
||||||
"appKey": "cool_stuff",
|
"appKey": "cool_stuff",
|
||||||
"label": "Enable Cool Stuff",
|
"label": "This is a Toggle",
|
||||||
"defaultValue": false
|
"defaultValue": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "color",
|
"type": "color",
|
||||||
"appKey": "colorTest",
|
"appKey": "colorTest",
|
||||||
"defaultValue": "FF0000",
|
"defaultValue": "FF0000",
|
||||||
"label": "Background Color",
|
"label": "Standard Color Picker",
|
||||||
"sunlight": false
|
"sunlight": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "color",
|
"type": "color",
|
||||||
"appKey": "sunnyColorTest",
|
"appKey": "sunnyColorTest",
|
||||||
"defaultValue": "00FF00",
|
"defaultValue": "00FF00",
|
||||||
"label": "Sunny Color",
|
"label": "Sunny Color Picker",
|
||||||
"sunlight": true
|
"sunlight": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -64,46 +63,33 @@ module.exports = [
|
|||||||
{
|
{
|
||||||
"type": "radiogroup",
|
"type": "radiogroup",
|
||||||
"appKey": "radiogroup-test",
|
"appKey": "radiogroup-test",
|
||||||
"label": "Radio test",
|
"label": "Radio Group",
|
||||||
"options": [
|
"options": [
|
||||||
{ "label": "Test thing one", "value": "one" },
|
{ "label": "Test thing", "value": "one" },
|
||||||
{ "label": "Another thing", "value": "two" },
|
{ "label": "Another thing", "value": "two" },
|
||||||
{ "label": "One really long thing that would not fit", "value": "three" },
|
{ "label": "Final thing with <em>html</em>", "value": "three" }
|
||||||
{ "label": "Small", "value": "quote' \"test" },
|
|
||||||
{ "label": "Final thing", "value": "three" }
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "checkboxgroup",
|
"type": "checkboxgroup",
|
||||||
"appKey": "checkboxgroup-test",
|
"appKey": "checkboxgroup-test",
|
||||||
"defaultValue": ["quote' \"test", "two"],
|
"defaultValue": ["quote' \"test", "two"],
|
||||||
"label": "Checkbox test",
|
"label": "Checkbox Group",
|
||||||
"options": [
|
"options": [
|
||||||
{ "label": "Test <strong>thing</strong> one", "value": "one" },
|
{ "label": "First thing", "value": "three" },
|
||||||
{ "label": "Another thing", "value": "two" },
|
{ "label": "Another thing", "value": "two" },
|
||||||
{ "label": "One really long thing that would not fit", "value": "three" },
|
|
||||||
{ "label": "Small", "value": "quote' \"test" },
|
|
||||||
{ "label": "Final thing", "value": "three" }
|
{ "label": "Final thing", "value": "three" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "input",
|
|
||||||
"appKey": "date",
|
|
||||||
"defaultValue": "",
|
|
||||||
"label": "Range",
|
|
||||||
"attributes": {
|
|
||||||
type: "range"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "select",
|
"type": "select",
|
||||||
"appKey": "flavor",
|
"appKey": "flavor",
|
||||||
"defaultValue": "grape",
|
"defaultValue": "grape",
|
||||||
"label": "Favorite Flavor",
|
"label": "Select Menu",
|
||||||
"options": [
|
"options": [
|
||||||
{ "label": "", "value": "" },
|
{ "label": "", "value": "" },
|
||||||
{ "label": "Berry", "value": "berry" },
|
{ "label": "Berry", "value": "berry" },
|
||||||
{ "label": "Grape", "value": "grape" },
|
{ "label": "This Option is Selected", "value": "grape" },
|
||||||
{ "label": "Banana", "value": "banana" }
|
{ "label": "Banana", "value": "banana" }
|
||||||
],
|
],
|
||||||
"attributes": {
|
"attributes": {
|
||||||
|
|||||||
+2
-2
@@ -10,9 +10,9 @@ module.exports = function() {
|
|||||||
*/
|
*/
|
||||||
function toggleBackground() {
|
function toggleBackground() {
|
||||||
if (this.get()) {
|
if (this.get()) {
|
||||||
Clay.getItemByAppKey('background').enable();
|
Clay.getItemByAppKey('colorTest').enable();
|
||||||
} else {
|
} else {
|
||||||
Clay.getItemByAppKey('background').disable();
|
Clay.getItemByAppKey('colorTest').disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Vendored
-3
File diff suppressed because one or more lines are too long
@@ -103,6 +103,7 @@ gulp.task('dev-js', ['js', 'sass'], function() {
|
|||||||
.transform(stringify(stringifyOptions))
|
.transform(stringify(stringifyOptions))
|
||||||
.transform('deamdify')
|
.transform('deamdify')
|
||||||
.transform(sassify, sassifyOptions)
|
.transform(sassify, sassifyOptions)
|
||||||
|
.transform(autoprefixify, autoprefixerOptions)
|
||||||
.bundle()
|
.bundle()
|
||||||
.pipe(source('dev.js'))
|
.pipe(source('dev.js'))
|
||||||
.pipe(gulp.dest('./tmp/'));
|
.pipe(gulp.dest('./tmp/'));
|
||||||
|
|||||||
@@ -29,11 +29,17 @@ function Clay(config, customFn, options) {
|
|||||||
self.config = config;
|
self.config = config;
|
||||||
self.customFn = customFn || function() {};
|
self.customFn = customFn || function() {};
|
||||||
self.components = {};
|
self.components = {};
|
||||||
|
self.meta = {
|
||||||
|
activeWatchInfo: null,
|
||||||
|
accountToken: '',
|
||||||
|
watchToken: ''
|
||||||
|
};
|
||||||
|
|
||||||
// Let Clay handle all the magic
|
// Let Clay handle all the magic
|
||||||
if (options.autoHandleEvents !== false && typeof Pebble !== 'undefined') {
|
if (options.autoHandleEvents !== false && typeof Pebble !== 'undefined') {
|
||||||
|
|
||||||
Pebble.addEventListener('showConfiguration', function() {
|
Pebble.addEventListener('showConfiguration', function() {
|
||||||
|
_populateMeta();
|
||||||
Pebble.openURL(self.generateUrl());
|
Pebble.openURL(self.generateUrl());
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -49,6 +55,23 @@ function Clay(config, customFn, options) {
|
|||||||
console.log(JSON.stringify(error));
|
console.log(JSON.stringify(error));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else if (typeof Pebble !== 'undefined') {
|
||||||
|
Pebble.addEventListener('ready', function() {
|
||||||
|
_populateMeta();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the meta with data from the Pebble object. Make sure to run this inside
|
||||||
|
* either the "showConfiguration" or "ready" event handler
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
function _populateMeta() {
|
||||||
|
self.meta = {
|
||||||
|
activeWatchInfo: Pebble.getActiveWatchInfo && Pebble.getActiveWatchInfo(),
|
||||||
|
accountToken: Pebble.getAccountToken(),
|
||||||
|
watchToken: Pebble.getWatchToken()
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +130,8 @@ Clay.prototype.generateUrl = function() {
|
|||||||
.replace('$$CUSTOM_FN$$', toSource(this.customFn))
|
.replace('$$CUSTOM_FN$$', toSource(this.customFn))
|
||||||
.replace('$$CONFIG$$', toSource(this.config))
|
.replace('$$CONFIG$$', toSource(this.config))
|
||||||
.replace('$$SETTINGS$$', toSource(settings))
|
.replace('$$SETTINGS$$', toSource(settings))
|
||||||
.replace('$$COMPONENTS$$', toSource(this.components));
|
.replace('$$COMPONENTS$$', toSource(this.components))
|
||||||
|
.replace('$$META$$', toSource(this.meta));
|
||||||
|
|
||||||
// if we are in the emulator then we need to proxy the data via a webpage to
|
// if we are in the emulator then we need to proxy the data via a webpage to
|
||||||
// obtain the return_to.
|
// obtain the return_to.
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pebble-clay",
|
"name": "pebble-clay",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"description": "Pebble Config Framework",
|
"description": "Pebble Config Framework",
|
||||||
"main": "dist/clay.js",
|
"main": "dist/clay.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
window.claySettings = $$SETTINGS$$;
|
window.claySettings = $$SETTINGS$$;
|
||||||
window.customFn = $$CUSTOM_FN$$;
|
window.customFn = $$CUSTOM_FN$$;
|
||||||
window.clayComponents = $$COMPONENTS$$;
|
window.clayComponents = $$COMPONENTS$$;
|
||||||
|
window.clayMeta = $$META$$;
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 116 KiB |
@@ -8,6 +8,7 @@ module.exports = {
|
|||||||
defaults: {
|
defaults: {
|
||||||
label: '',
|
label: '',
|
||||||
options: [],
|
options: [],
|
||||||
|
description: '',
|
||||||
attributes: {}
|
attributes: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ module.exports = {
|
|||||||
style: require('../../styles/clay/components/color.scss'),
|
style: require('../../styles/clay/components/color.scss'),
|
||||||
manipulator: 'color',
|
manipulator: 'color',
|
||||||
defaults: {
|
defaults: {
|
||||||
label: ''
|
label: '',
|
||||||
|
description: ''
|
||||||
},
|
},
|
||||||
initialize: function(minified) {
|
initialize: function(minified) {
|
||||||
var HTML = minified.HTML;
|
var HTML = minified.HTML;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ module.exports = {
|
|||||||
manipulator: 'val',
|
manipulator: 'val',
|
||||||
defaults: {
|
defaults: {
|
||||||
label: '',
|
label: '',
|
||||||
|
description: '',
|
||||||
attributes: {}
|
attributes: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ module.exports = {
|
|||||||
defaults: {
|
defaults: {
|
||||||
label: '',
|
label: '',
|
||||||
options: [],
|
options: [],
|
||||||
|
description: '',
|
||||||
attributes: {}
|
attributes: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ module.exports = {
|
|||||||
defaults: {
|
defaults: {
|
||||||
label: '',
|
label: '',
|
||||||
options: [],
|
options: [],
|
||||||
|
description: '',
|
||||||
attributes: {}
|
attributes: {}
|
||||||
},
|
},
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
@@ -15,8 +16,10 @@ module.exports = {
|
|||||||
|
|
||||||
var $value = self.$element.select('.value');
|
var $value = self.$element.select('.value');
|
||||||
|
|
||||||
self.on('change', function(ev) {
|
self.on('change', function() {
|
||||||
var value = self.$manipulatorTarget.select('option:checked').get('innerHTML');
|
var selectedIndex = self.$manipulatorTarget.get('selectedIndex');
|
||||||
|
var $options = self.$manipulatorTarget.select('option');
|
||||||
|
var value = $options[selectedIndex] && $options[selectedIndex].innerHTML;
|
||||||
$value.set('innerHTML', value);
|
$value.set('innerHTML', value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
name: 'submit',
|
name: 'submit',
|
||||||
template: require('../../templates/components/submit.tpl'),
|
template: require('../../templates/components/submit.tpl'),
|
||||||
|
style: require('../../styles/clay/components/submit.scss'),
|
||||||
manipulator: 'html',
|
manipulator: 'html',
|
||||||
defaults: {
|
defaults: {
|
||||||
attributes: {}
|
attributes: {}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ module.exports = {
|
|||||||
manipulator: 'checked',
|
manipulator: 'checked',
|
||||||
defaults: {
|
defaults: {
|
||||||
label: '',
|
label: '',
|
||||||
|
description: '',
|
||||||
attributes: {}
|
attributes: {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ var settings = _.extend({}, window.claySettings || {});
|
|||||||
var returnTo = window.returnTo || 'pebblejs://close#';
|
var returnTo = window.returnTo || 'pebblejs://close#';
|
||||||
var customFn = window.customFn || function() {};
|
var customFn = window.customFn || function() {};
|
||||||
var clayComponents = window.clayComponents || {};
|
var clayComponents = window.clayComponents || {};
|
||||||
|
var clayMeta = window.clayMeta || {};
|
||||||
|
|
||||||
var platform = window.navigator.userAgent.match(/android/i) ? 'android' : 'ios';
|
var platform = window.navigator.userAgent.match(/android/i) ? 'android' : 'ios';
|
||||||
document.documentElement.classList.add('platform-' + platform);
|
document.documentElement.classList.add('platform-' + platform);
|
||||||
@@ -21,7 +22,7 @@ _.eachObj(clayComponents, function(key, component) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var $mainForm = $('#main-form');
|
var $mainForm = $('#main-form');
|
||||||
var clayConfig = new ClayConfig(settings, config, $mainForm);
|
var clayConfig = new ClayConfig(settings, config, $mainForm, clayMeta);
|
||||||
|
|
||||||
// add listeners here
|
// add listeners here
|
||||||
$mainForm.on('submit', function() {
|
$mainForm.on('submit', function() {
|
||||||
|
|||||||
@@ -26,9 +26,10 @@ var manipulators = require('./manipulators');
|
|||||||
* @param {Object} settings - setting that were set from a previous session
|
* @param {Object} settings - setting that were set from a previous session
|
||||||
* @param {Array|Object} config
|
* @param {Array|Object} config
|
||||||
* @param {M} $rootContainer
|
* @param {M} $rootContainer
|
||||||
|
* @param {Object} meta
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function ClayConfig(settings, config, $rootContainer) {
|
function ClayConfig(settings, config, $rootContainer, meta) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var _settings = _.copyObj(settings);
|
var _settings = _.copyObj(settings);
|
||||||
@@ -95,6 +96,8 @@ function ClayConfig(settings, config, $rootContainer) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.meta = meta;
|
||||||
|
|
||||||
self.EVENTS = {
|
self.EVENTS = {
|
||||||
/**
|
/**
|
||||||
* Called before framework has initialized. This is when you would attach your
|
* Called before framework has initialized. This is when you would attach your
|
||||||
@@ -183,7 +186,6 @@ function ClayConfig(settings, config, $rootContainer) {
|
|||||||
|
|
||||||
// expose the config to allow developers to update it before the build is run
|
// expose the config to allow developers to update it before the build is run
|
||||||
self.config = config;
|
self.config = config;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,6 +18,22 @@ function enable() {
|
|||||||
return this.trigger('enabled');
|
return this.trigger('enabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {ClayEvents}
|
||||||
|
*/
|
||||||
|
function hide() {
|
||||||
|
this.$element.set('+hide');
|
||||||
|
return this.trigger('hide');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {ClayEvents}
|
||||||
|
*/
|
||||||
|
function show() {
|
||||||
|
this.$element.set('-hide');
|
||||||
|
return this.trigger('show');
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
html: {
|
html: {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -26,7 +42,9 @@ module.exports = {
|
|||||||
set: function(value) {
|
set: function(value) {
|
||||||
this.$manipulatorTarget.set('innerHTML', value);
|
this.$manipulatorTarget.set('innerHTML', value);
|
||||||
return this.trigger('change');
|
return this.trigger('change');
|
||||||
}
|
},
|
||||||
|
hide: hide,
|
||||||
|
show: show
|
||||||
},
|
},
|
||||||
val: {
|
val: {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -37,7 +55,9 @@ module.exports = {
|
|||||||
return this.trigger('change');
|
return this.trigger('change');
|
||||||
},
|
},
|
||||||
disable: disable,
|
disable: disable,
|
||||||
enable: enable
|
enable: enable,
|
||||||
|
hide: hide,
|
||||||
|
show: show
|
||||||
},
|
},
|
||||||
checked: {
|
checked: {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -48,7 +68,9 @@ module.exports = {
|
|||||||
return this.trigger('change');
|
return this.trigger('change');
|
||||||
},
|
},
|
||||||
disable: disable,
|
disable: disable,
|
||||||
enable: enable
|
enable: enable,
|
||||||
|
hide: hide,
|
||||||
|
show: show
|
||||||
},
|
},
|
||||||
radiogroup: {
|
radiogroup: {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -61,7 +83,9 @@ module.exports = {
|
|||||||
return this.trigger('change');
|
return this.trigger('change');
|
||||||
},
|
},
|
||||||
disable: disable,
|
disable: disable,
|
||||||
enable: enable
|
enable: enable,
|
||||||
|
hide: hide,
|
||||||
|
show: show
|
||||||
},
|
},
|
||||||
checkboxgroup: {
|
checkboxgroup: {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -83,7 +107,9 @@ module.exports = {
|
|||||||
return self.trigger('change');
|
return self.trigger('change');
|
||||||
},
|
},
|
||||||
disable: disable,
|
disable: disable,
|
||||||
enable: enable
|
enable: enable,
|
||||||
|
hide: hide,
|
||||||
|
show: show
|
||||||
},
|
},
|
||||||
color: {
|
color: {
|
||||||
get: function() {
|
get: function() {
|
||||||
@@ -99,6 +125,8 @@ module.exports = {
|
|||||||
return this.trigger('change');
|
return this.trigger('change');
|
||||||
},
|
},
|
||||||
disable: disable,
|
disable: disable,
|
||||||
enable: enable
|
enable: enable,
|
||||||
|
hide: hide,
|
||||||
|
show: show
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+65
-70
@@ -17,7 +17,24 @@ html, body {
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: $color-gray-2;
|
background-color: $color-gray-2;
|
||||||
padding: $item-spacing-v $item-spacing-h;
|
padding: 0 $item-spacing-h $item-spacing-v;
|
||||||
|
}
|
||||||
|
|
||||||
|
em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
strong {
|
||||||
|
@include font-pfdin(medium);
|
||||||
|
color: $color-orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: $color-gray-8;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3, h4 {
|
h1, h2, h3, h4 {
|
||||||
@@ -54,6 +71,7 @@ label {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
padding: $item-spacing-v $item-spacing-h;
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
@@ -83,35 +101,43 @@ label {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.component {
|
.hide {
|
||||||
padding-bottom: $item-spacing-v;
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tap-highlight {
|
||||||
@include tap-highlight();
|
@include tap-highlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
.component {
|
||||||
|
padding-top: $item-spacing-v;
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
opacity: 0.25;
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
> * {
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.section {
|
.section {
|
||||||
background: $color-gray-4;
|
background: $color-gray-4;
|
||||||
border-radius: 0.25rem;
|
border-radius: 0.25rem;
|
||||||
margin-bottom: 1rem;
|
|
||||||
box-shadow: $color-gray-1 0 0.15rem 0.25rem;
|
box-shadow: $color-gray-1 0 0.15rem 0.25rem;
|
||||||
|
|
||||||
.component {
|
> .component {
|
||||||
padding-top: $item-spacing-v;
|
padding-bottom: $item-spacing-v;
|
||||||
padding-right: $item-spacing-h;
|
padding-right: $item-spacing-h;
|
||||||
padding-left: $item-spacing-h;
|
padding-left: $item-spacing-h;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
margin-top: 1rem;
|
||||||
|
|
||||||
&:last-child,
|
&:not(.hide) ~ .component {
|
||||||
&:first-child {
|
margin-top: 0;
|
||||||
padding-bottom: $item-spacing-v;
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:first-child:after {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
@@ -119,7 +145,7 @@ label {
|
|||||||
background: $color-gray-6;
|
background: $color-gray-6;
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
top: 0;
|
||||||
left: $item-spacing-h / 2;
|
left: $item-spacing-h / 2;
|
||||||
right: $item-spacing-h / 2;
|
right: $item-spacing-h / 2;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
@@ -127,72 +153,41 @@ label {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.component-heading:first-child {
|
// don't show the separator for the first non-hidden item
|
||||||
|
> .component:not(.hide):after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .component:not(.hide) ~ .component:not(.hide):after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
> .component-heading:first-child {
|
||||||
background: $color-gray-3;
|
background: $color-gray-3;
|
||||||
border-radius: $border-radius $border-radius 0 0;
|
border-radius: $border-radius $border-radius 0 0;
|
||||||
|
|
||||||
|
// don't show the separator for the first non-hidden item after the heading
|
||||||
|
&:after,
|
||||||
|
~ .component:not(.hide):after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
~ .component:not(.hide) ~ .component:not(.hide):after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strong {
|
.description {
|
||||||
@include font-pfdin(medium);
|
padding: 0 $item-spacing-h $item-spacing-v ;
|
||||||
color: $color-orange;
|
@include font-size(0.9);
|
||||||
}
|
color: $color-gray-9;
|
||||||
|
|
||||||
a {
|
|
||||||
color: $color-gray-8;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputs {
|
.inputs {
|
||||||
display: block;
|
display: block;
|
||||||
width:100%;
|
width:100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
|
||||||
.section & .component {
|
|
||||||
display: table;
|
|
||||||
width:100%;
|
|
||||||
|
|
||||||
.label,
|
|
||||||
.input {
|
|
||||||
display: table-cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.invalid {
|
|
||||||
.input:after {
|
|
||||||
content: "!";
|
|
||||||
display: inline-block;
|
|
||||||
color: $color-white;
|
|
||||||
background: $color-orange;
|
|
||||||
border-radius: $border-radius;
|
|
||||||
width: 1.2em;
|
|
||||||
text-align: center;
|
|
||||||
height: 1.2em;
|
|
||||||
font-size: 1em;
|
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1.3em;
|
|
||||||
margin-left: -0.7em;
|
|
||||||
position:absolute;
|
|
||||||
@include font-pfdin(regular);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input input {
|
|
||||||
color: $color-orange;
|
|
||||||
padding-right: 1em;
|
|
||||||
|
|
||||||
@include placeholder {
|
|
||||||
color: $color-orange;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,14 +34,7 @@ $color-gray-9: #a4a4a4 ;
|
|||||||
$color-gray-10: #ececec;
|
$color-gray-10: #ececec;
|
||||||
$color-gray-11: #f2f2f2;
|
$color-gray-11: #f2f2f2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$global-margin: 55px;
|
|
||||||
$form-margin: 25px;
|
|
||||||
$button-padding: 0.7rem;
|
$button-padding: 0.7rem;
|
||||||
$button-padding-ios: 0.6rem;
|
$button-padding-ios: 0.6rem;
|
||||||
$button-line-height: 13px;
|
|
||||||
$footer-height-large: 90px;
|
|
||||||
|
|
||||||
$box-shadow-small-components: $color-gray-1 0 0.1rem 0.1rem;
|
$box-shadow-small-components: $color-gray-1 0 0.1rem 0.1rem;
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
.component-checkbox {
|
.component-checkbox {
|
||||||
|
|
||||||
@include tap-highlight(rgba(0,0,0,0));
|
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
|
.section & {
|
||||||
|
padding-right: $item-spacing-h / 2;
|
||||||
|
}
|
||||||
|
|
||||||
> .label {
|
> .label {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -14,14 +16,14 @@
|
|||||||
|
|
||||||
.checkbox-group {
|
.checkbox-group {
|
||||||
|
|
||||||
|
padding-bottom: $item-spacing-v / 2;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
padding: $item-spacing-v / 2 0;
|
padding: $item-spacing-v / 2 $item-spacing-h / 2;
|
||||||
@include tap-highlight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
padding: 0 $item-spacing-h / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@@ -39,7 +41,7 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked ~ i {
|
input:checked + i {
|
||||||
border-color: $color-orange;
|
border-color: $color-orange;
|
||||||
background: $color-orange;
|
background: $color-orange;
|
||||||
|
|
||||||
@@ -59,6 +61,10 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
.component-color {
|
.component-color {
|
||||||
|
|
||||||
|
.section & {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
width: $small-component-width;
|
width: $small-component-width;
|
||||||
height: $base-height;
|
height: $base-height;
|
||||||
border-radius: $base-height / 2;
|
border-radius: $base-height / 2;
|
||||||
box-shadow: $box-shadow-small-components;
|
box-shadow: $box-shadow-small-components;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.picker-wrap {
|
.picker-wrap {
|
||||||
|
|||||||
@@ -2,7 +2,13 @@
|
|||||||
|
|
||||||
.component-input {
|
.component-input {
|
||||||
|
|
||||||
|
.section & {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
display: block;
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
padding-bottom: $item-spacing-v;
|
padding-bottom: $item-spacing-v;
|
||||||
|
|||||||
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
.component-radio {
|
.component-radio {
|
||||||
|
|
||||||
@include tap-highlight(rgba(0,0,0,0));
|
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
|
.section & {
|
||||||
|
padding-right: $item-spacing-h / 2;
|
||||||
|
}
|
||||||
|
|
||||||
> .label {
|
> .label {
|
||||||
display: block;
|
display: block;
|
||||||
@@ -14,14 +16,14 @@
|
|||||||
|
|
||||||
.radio-group {
|
.radio-group {
|
||||||
|
|
||||||
|
padding-bottom: $item-spacing-v / 2;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
padding: $item-spacing-v / 2 0;
|
padding: $item-spacing-v / 2 $item-spacing-h / 2;
|
||||||
@include tap-highlight();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
padding: 0 $item-spacing-h / 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@@ -39,7 +41,7 @@
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input:checked ~ i {
|
input:checked + i {
|
||||||
border-color: $color-orange;
|
border-color: $color-orange;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
@@ -58,4 +60,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
padding-left: 0;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,20 @@
|
|||||||
@import "clay";
|
@import "clay";
|
||||||
|
|
||||||
.component-select {
|
.component-select {
|
||||||
|
|
||||||
|
.section & {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
$triangle-size: 0.85rem;
|
$triangle-size: 0.85rem;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-right: $triangle-size + 0.25rem;
|
padding-right: $triangle-size + 0.25rem;
|
||||||
|
display: block;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
@@ -15,7 +23,7 @@
|
|||||||
right: 0;
|
right: 0;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
margin-top: -0.1rem;
|
margin-top: -0.1rem;
|
||||||
@include triangle($triangle-size, $color-gray-10, down);
|
@include triangle($triangle-size, $color-orange, down);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.component-submit {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@@ -6,6 +6,10 @@
|
|||||||
$slide-width: $small-component-width;
|
$slide-width: $small-component-width;
|
||||||
$marker-diameter: $base-height;
|
$marker-diameter: $base-height;
|
||||||
|
|
||||||
|
.section & {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
display: none; // @todo make sure this doesn't mess up interactivity on iOS
|
display: none; // @todo make sure this doesn't mess up interactivity on iOS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ button,
|
|||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
border: none;
|
border: none;
|
||||||
display: block;
|
display: inline-block;
|
||||||
|
|
||||||
color: $color-white;
|
color: $color-white;
|
||||||
min-width: 12rem;
|
min-width: 12rem;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<span class="label">{{{label}}}</span>
|
<span class="label">{{{label}}}</span>
|
||||||
<div class="checkbox-group">
|
<div class="checkbox-group">
|
||||||
{{each options}}
|
{{each options}}
|
||||||
<label>
|
<label class="tap-highlight">
|
||||||
<span class="label">{{{this.label}}}</span>
|
<span class="label">{{{this.label}}}</span>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@@ -15,4 +15,7 @@
|
|||||||
</label>
|
</label>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
{{if description}}
|
||||||
|
<div class="description">{{{description}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<div class="component component-color">
|
<div class="component component-color">
|
||||||
<label>
|
<label class="tap-highlight">
|
||||||
<input
|
<input
|
||||||
data-manipulator-target
|
data-manipulator-target
|
||||||
type="hidden"
|
type="hidden"
|
||||||
@@ -7,6 +7,9 @@
|
|||||||
<span class="label">{{{label}}}</span>
|
<span class="label">{{{label}}}</span>
|
||||||
<span class="value"></span>
|
<span class="value"></span>
|
||||||
</label>
|
</label>
|
||||||
|
{{if description}}
|
||||||
|
<div class="description">{{{description}}}</div>
|
||||||
|
{{/if}}
|
||||||
<div class="picker-wrap">
|
<div class="picker-wrap">
|
||||||
<div class="picker">
|
<div class="picker">
|
||||||
<div class="color-box-wrap">
|
<div class="color-box-wrap">
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<label class="component component-input">
|
<div class="component component-input">
|
||||||
|
<label class="tap-highlight">
|
||||||
<span class="label">{{{label}}}</span>
|
<span class="label">{{{label}}}</span>
|
||||||
<span class="input">
|
<span class="input">
|
||||||
<input
|
<input
|
||||||
@@ -6,4 +7,9 @@
|
|||||||
{{each key: attributes}}{{key}}="{{this}}"{{/each}}
|
{{each key: attributes}}{{key}}="{{this}}"{{/each}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
{{if description}}
|
||||||
|
<div class="description">{{{description}}}</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<span class="label">{{{label}}}</span>
|
<span class="label">{{{label}}}</span>
|
||||||
<div class="radio-group">
|
<div class="radio-group">
|
||||||
{{each options}}
|
{{each options}}
|
||||||
<label>
|
<label class="tap-highlight">
|
||||||
<span class="label">{{{this.label}}}</span>
|
<span class="label">{{{this.label}}}</span>
|
||||||
<input
|
<input
|
||||||
type="radio"
|
type="radio"
|
||||||
@@ -15,4 +15,7 @@
|
|||||||
</label>
|
</label>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
{{if description}}
|
||||||
|
<div class="description">{{{description}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<label class="component component-select">
|
<div class="component component-select">
|
||||||
|
<label class="tap-highlight">
|
||||||
<span class="label">{{{label}}}</span>
|
<span class="label">{{{label}}}</span>
|
||||||
<span class="value"></span>
|
<span class="value"></span>
|
||||||
<select data-manipulator-target {{each key: attributes}}{{key}}="{{this}}"{{/each}}>
|
<select data-manipulator-target {{each key: attributes}}{{key}}="{{this}}"{{/each}}>
|
||||||
@@ -6,4 +7,8 @@
|
|||||||
<option value="{{this.value}}" class="item-select-option">{{this.label}}</option>
|
<option value="{{this.value}}" class="item-select-option">{{this.label}}</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
{{if description}}
|
||||||
|
<div class="description">{{{description}}}</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="component component-button">
|
<div class="component component-submit">
|
||||||
<button
|
<button
|
||||||
data-manipulator-target
|
data-manipulator-target
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<label class="component component-toggle">
|
<div class="component component-toggle">
|
||||||
|
<label class="tap-highlight">
|
||||||
<span class="label">{{{label}}}</span>
|
<span class="label">{{{label}}}</span>
|
||||||
<span class="input">
|
<span class="input">
|
||||||
<input
|
<input
|
||||||
@@ -11,4 +12,8 @@
|
|||||||
<span class="marker"></span>
|
<span class="marker"></span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
|
{{if description}}
|
||||||
|
<div class="description">{{{description}}}</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|||||||
+25
-1
@@ -10,6 +10,29 @@ var components = require('../src/scripts/components');
|
|||||||
var componentRegistry = require('../src/scripts/lib/component-registry');
|
var componentRegistry = require('../src/scripts/lib/component-registry');
|
||||||
var idCounter = 0;
|
var idCounter = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {{accountToken: string, watchToken: string, activeWatchInfo: {platform:
|
||||||
|
* string, model: string, language: string, firmware: {major: number, minor:
|
||||||
|
* number, patch: number, suffix: string}}}}
|
||||||
|
*/
|
||||||
|
module.exports.meta = function() {
|
||||||
|
return {
|
||||||
|
accountToken: '0123456789abcdef0123456789abcdef',
|
||||||
|
watchToken: '0123456789abcdef0123456789abcdef',
|
||||||
|
activeWatchInfo: {
|
||||||
|
platform: 'chalk',
|
||||||
|
model: 'qemu_platform_chalk',
|
||||||
|
language: 'en_US',
|
||||||
|
firmware: {
|
||||||
|
major: 3,
|
||||||
|
minor: 3,
|
||||||
|
patch: 2,
|
||||||
|
suffix: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string|Object} config
|
* @param {string|Object} config
|
||||||
* @param {boolean} [autoRegister=true]
|
* @param {boolean} [autoRegister=true]
|
||||||
@@ -70,7 +93,8 @@ module.exports.clayConfig = function(types, build, autoRegister, settings) {
|
|||||||
var clayConfig = new ClayConfig(
|
var clayConfig = new ClayConfig(
|
||||||
settings || {},
|
settings || {},
|
||||||
module.exports.config(types, autoRegister),
|
module.exports.config(types, autoRegister),
|
||||||
$(HTML('<div>'))
|
$(HTML('<div>')),
|
||||||
|
module.exports.meta()
|
||||||
);
|
);
|
||||||
return build === false ? clayConfig : clayConfig.build();
|
return build === false ? clayConfig : clayConfig.build();
|
||||||
};
|
};
|
||||||
|
|||||||
+137
-5
@@ -5,6 +5,21 @@ var Clay = require('../../index');
|
|||||||
var assert = require('chai').assert;
|
var assert = require('chai').assert;
|
||||||
var standardComponents = require('../../src/scripts/components');
|
var standardComponents = require('../../src/scripts/components');
|
||||||
var sinon = require('sinon');
|
var sinon = require('sinon');
|
||||||
|
var toSource = require('tosource');
|
||||||
|
|
||||||
|
var accountToken = '0123456789abcdef0123456789abcdef';
|
||||||
|
var watchToken = '0123456789abcdef0123456789abcdef';
|
||||||
|
var activeWatchInfo = {
|
||||||
|
platform: 'chalk',
|
||||||
|
model: 'qemu_platform_chalk',
|
||||||
|
language: 'en_US',
|
||||||
|
firmware: {
|
||||||
|
major: 3,
|
||||||
|
minor: 3,
|
||||||
|
patch: 2,
|
||||||
|
suffix: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {void}
|
* @return {void}
|
||||||
@@ -13,7 +28,10 @@ function stubPebble() {
|
|||||||
global.Pebble = {
|
global.Pebble = {
|
||||||
addEventListener: sinon.stub(),
|
addEventListener: sinon.stub(),
|
||||||
openURL: sinon.stub(),
|
openURL: sinon.stub(),
|
||||||
sendAppMessage: sinon.stub()
|
sendAppMessage: sinon.stub(),
|
||||||
|
getActiveWatchInfo: sinon.stub().returns(activeWatchInfo),
|
||||||
|
getAccountToken: sinon.stub().returns(accountToken),
|
||||||
|
getWatchToken: sinon.stub().returns(watchToken)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,12 +74,19 @@ describe('Clay', function() {
|
|||||||
|
|
||||||
it('handles the "showConfiguration" event if autoHandleEvents is not false',
|
it('handles the "showConfiguration" event if autoHandleEvents is not false',
|
||||||
function() {
|
function() {
|
||||||
|
this.timeout(10000); // 10 seconds
|
||||||
|
|
||||||
stubPebble();
|
stubPebble();
|
||||||
var clay = fixture.clay([]);
|
var clay = fixture.clay([]);
|
||||||
|
|
||||||
|
// we stub the generateUrl method to avoid very large string comparisons.
|
||||||
|
var generateUrlStub = sinon.stub(clay, 'generateUrl');
|
||||||
|
generateUrlStub.returns('data:text/html;base64,PGh0bWw%2BVEVTVDwvaHRtbD4%3D');
|
||||||
Pebble.addEventListener.withArgs('showConfiguration').callArg(1);
|
Pebble.addEventListener.withArgs('showConfiguration').callArg(1);
|
||||||
|
|
||||||
assert(Pebble.addEventListener.calledWith('showConfiguration'));
|
assert(Pebble.addEventListener.calledWith('showConfiguration'));
|
||||||
assert(Pebble.openURL.calledWith(clay.generateUrl()));
|
assert(Pebble.openURL.calledWith(clay.generateUrl()));
|
||||||
|
generateUrlStub.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles the "webviewclosed" event if autoHandleEvents is not false',
|
it('handles the "webviewclosed" event if autoHandleEvents is not false',
|
||||||
@@ -99,7 +124,14 @@ describe('Clay', function() {
|
|||||||
'if autoHandleEvents is false', function() {
|
'if autoHandleEvents is false', function() {
|
||||||
stubPebble();
|
stubPebble();
|
||||||
fixture.clay([], null, { autoHandleEvents: false });
|
fixture.clay([], null, { autoHandleEvents: false });
|
||||||
assert.strictEqual(Pebble.addEventListener.called, false);
|
assert.strictEqual(
|
||||||
|
Pebble.addEventListener.withArgs('webviewclosed').called,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert.strictEqual(
|
||||||
|
Pebble.addEventListener.withArgs('showConfiguration').called,
|
||||||
|
false
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -117,13 +149,67 @@ describe('Clay', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('.generateUrl()', function() {
|
describe('.generateUrl()', function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode the generated data URI into just the HTML portion
|
||||||
|
* @param {string} url
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function decodeUrl(url) {
|
||||||
|
return atob(decodeURIComponent(url.replace(/^.*?[#,]/, '')));
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('string substitutions', function() {
|
||||||
|
var customFn = function() { this.getAllItems(); };
|
||||||
|
var config = fixture.config(['input', 'color']);
|
||||||
|
var settings = { appKey: 'value' };
|
||||||
|
var clay;
|
||||||
|
var html;
|
||||||
|
|
||||||
|
before(function() {
|
||||||
|
stubPebble();
|
||||||
|
clay = fixture.clay(config, customFn);
|
||||||
|
Pebble.addEventListener.withArgs('showConfiguration').callArg(1);
|
||||||
|
localStorage.setItem('clay-settings', JSON.stringify(settings));
|
||||||
|
html = decodeUrl(clay.generateUrl());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Substitutes $$RETURN_TO$$ with the pebblejs://close#', function() {
|
||||||
|
assert.notInclude(html, '$$RETURN_TO$$');
|
||||||
|
assert.include(html, 'window.returnTo="pebblejs://close#"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Substitutes $$CUSTOM_FN$$ with the customFn', function() {
|
||||||
|
assert.notInclude(html, '$$CUSTOM_FN$$');
|
||||||
|
assert.include(html, 'window.customFn=' + toSource(customFn));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Substitutes $$CONFIG$$ with the config', function() {
|
||||||
|
assert.notInclude(html, '$$CONFIG$$');
|
||||||
|
assert.include(html, 'window.clayConfig=' + toSource(config));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Substitutes $$SETTINGS$$ with the config', function() {
|
||||||
|
assert.notInclude(html, '$$SETTINGS$$');
|
||||||
|
assert.include(html, 'window.claySettings=' + toSource(settings));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Substitutes $$COMPONENTS$$ with the config', function() {
|
||||||
|
assert.notInclude(html, '$$COMPONENTS$$');
|
||||||
|
assert.include(html, 'window.clayComponents=' + toSource(clay.components));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Substitutes $$META$$ with the config', function() {
|
||||||
|
assert.notInclude(html, '$$META$$');
|
||||||
|
assert.include(html, 'window.clayMeta=' + toSource(clay.meta));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('does not replace $$RETURN_TO$$ if in the emulator', function() {
|
it('does not replace $$RETURN_TO$$ if in the emulator', function() {
|
||||||
var clay = fixture.clay([]);
|
var clay = fixture.clay([]);
|
||||||
stubPebble();
|
stubPebble();
|
||||||
Pebble.platform = 'pypkjs';
|
Pebble.platform = 'pypkjs';
|
||||||
var decodedUrl =
|
assert.match(decodeUrl(clay.generateUrl()), /\$\$RETURN_TO\$\$/);
|
||||||
atob(decodeURIComponent(clay.generateUrl().replace(/^.*?#/, '')));
|
|
||||||
assert.match(decodedUrl, /\$\$RETURN_TO\$\$/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns the emulator URL if inside emulator', function() {
|
it('returns the emulator URL if inside emulator', function() {
|
||||||
@@ -170,6 +256,52 @@ describe('Clay', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('.meta', function() {
|
||||||
|
var emptyMeta = {
|
||||||
|
activeWatchInfo: null,
|
||||||
|
accountToken: '',
|
||||||
|
watchToken: ''
|
||||||
|
};
|
||||||
|
|
||||||
|
it('populates the meta in the showConfiguration handler', function() {
|
||||||
|
stubPebble();
|
||||||
|
var clay = fixture.clay([]);
|
||||||
|
|
||||||
|
// meta only gets populated after showConfiguration happens
|
||||||
|
assert.deepEqual(clay.meta, emptyMeta);
|
||||||
|
Pebble.addEventListener.withArgs('showConfiguration').callArg(1);
|
||||||
|
|
||||||
|
assert.deepEqual(clay.meta, {
|
||||||
|
activeWatchInfo: activeWatchInfo,
|
||||||
|
accountToken: accountToken,
|
||||||
|
watchToken: watchToken
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('populates the meta in the ready handler', function() {
|
||||||
|
stubPebble();
|
||||||
|
var clay = fixture.clay([], null, {autoHandleEvents: false});
|
||||||
|
|
||||||
|
// meta only gets populated after ready happens
|
||||||
|
assert.deepEqual(clay.meta, emptyMeta);
|
||||||
|
Pebble.addEventListener.withArgs('ready').callArg(1);
|
||||||
|
|
||||||
|
assert.deepEqual(clay.meta, {
|
||||||
|
activeWatchInfo: activeWatchInfo,
|
||||||
|
accountToken: accountToken,
|
||||||
|
watchToken: watchToken
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('populates the meta with with empty values when there is no Pebble global',
|
||||||
|
function() {
|
||||||
|
delete global.Pebble;
|
||||||
|
var clay = fixture.clay([], null, {autoHandleEvents: false});
|
||||||
|
|
||||||
|
assert.deepEqual(clay.meta, emptyMeta);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('Clay.encodeDataUri()', function() {
|
describe('Clay.encodeDataUri()', function() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,12 +20,20 @@ describe('ClayConfig', function() {
|
|||||||
'build',
|
'build',
|
||||||
'on',
|
'on',
|
||||||
'off',
|
'off',
|
||||||
'trigger'
|
'trigger',
|
||||||
|
'meta'
|
||||||
];
|
];
|
||||||
var clayConfig = fixtures.clayConfig(['input']);
|
var clayConfig = fixtures.clayConfig(['input']);
|
||||||
checkReadOnly(clayConfig, properties);
|
checkReadOnly(clayConfig, properties);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('.meta', function() {
|
||||||
|
it('populates meta', function() {
|
||||||
|
var clayConfig = fixtures.clayConfig(['input']);
|
||||||
|
assert.deepEqual(clayConfig.meta, fixtures.meta());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('throws when trying to run methods before being built', function() {
|
describe('throws when trying to run methods before being built', function() {
|
||||||
[
|
[
|
||||||
'getItemByAppKey',
|
'getItemByAppKey',
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ describe('ClayItem', function() {
|
|||||||
describe('.$element', function() {
|
describe('.$element', function() {
|
||||||
it('sets $element correctly', function() {
|
it('sets $element correctly', function() {
|
||||||
var clayItem = fixture.clayItem('input');
|
var clayItem = fixture.clayItem('input');
|
||||||
assert.strictEqual(clayItem.$element[0].tagName, 'LABEL');
|
assert.strictEqual(clayItem.$element[0].classList.contains('component'), true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ var fixture = require('../../fixture');
|
|||||||
describe('manipulators', function() {
|
describe('manipulators', function() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string|Clay~ConfigItem} itemType
|
* @param {string|Object} itemType
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
* @param {*} [expected]
|
* @param {*} [expected]
|
||||||
* @return {void}
|
* @return {void}
|
||||||
@@ -31,7 +31,7 @@ describe('manipulators', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string|Clay~ConfigItem} itemType
|
* @param {string|Object} itemType
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
function testDisable(itemType) {
|
function testDisable(itemType) {
|
||||||
@@ -57,7 +57,7 @@ describe('manipulators', function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} itemType
|
* @param {string|Object} itemType
|
||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
function testEnable(itemType) {
|
function testEnable(itemType) {
|
||||||
@@ -84,14 +84,71 @@ describe('manipulators', function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string|Object} itemType
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
function testHide(itemType) {
|
||||||
|
describe('.hide()', function() {
|
||||||
|
it('hides the field then triggers a "hide" event', function() {
|
||||||
|
var handlerSpy = sinon.spy();
|
||||||
|
var clayItem = fixture.clayItem(itemType);
|
||||||
|
clayItem.on('hide', handlerSpy);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
clayItem.$element[0].classList.contains('hide'),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
clayItem.hide();
|
||||||
|
assert.strictEqual(
|
||||||
|
clayItem.$element[0].classList.contains('hide'),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
assert.strictEqual(handlerSpy.callCount, 1, 'handler not called once');
|
||||||
|
assert(handlerSpy.calledOn(clayItem), 'handler not called on clayItem');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string|Object} itemType
|
||||||
|
* @return {void}
|
||||||
|
*/
|
||||||
|
function testShow(itemType) {
|
||||||
|
describe('.show()', function() {
|
||||||
|
it('shows the field then triggers a "show" event', function() {
|
||||||
|
var handlerSpy = sinon.spy();
|
||||||
|
var clayItem = fixture.clayItem(itemType);
|
||||||
|
clayItem.on('show', handlerSpy);
|
||||||
|
|
||||||
|
clayItem.hide();
|
||||||
|
assert.strictEqual(
|
||||||
|
clayItem.$element[0].classList.contains('hide'),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
clayItem.show();
|
||||||
|
assert.strictEqual(
|
||||||
|
clayItem.$element[0].classList.contains('hide'),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
assert.strictEqual(handlerSpy.callCount, 1, 'handler not called once');
|
||||||
|
assert(handlerSpy.calledOn(clayItem), 'handler not called on clayItem');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
describe('html', function() {
|
describe('html', function() {
|
||||||
testSetGet('footer', 'test123');
|
testSetGet('text', 'test123');
|
||||||
|
testShow('text');
|
||||||
|
testHide('text');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('val', function() {
|
describe('val', function() {
|
||||||
testSetGet('input', 'test321');
|
testSetGet('input', 'test321');
|
||||||
testDisable('input');
|
testDisable('input');
|
||||||
testEnable('input');
|
testEnable('input');
|
||||||
|
testShow('text');
|
||||||
|
testHide('text');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('checked', function() {
|
describe('checked', function() {
|
||||||
@@ -101,6 +158,8 @@ describe('manipulators', function() {
|
|||||||
testSetGet('toggle', 0);
|
testSetGet('toggle', 0);
|
||||||
testDisable('toggle');
|
testDisable('toggle');
|
||||||
testEnable('toggle');
|
testEnable('toggle');
|
||||||
|
testShow('toggle');
|
||||||
|
testHide('toggle');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('radiogroup', function() {
|
describe('radiogroup', function() {
|
||||||
@@ -118,6 +177,8 @@ describe('manipulators', function() {
|
|||||||
testSetGet(item, 'three "quote');
|
testSetGet(item, 'three "quote');
|
||||||
testDisable(item);
|
testDisable(item);
|
||||||
testEnable(item);
|
testEnable(item);
|
||||||
|
testShow(item);
|
||||||
|
testHide(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('checkboxgroup', function() {
|
describe('checkboxgroup', function() {
|
||||||
@@ -136,6 +197,8 @@ describe('manipulators', function() {
|
|||||||
testSetGet(item, false, []);
|
testSetGet(item, false, []);
|
||||||
testDisable(item);
|
testDisable(item);
|
||||||
testEnable(item);
|
testEnable(item);
|
||||||
|
testShow(item);
|
||||||
|
testHide(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('color', function() {
|
describe('color', function() {
|
||||||
@@ -149,5 +212,7 @@ describe('manipulators', function() {
|
|||||||
testSetGet('color', undefined, 0x000000);
|
testSetGet('color', undefined, 0x000000);
|
||||||
testDisable('color');
|
testDisable('color');
|
||||||
testEnable('color');
|
testEnable('color');
|
||||||
|
testShow('color');
|
||||||
|
testHide('color');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user