Browse code

init v1

Louis Jonget authored on13/05/2024 20:43:46
Showing78 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+wscript
2
+
3
+# Ignore swap files
4
+*.swp
5
+
6
+# Ignore lock file
7
+.lock-waf_linux2_build
8
+
9
+# Ignore build generated files but pbw (compiled app)
10
+/build/*
11
+!/build/*.pbw
0 12
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+{
2
+    "configurations": [
3
+        {
4
+            "name": "Win32",
5
+            "includePath": [
6
+                "${workspaceFolder}/**"
7
+            ],
8
+            "defines": [
9
+                "_DEBUG",
10
+                "UNICODE",
11
+                "_UNICODE"
12
+            ]
13
+        }
14
+    ],
15
+    "version": 4
16
+}
0 17
\ No newline at end of file
1 18
new file mode 100644
2 19
Binary files /dev/null and b/build/agenda_sommeil.pbw differ
3 20
new file mode 100644
... ...
@@ -0,0 +1,21 @@
1
+The MIT License (MIT)
2
+
3
+Copyright (c) 2016 Pebble Technology
4
+
5
+Permission is hereby granted, free of charge, to any person obtaining a copy
6
+of this software and associated documentation files (the "Software"), to deal
7
+in the Software without restriction, including without limitation the rights
8
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+copies of the Software, and to permit persons to whom the Software is
10
+furnished to do so, subject to the following conditions:
11
+
12
+The above copyright notice and this permission notice shall be included in all
13
+copies or substantial portions of the Software.
14
+
15
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+SOFTWARE.
0 22
new file mode 100644
... ...
@@ -0,0 +1,1267 @@
1
+# Clay
2
+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. 
3
+
4
+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 `messageKey` as defined in `package.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).
5
+
6
+Clay is distributed as a [Pebble package](https://developer.pebble.com/guides/pebble-packages/) so it is super easy to include in your project. If you are upgrading from v0.1.x of Clay you need to follow the [migration guide](#migrating-from-v01x-to-v1x) before you can get started.
7
+
8
+If you would like to contribute to Clay, check out the [contributing guide.](CONTRIBUTING.md)
9
+
10
+# Getting Started (SDK 3.13 or higher)
11
+
12
+1. Run `pebble package install pebble-clay` to install the package in your project
13
+2. Create a JSON file called `config.json` and place it in your `src/js` directory.
14
+3. 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']))`.
15
+4. Your `index.js` (`app.js` in SDK 3) file needs to `require` clay and your config file, then be initialized. Clay will by default automatically handle the 'showConfiguration' and 'webviewclosed' events. Copy and paste the following into the top of your `index.js` file:
16
+
17
+  ```javascript
18
+  var Clay = require('pebble-clay');
19
+  var clayConfig = require('./config.json');
20
+  var clay = new Clay(clayConfig);
21
+  ```
22
+5. Ensure `pebble.enableMultiJS` is set to true in your `package.json`.
23
+6. Next is the fun part - creating your config page. Edit your `config.json` file to build a layout of elements as described in the sections below.
24
+7. Make sure you have defined all of your `messageKeys` in your `package.json`. More info on how that works [here.](https://developer.pebble.com/guides/communication/using-pebblekit-js/#defining-keys)
25
+
26
+# Getting Started (CloudPebble)
27
+
28
+1. Ensure `JS Handling` is set to `CommonJS-style` in your project settings.
29
+2. Under `Dependencies` in the project navigation, enter `pebble-clay` as the `Package Name` and `^1.0.0` for the `Version`. You may use any specific version you like, however using `^1.0.0` will ensure you receive all minor version updates.
30
+4. Create a 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:
31
+
32
+  ```javascript
33
+  module.exports = [];
34
+  ```
35
+5. Your `index.js` file needs to `require` clay and your config file, then be initialized. Clay will by default automatically handle the 'showConfiguration' and 'webviewclosed' events. Copy and paste the following into the top of your `app.js` file:
36
+
37
+  ```javascript
38
+  var Clay = require('pebble-clay');
39
+  var clayConfig = require('./config');
40
+  var clay = new Clay(clayConfig);
41
+  ```
42
+6. Next is the fun part - creating your config page. Edit your `config.js` file to build a layout of elements as described in the sections below.
43
+7. Make sure you have defined all of your message keys using `Automatic assignment` in your project settings. More info on how that works [here.](https://developer.pebble.com/guides/communication/using-pebblekit-js/#defining-keys)
44
+
45
+# Getting Started (Pebble.js)
46
+If you are using [Pebble.js](https://developer.pebble.com/docs/pebblejs/) and would like to use Clay, The setup process is a little different. Pebble.js does not currently support message keys so you will have to use [v0.1.7](https://github.com/pebble/clay/releases/v0.1.7) of Clay. Follow the instructions in the [readme for that version.](https://github.com/pebble/clay/blob/v0.1.7/README.md) 
47
+
48
+# Getting Started (Rocky.js)
49
+If you are using [Rocky.js](https://developer.pebble.com/docs/rockyjs/) and would like to use Clay, please be aware that this is currently unsupported. It is possible to install the Clay package and override the 'showConfiguration' and 'webviewclosed' events and handle them manually, but Rocky.js does not currently support persistent storage, so the settings must be loaded from the phone each time. You can find an example of using Clay with Rocky.js [here](https://github.com/orviwan/rocky-leco-clay).
50
+
51
+# Creating Your Config File
52
+
53
+Clay uses JavaScript object notation (or JSON) to generate the config page for you. The structure of the page is up to you, but you do need to follow some basic rules. 
54
+
55
+## Basic Config Structure 
56
+
57
+Your root element **must** be an array. This represents the entire page. Inside this array you place your config items. Each config item is an object with some properties that configure how each item should be displayed. 
58
+
59
+#### Example
60
+
61
+NOTE for config.js (rather than config.json) a leading `module.exports =` is required.
62
+
63
+```javascript
64
+[
65
+  { 
66
+    "type": "heading", 
67
+    "defaultValue": "Example Header Item" 
68
+  }, 
69
+  { 
70
+    "type": "text", 
71
+    "defaultValue": "Example text item." 
72
+  }
73
+]
74
+```
75
+
76
+## Components
77
+
78
+<img src="src/images/example.png" width="360" title="Example">
79
+
80
+### Section
81
+
82
+Sections help divide up the page into logical groups of items. It is recommended that you place all your input-based items in at least one section. 
83
+
84
+##### Properties
85
+
86
+| Property | Type | Description |
87
+|----------|------|-------------|
88
+| type | string | Set to `section`. |
89
+| items | array | Array of items to include in this section. |
90
+| capabilities | array | Array of features that the connected watch must have for this section to be present |
91
+
92
+##### Example
93
+
94
+```javascript
95
+{
96
+  "type": "section",
97
+  "items": [
98
+    {
99
+      "type": "heading",
100
+      "defaultValue": "This is a section"
101
+    },
102
+    {
103
+      "type": "input",
104
+      "messageKey": "email",
105
+      "label": "Email Address"
106
+    },
107
+    {
108
+      "type": "toggle",
109
+      "messageKey": "enableAnimations",
110
+      "label": "Enable Animations"
111
+    }
112
+  ]
113
+}
114
+```
115
+
116
+---
117
+
118
+### Heading
119
+
120
+**Manipulator:** [`html`](#html)
121
+
122
+Headings can be used in anywhere and can have their size adjusted to suit the context. If you place a heading item at the first position of a section's `items` array then it will automatically be styled as the header for that section. 
123
+
124
+##### Properties
125
+
126
+| Property | Type | Description |
127
+|----------|------|-------------|
128
+| type | string | Set to `heading`. |
129
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
130
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
131
+| defaultValue | string/HTML | The heading's text. |
132
+| size | int | Defaults to `4`. An integer from 1 to 6 where 1 is the largest size and 6 is the smallest. (represents HTML `<h1>`, `<h2>`, `<h3>`, etc). |
133
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
134
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
135
+
136
+
137
+##### Example
138
+
139
+```javascript
140
+{
141
+  "type": "heading",
142
+  "id": "main-heading",
143
+  "defaultValue": "My Cool Watchface",
144
+  "size": 1
145
+}
146
+```
147
+
148
+---
149
+
150
+### Text
151
+
152
+**Manipulator:** [`html`](#html)
153
+
154
+Text is used to provide descriptions of sections or to explain complex parts of your page. Feel free to add any extra HTML you require to the `defaultValue` 
155
+
156
+##### Properties
157
+
158
+| Property | Type | Description |
159
+|----------|------|-------------|
160
+| type | string | Set to `text`. |
161
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
162
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
163
+| defaultValue | string/HTML | The content of the text element. |
164
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
165
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
166
+
167
+
168
+##### Example
169
+
170
+```javascript
171
+{
172
+  "type": "text",
173
+  "defaultValue": "This will be displayed in the text element!",
174
+}
175
+```
176
+
177
+---
178
+
179
+### Input
180
+
181
+**Manipulator:** [`val`](#val)
182
+
183
+Standard text input field. 
184
+
185
+##### Properties
186
+
187
+| Property | Type | Description |
188
+|----------|------|-------------|
189
+| type | string | Set to `input`. |
190
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
191
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
192
+| label | string | The label that should appear next to this item. |
193
+| defaultValue | string | The default value of the input field. |
194
+| description | string | Optional sub-text to include below the component |
195
+| attributes | object | An object containing HTML attributes to set on the input field. Set `type` to values such as "email", "time", "date" etc to adjust the behavior of the component. |
196
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
197
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
198
+
199
+
200
+##### Example
201
+
202
+```javascript
203
+{
204
+  "type": "input",
205
+  "messageKey": "email",
206
+  "defaultValue": "",
207
+  "label": "Email Address",
208
+  "attributes": {
209
+    "placeholder": "eg: name@domain.com",
210
+    "limit": 10,
211
+    "type": "email"
212
+  }
213
+}
214
+```
215
+
216
+---
217
+
218
+#### Toggle
219
+
220
+**Manipulator:** [`checked`](#checked)
221
+
222
+Switch for a single item. 
223
+
224
+##### Properties
225
+
226
+| Property | Type | Description |
227
+|----------|------|-------------|
228
+| type | string | Set to `toggle`. |
229
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
230
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
231
+| label | string | The label that should appear next to this item. |
232
+| defaultValue | int\|boolean | The default value of the toggle. Defaults to `false` if not specified. |
233
+| description | string | Optional sub-text to include below the component |
234
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
235
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
236
+
237
+
238
+##### Example
239
+
240
+```javascript
241
+{
242
+  "type": "toggle",
243
+  "messageKey": "invert",
244
+  "label": "Invert Colors",
245
+  "defaultValue": true
246
+}
247
+```
248
+
249
+---
250
+
251
+#### Select
252
+
253
+**Manipulator:** [`val`](#val)
254
+
255
+A dropdown menu containing multiple options.
256
+
257
+##### Properties
258
+
259
+| Property | Type | Description |
260
+|----------|------|-------------|
261
+| type | string | Set to `select`. |
262
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
263
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
264
+| label | string | The label that should appear next to this item. |
265
+| defaultValue | string | The default value of the dropdown menu. Must match a value in the `options` array. |
266
+| description | string | Optional sub-text to include below the component |
267
+| 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. |
268
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
269
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
270
+
271
+##### Example
272
+
273
+```javascript
274
+{
275
+  "type": "select",
276
+  "messageKey": "flavor",
277
+  "defaultValue": "grape",
278
+  "label": "Favorite Flavor",
279
+  "options": [
280
+    { 
281
+      "label": "", 
282
+      "value": "" 
283
+    },
284
+    { 
285
+      "label": "Berry",
286
+      "value": "berry" 
287
+    },
288
+    { 
289
+      "label": "Grape",
290
+      "value": "grape" 
291
+    },
292
+    { 
293
+      "label": "Banana",
294
+      "value": "banana" 
295
+    }
296
+  ]
297
+}
298
+```
299
+
300
+If you wish to use optgroups, then use the following format:
301
+
302
+```javascript
303
+{
304
+  "type": "select",
305
+  "messageKey": "flavor",
306
+  "defaultValue": "grape",
307
+  "label": "Favorite Flavor",
308
+  "options": [
309
+    { 
310
+      "label": "", 
311
+      "value": "" 
312
+    },
313
+    {
314
+      "label": "Fruits",
315
+      "value": [
316
+        { 
317
+          "label": "Berry",
318
+          "value": "berry" 
319
+        },
320
+        { 
321
+          "label": "Grape",
322
+          "value": "grape" 
323
+        },
324
+        { 
325
+          "label": "Banana",
326
+          "value": "banana" 
327
+        }
328
+      ]
329
+    }, 
330
+    {
331
+      "label": "Candy",
332
+      "value": [
333
+        { 
334
+          "label": "Chocolate",
335
+          "value": "chocolate" 
336
+        },
337
+        { 
338
+          "label": "Cream",
339
+          "value": "cream" 
340
+        },
341
+        { 
342
+          "label": "Lollipop",
343
+          "value": "lollipop" 
344
+        }
345
+      ]
346
+    }
347
+  ]
348
+}
349
+```
350
+
351
+---
352
+
353
+#### Color Picker
354
+
355
+**Manipulator:** [`color`](#color)
356
+
357
+A color picker that allows users to choose a color from the ones that are compatible with their Pebble smartwatch. 
358
+The color picker will automatically show a different layout depending on the watch connected: 
359
+
360
+ - Aplite (Firmware 2.x) - Black and white
361
+ - Aplite (Firmware 3.x) - Black and white. Will also include gray (`#AAAAAA`) if `allowGray` is set to `true`
362
+ - Basalt/chalk - The 64 colors compatible with color Pebble smartwatches. 
363
+
364
+##### Properties
365
+
366
+| Property | Type | Description |
367
+|----------|------|-------------|
368
+| type | string | Set to `color`. |
369
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
370
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
371
+| label | string | The label that should appear next to this item. |
372
+| defaultValue | string OR int | The default color. One of the [64 colors](https://developer.pebble.com/guides/tools-and-resources/color-picker/) compatible with Pebble smartwatches. Always use the uncorrected value even if `sunlight` is true. The component will do the conversion internally. |
373
+| description | string | Optional sub-text to include below the component |
374
+| sunlight | boolean | Use the color-corrected sunlight color palette if `true`, else the uncorrected version. Defaults to `true` if not specified. |
375
+| layout | string OR array | Optional. Use a custom layout for the color picker. Defaults to automatically choosing the most appropriate layout for the connected watch. The layout is represented by a two dimensional array. Use `false` to insert blank spaces. You may also use one of the preset layouts by setting `layout` to: `"COLOR"`, `"GRAY"` or `"BLACK_WHITE"` |
376
+| allowGray | boolean | Optional. Set this to `true` to include gray (`#AAAAAA`) in the color picker for aplite running on firmware 3 and above. This is optional because only a subset of the drawing operations support gray on aplite. Defaults to `false` |
377
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
378
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
379
+
380
+##### Example
381
+
382
+```javascript
383
+{
384
+  "type": "color",
385
+  "messageKey": "background",
386
+  "defaultValue": "ff0000",
387
+  "label": "Background Color",
388
+  "sunlight": true,
389
+  "layout": [
390
+    [false, "00aaff", false],
391
+    ["0055ff", "0000ff", "0000aa"],
392
+    [false, "5555ff", false]
393
+  ]
394
+}
395
+```
396
+
397
+##### Example
398
+
399
+```javascript
400
+{
401
+  "type": "color",
402
+  "messageKey": "background",
403
+  "defaultValue": "ffffff",
404
+  "label": "Background Color",
405
+  "sunlight": false,
406
+  "layout": "BLACK_WHITE"
407
+}
408
+```
409
+
410
+##### Example
411
+
412
+```javascript
413
+{
414
+  "type": "color",
415
+  "messageKey": "background",
416
+  "defaultValue": "aaaaaa",
417
+  "label": "Background Color",
418
+  "sunlight": false,
419
+  "allowGray": true
420
+}
421
+```
422
+
423
+---
424
+
425
+#### Radio Group
426
+
427
+**Manipulator:** [`radiogroup`](#radiogroup)
428
+
429
+A list of options allowing the user can only choose one option to submit.
430
+
431
+##### Properties
432
+
433
+| Property | Type | Description |
434
+|----------|------|-------------|
435
+| type | string | Set to `radiogroup`. |
436
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
437
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. |
438
+| label | string | The label that should appear next to this item. |
439
+| defaultValue | string | The default selected item. Must match a value in the `options` array. |
440
+| description | string | Optional sub-text to include below the component |
441
+| 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. |
442
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
443
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
444
+
445
+##### Example
446
+
447
+```javascript
448
+{
449
+  "type": "radiogroup",
450
+  "messageKey": "favorite_food",
451
+  "label": "Favorite Food",
452
+  "options": [
453
+    { 
454
+      "label": "Sushi", 
455
+      "value": "sushi" 
456
+    },
457
+    { 
458
+      "label": "Pizza", 
459
+      "value": "pizza" 
460
+    },
461
+    { 
462
+      "label": "Burgers", 
463
+      "value": "burgers" 
464
+    }
465
+  ]
466
+}
467
+```
468
+
469
+---
470
+
471
+#### Checkbox Group
472
+
473
+**Manipulator:** [`checkboxgroup`](#checkboxgroup)
474
+
475
+A list of options where a user may choose more than one option to submit.
476
+
477
+##### Properties
478
+
479
+| Property | Type | Description |
480
+|----------|------|-------------|
481
+| type | string | Set to `checkboxgroup`. |
482
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
483
+| messageKey | string (unique) | The AppMessage key matching the `messageKey` item defined in your `package.json`.  Set this to a unique string to allow this item to be looked up using `Clay.getItemsByMessageKey()` 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. **NOTE:** The checkboxgroup component will expect you to have defined a `messageKey` in your `package.json` using array syntax. In the example below, the matching entry in the `package.json` would be `favorite_food[3]`. In CloudPebble, you must use `Automatic assignment` for message keys and the `Key Array Length` must match the number of options in the checkboxgroup |
484
+| label | string | The label that should appear next to this item. |
485
+| defaultValue | array of booleans | The default selected items. |
486
+| description | string | Optional sub-text to include below the component |
487
+| options | array of strings | The labels for each checkbox you want to appear in the checkbox group. |
488
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
489
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
490
+
491
+##### Example
492
+
493
+```javascript
494
+{
495
+  "type": "checkboxgroup",
496
+  "messageKey": "favorite_food",
497
+  "label": "Favorite Food",
498
+  "defaultValue": [true, false, true],
499
+  "options": ["Sushi", "Pizza", "Burgers"]
500
+}
501
+```
502
+
503
+In the above example, Sushi and Burgers will be selected by default.
504
+
505
+---
506
+
507
+### Generic Button
508
+
509
+**Manipulator:** [`button`](#button)
510
+
511
+##### Properties
512
+
513
+| Property | Type | Description |
514
+|----------|------|-------------|
515
+| type | string | Set to `button`. |
516
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
517
+| defaultValue | string | The text displayed on the button. |
518
+| primary | boolean | If `true` the button will be orange, if `false`, the button will be gray (defaults to `false`)|
519
+| description | string | Optional sub-text to include below the component |
520
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
521
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
522
+
523
+##### Example
524
+
525
+```javascript
526
+{
527
+  "type": "button",
528
+  "primary": true,
529
+  "defaultValue": "Send"
530
+}
531
+```
532
+
533
+---
534
+
535
+### Range Slider
536
+
537
+**Manipulator:** [`slider`](#slider)
538
+
539
+The range slider is used to allow users to select numbers between two values. 
540
+
541
+**NOTE** If you set the `step` property to anything less than `1`, 
542
+it will multiply the final value sent to the watch by 10 to the power of the number of decimal places in the value of `step`.
543
+Eg: If you set the `step` to `0.25` and the slider has value of `34.5`, the watch will receive `3450`. 
544
+The reason why this is necessary, is because you can not send floats to the watch via `Pebble.sendAppMessage()`. 
545
+This allows your users to still be able to input values that have decimals, 
546
+you must just remember to divide the received value on the watch accordingly. 
547
+
548
+##### Properties
549
+
550
+| Property | Type | Description |
551
+|----------|------|-------------|
552
+| type | string | Set to `slider`. |
553
+| defaultValue | number | The value of the slider. |
554
+| label | string | The label that should appear next to this item. |
555
+| min | number | The minimum allowed value of the slider. Defaults to `100` |
556
+| max | number | The maximum allowed value of the slider. Defaults to `0` |
557
+| step | number | The multiple of the values allowed to be set on the slider. The slider will snap to these values. This value also determines the precision used when the value is sent to the watch. Defaults to 1 |
558
+| description | string | Optional sub-text to include below the component |
559
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
560
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
561
+
562
+##### Example
563
+
564
+```javascript
565
+{
566
+  "type": "slider",
567
+  "messageKey": "slider",
568
+  "defaultValue": 15,
569
+  "label": "Slider",
570
+  "description": "This is the description for the slider",
571
+  "min": 10,
572
+  "max": 20,
573
+  "step": 0.25
574
+},
575
+```
576
+
577
+---
578
+
579
+### Submit
580
+
581
+**Manipulator:** [`button`](#button)
582
+
583
+The submit button for the page. You **MUST** include this component somewhere in the config page (traditionally at the bottom) or users will not be able to save the form. 
584
+
585
+##### Properties
586
+
587
+| Property | Type | Description |
588
+|----------|------|-------------|
589
+| type | string | Set to `submit`. |
590
+| defaultValue | string | The text displayed on the button. |
591
+| id | string (unique) | Set this to a unique string to allow this item to be looked up using `Clay.getItemById()` in your [custom function](#custom-function). |
592
+| capabilities | array | Array of features that the connected watch must have for this item to be present |
593
+| group | string | Set this to allow this item, along with other items sharing the same group to be looked up using `Clay.getItemsByGroup()` in your [custom function](#custom-function) |
594
+
595
+##### Example
596
+
597
+```javascript
598
+{
599
+  "type": "submit",
600
+  "defaultValue": "Save"
601
+}
602
+```
603
+
604
+---
605
+
606
+### Message keys and array syntax
607
+
608
+Clay supports (and requires in some cases) the use of array syntax for message keys. Also known as `Automatic assignment` in CloudPebble. More info [here.](https://developer.pebble.com/guides/communication/using-pebblekit-js/#defining-keys)
609
+
610
+You can assign any component that does not return an array to a particular position in your message key. This is done by appending the position (zero indexed) wrapped in brackets to the end of the `messageKey` property. Do **NOT** include any spaces in your `messageKey`.
611
+
612
+##### Example
613
+
614
+```javascript
615
+{
616
+  "type": "toggle",
617
+  "messageKey": "light_switch[1]",
618
+  "label": "Invert Colors",
619
+  "defaultValue": true
620
+}
621
+```
622
+In the above example, the value of the item will be accessible with `MESSAGE_KEY_light_switch + 1` in your C code.
623
+
624
+Components that return an array in their `.get()` method, such as the checkboxgroup will expect the corresponding message key to already be defined with the correct length. You **CAN NOT** use the array syntax in the `messageKey` property as this would be trying to create a 2 dimensional array.
625
+
626
+##### Example
627
+
628
+```javascript
629
+{
630
+  "type": "checkboxgroup",
631
+  "messageKey": "favorite_food",
632
+  "label": "Favorite Food",
633
+  "defaultValue": [true, false, true],
634
+  "options": ["Sushi", "Pizza", "Burgers"]
635
+}
636
+```
637
+In the above example, the value of the item will be accessible with `MESSAGE_KEY_favorite_food`, `MESSAGE_KEY_favorite_food + 1`, and `MESSAGE_KEY_favorite_food + 2` in your C code.
638
+
639
+---
640
+### Showing items for specific platforms and features
641
+
642
+If you want particular items or sections to only be present in the config based on the
643
+connected watch's capabilities, you can include the "capabilities" property in the item. 
644
+The "capabilities" property is an array of features that the connected watch must have
645
+in order for the item or section to be included in the page. Note: all capabilities in 
646
+the array must be present for item/section to be included. 
647
+
648
+You can also prefix the capability with `NOT_` to negate the capability. Eg: `NOT_HEALTH` 
649
+will only be included in the page if the device does **NOT** support health. 
650
+
651
+**Warning:** Items that do not satisfy the capabilities will not be included in the page 
652
+at all. You will not be able to use methods like `clayConfig.getItemByMessageKey()` to
653
+obtain a reference to them. However, this does mean that you will be able to have
654
+multiple items with the same `messageKey`as long as they do not both satisfy the
655
+same conditions. 
656
+
657
+##### Examples
658
+
659
+```javascript
660
+{
661
+  "type": "text",
662
+  "defaultValue": "This item will only be visible for watches that are rectangular and have a microphone"
663
+  "capabilities": ["MICROPHONE", "RECT"],
664
+}
665
+```
666
+
667
+```javascript
668
+{
669
+  "type": "section",
670
+  "capabilities": ["NOT_HEALTH"],
671
+  "items": [
672
+    {
673
+      "type": "text",
674
+      "defaultValue": "Only visible for watches that do not support health"
675
+    }
676
+  ]
677
+}
678
+```
679
+
680
+Below is the full list of capabilities 
681
+
682
+| Capability | Description |
683
+|------------|-------------|
684
+| PLATFORM_APLITE | Running on Pebble/Pebble Steel.|
685
+| PLATFORM_BASALT | Running on Pebble Time/Pebble Time Steel. |
686
+| PLATFORM_CHALK | Running on Pebble Time Round. |
687
+| PLATFORM_DIORITE | Running on Pebble 2 |
688
+| PLATFORM_EMERY | Running on Time 2. |
689
+| BW | Running on hardware that supports only black and white. |
690
+| COLOR | Running on hardware that supports 64 colors. |
691
+| MICROPHONE | Running on hardware that includes a microphone. |
692
+| SMARTSTRAP | Running on hardware that includes a smartstrap connector. |
693
+| SMARTSTRAP_POWER | Running on hardware that includes a powered smartstrap connector. |
694
+| HEALTH | Running on hardware that supports Pebble Health and the HealthService API. |
695
+| RECT | Running on hardware with a rectangular display. |
696
+| ROUND | Running on hardware with a round display. |
697
+| DISPLAY_144x168 | Running on hardware with a 144x168 pixels display. |
698
+| DISPLAY_180x180_ROUND | Running on hardware with a 180x180 pixels round display. |
699
+| DISPLAY_200x228 | Running on hardware with a 200x228 pixels display. |
700
+
701
+## Manipulators 
702
+
703
+Each component has a **manipulator**. This is a set of methods used to talk to the item on the page. 
704
+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()`. 
705
+**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. 
706
+
707
+When the config page is closed, the `.get()` method is run on all components registered with an `messageKey` to construct the object sent to the C app.
708
+
709
+Many of these methods fire an event when the method is called. You can listen for these events with `ClayItem.on()`. 
710
+**NOTE** These events will only be fired if the state actually changes. 
711
+Eg: If you run the `.show()` manipulator on an item that is already visible, the `show` event will not be triggered.
712
+
713
+#### html
714
+
715
+| Method | Returns | Event Fired | Description | 
716
+|--------|---------|-------------| ------------|
717
+| `.set( [string\|HTML] value)` | `ClayItem` | `change` | Sets the content of this item. |
718
+| `.get()` | `string` | | Gets the content of this item. |
719
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
720
+| `.show()` | `ClayItem` | `show` | Shows the item |
721
+
722
+#### button
723
+
724
+| Method | Returns | Event Fired | Description | 
725
+|--------|---------|-------------| ------------|
726
+| `.set( [string\|HTML] value)` | `ClayItem` | `change` | Sets the content of this item. |
727
+| `.get()` | `string` | | Gets the content of this item. |
728
+| `.disable()` |  `ClayItem` | `disabled` | Prevents this item from being clicked by the user. |
729
+| `.enable()` |  `ClayItem` | `enabled` | Allows this item to be clicked by the user. |
730
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
731
+| `.show()` | `ClayItem` | `show` | Shows the item |
732
+
733
+#### val
734
+
735
+| Method | Returns | Event Fired | Description | 
736
+|--------|---------|-------------| ------------|
737
+| `.set( [string] value)` | `ClayItem` | `change` | Sets the value of this item. |
738
+| `.get()` |  `string` | | Gets the content of this item. |
739
+| `.disable()` |  `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
740
+| `.enable()` |  `ClayItem` | `enabled` | Allows this item to be edited by the user. |
741
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
742
+| `.show()` | `ClayItem` | `show` | Shows the item |
743
+
744
+#### checked
745
+
746
+| Method | Returns | Event Fired | Description | 
747
+|--------|---------|-------------| ------------|
748
+| `.set( [boolean\|int] value)` | `ClayItem` | `change` | Check/uncheck the state of this item. |
749
+| `.get()` | `boolean` | | `true` if checked, `false` if not. **NOTE** this will be converted to a `1` or `0` when sent to the watch. See [`Clay.getSettings()`](#methods) |
750
+| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
751
+| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
752
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
753
+| `.show()` | `ClayItem` | `show` | Shows the item |
754
+
755
+#### color
756
+
757
+| Method | Returns | Event Fired | Description | 
758
+|--------|---------|-------------| ------------|
759
+| `.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'`. |
760
+| `.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()`. |
761
+| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
762
+| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
763
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
764
+| `.show()` | `ClayItem` | `show` | Shows the item |
765
+
766
+#### radiogroup
767
+
768
+| Method | Returns | Event Fired | Description | 
769
+|--------|---------|-------------| ------------|
770
+| `.set( [string] value)` | `ClayItem` | `change` | Checks the radio button that corresponds to the provided value. |
771
+| `.get()` |  `string` | | Gets the value of the checked radio button in the list. |
772
+| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
773
+| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
774
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
775
+| `.show()` | `ClayItem` | `show` | Shows the item |
776
+
777
+#### checkboxgroup
778
+
779
+| Method | Returns | Event Fired | Description | 
780
+|--------|---------|-------------| ------------|
781
+| `.set( [array] value)` | `ClayItem` | `change` | Checks the checkboxes that corresponds to the provided list of values. |
782
+| `.get()` |  `Array.<string>` | | Gets an array of booleans representing the list the checked items. **NOTE:** each item in the array will be converted to an `int` when sent to the watch. See [`Clay.getSettings()`](#methods) |
783
+| `.disable()` | `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
784
+| `.enable()` | `ClayItem` | `enabled` | Allows this item to be edited by the user. |
785
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
786
+| `.show()` | `ClayItem` | `show` | Shows the item |
787
+
788
+#### slider
789
+
790
+| Method | Returns | Event Fired | Description | 
791
+|--------|---------|-------------| ------------|
792
+| `.set( [number] value)` | `ClayItem` | `change` | Sets the value of this item. |
793
+| `.get()` |  `number` | | Gets the value of this item. |
794
+| `.disable()` |  `ClayItem` | `disabled` | Prevents this item from being edited by the user. |
795
+| `.enable()` |  `ClayItem` | `enabled` | Allows this item to be edited by the user. |
796
+| `.hide()` | `ClayItem` | `hide` | Hides the item |
797
+| `.show()` | `ClayItem` | `show` | Shows the item |
798
+
799
+# Extending Clay
800
+
801
+Clay is built to allow developers to add their own basic interactivity to the config page. This can be done in a number of ways:
802
+
803
+## Handling The 'showConfiguration' and 'webviewclosed' Events Manually
804
+
805
+Clay will by default, automatically handle the 'showConfiguration' and 'webviewclosed' events. This allows the `messageKey` of each config item to be automatically delivered to the `InboxReceivedHandler` on the watch side. If you wish to override this behavior and handle the events yourself, pass an object as the 3rd parameter of the Clay constructor with `autoHandleEvents` set to `false`.
806
+
807
+Example:
808
+
809
+```javascript
810
+var Clay = require('pebble-clay');
811
+var clayConfig = require('./config');
812
+var clayConfigAplite = require('./config-aplite');
813
+var clay = new Clay(clayConfig, null, { autoHandleEvents: false });
814
+
815
+Pebble.addEventListener('showConfiguration', function(e) {
816
+  
817
+  // This is an example of how you might load a different config based on platform.
818
+  var platform = clay.meta.activeWatchInfo.platform || 'aplite';
819
+  if (platform === 'aplite') {
820
+    clay.config = clayConfigAplite;
821
+  }
822
+  
823
+  Pebble.openURL(clay.generateUrl());
824
+});
825
+
826
+Pebble.addEventListener('webviewclosed', function(e) {
827
+  if (e && !e.response) {
828
+    return;
829
+  }
830
+
831
+  // Get the keys and values from each config item
832
+  var dict = clay.getSettings(e.response);
833
+
834
+  // Send settings values to watch side
835
+  Pebble.sendAppMessage(dict, function(e) {
836
+    console.log('Sent config data to Pebble');
837
+  }, function(e) {
838
+    console.log('Failed to send config data!');
839
+    console.log(JSON.stringify(e));
840
+  });
841
+});
842
+```
843
+
844
+## Clay API (app.js)
845
+
846
+### `Clay([Array] config, [function] customFn, [object] options)`
847
+
848
+#### Constructor Parameters
849
+
850
+| Parameter | Type | Description |
851
+|----------|-------|-------------|
852
+| `config` | Array | The config that will be used to generate the configuration page |
853
+| `customFn` | Function\|null | (Optional) The [custom function](#custom-function) to be injected into the generated configuration page.  |
854
+| `options` | Object | (Optional) See below for properties |
855
+| `options.autoHandleEvents` | Boolean | (Optional) Defaults to `true`. If set to `false`, Clay will not [auto handle the `showConfiguration` and `webviewclosed` events](#handling-the-showconfiguration-and-webviewclosed-events-manually) |
856
+| `options.userData` | Any | (Optional) Any arbitrary data you want to pass to your config page. It will be available in your custom function as `this.meta.userData` |
857
+
858
+#### Properties
859
+
860
+| Property | Type | Description |
861
+|----------|------|-------------|
862
+| `.config` | Array | Copy of the config passed to the constructor and used for generating the page. |
863
+| `.customFn` | Function | Reference to the custom function passed to the constructor. **WARNING** this is a direct reference, not a copy of the custom function so any modification you make to it, will be reflected on the original as well |
864
+| `.meta` | Object | Contains information about the current user and watch. **WARNING** This will only be populated in the `showConfiguration` event handler. (See example above) |
865
+| `.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). |
866
+| `.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). |
867
+| `.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). |
868
+| `.meta.userData` | Any | A deep copy of the arbitrary data provided in the `options.userData`. Defaults to an empty object |
869
+| `.version` | String | The version of Clay currently being used. |
870
+
871
+#### Methods
872
+
873
+| Method | Returns |
874
+| -------|---------|
875
+| `Clay( [array] config, [function] customFn=null, [object] options={autoHandleEvents: true})` <br> `config` - an Array representing your config <br> `customFn` - function to be run in the context of the generated page <br> `options.autoHandleEvents` - set to `false` to prevent Clay from automatically handling the "showConfiguration" and "webviewclosed" events | `Clay` - a new instance of Clay. |
876
+| `.registerComponent( [ClayComponent] component )` <br> Registers a custom component. | `void`. |  
877
+| `.generateUrl()` | `string` - The URL to open with `Pebble.openURL()` to use the Clay-generated config page. |
878
+| `.getSettings( [object] response, [boolean] convert=true)` <br> `response` - the response object provided to the "webviewclosed" event <br> `convert` - Pass `false` to not convert the settings to be compatible with `Pebble.sendAppMessage()` | `Object` - object of keys and values for each config page item with an `messageKey`, where the key is the `messageKey` and the value is the chosen value of that item.  <br><br>This method will do some conversions depending on the type of the setting. Arrays will use message key array syntax to make the values of each item in the array available as individual message keys. Booleans will be converted to numbers. eg `true` becomes `1` and `false` becomes `0`. If the value is a number or an array of numbers and the optional property: "precision" is the power of precision (value * 10 ^ precision) and then floored. Eg: `1.4567` with a precision set to `3` will become `1456`. Pass `false` as the second parameter to disable this behavior. See the example below for how this all works |
879
+| `.setSettings( [string] key, [*] value )` <br> `key` - The key for the setting you want to set. <br> `value` - The value of the setting you want to set. | `void` |
880
+| `.setSettings( [object] settings )` <br> `settings` - An object of key/value pairs that you would like to update the settings with. eg `{ user_name: 'Emily', show_animations: true }` | `void` |
881
+
882
+#### `.getSettings()` Example 
883
+
884
+```javascript
885
+
886
+// webviewclosed response
887
+{
888
+  "favorite_food": {"value": [1, 0, 1]},
889
+  "cool_things_enabled": {"value": true},
890
+  "user_name": {"value": "Jane Doe"},
891
+  "date_of_birth[0]": {"value": 1989},
892
+  "date_of_birth[1]": {"value": 11},
893
+  "date_of_birth[2]": {"value": 28},
894
+  "rating": {"value": 3.5, "precision": 1},
895
+}
896
+
897
+// resulting converted values
898
+
899
+var messageKeys = require('message_keys');
900
+
901
+messageKeys.favorite_food + 0 = 1;
902
+messageKeys.favorite_food + 1 = 0;
903
+messageKeys.favorite_food + 2 = 1;
904
+messageKeys.cool_things_enabled = 1;
905
+messageKeys.user_name = 'Jane Doe';
906
+messageKeys.date_of_birth + 0 = 1989;
907
+messageKeys.date_of_birth + 1 = 11;
908
+messageKeys.date_of_birth + 2 = 28;
909
+messageKeys.rating = 35;
910
+
911
+
912
+``` 
913
+
914
+---
915
+
916
+
917
+## Custom Function
918
+
919
+When initializing Clay in your `app.js` file, you can optionally provide a function that will be copied and run on the generated config page. 
920
+
921
+**IMPORTANT:** This function is injected by running `.toString()` on it. If you are making use of `require` or any other dynamic features, they will not work. You must make sure that everything the function needs to execute is available in the function body itself. 
922
+
923
+This function, when injected into the config page, will be run with `ClayConfig` as its context (`this`), and [**Minified**](#minified) as its first parameter.
924
+
925
+Make sure to always wait for the config page to be built before manipulating items. You do this by registering a handler for the `Clay.EVENTS.AFTER_BUILD` event (see below). 
926
+
927
+#### Example 
928
+
929
+##### app.js
930
+
931
+```javascript
932
+var Clay = require('pebble-clay');
933
+var clayConfig = require('./config');
934
+var customClay = require('./custom-clay');
935
+var userData = {token: 'abc123'}
936
+var clay = new Clay(clayConfig, customClay, {userData: userData});
937
+```
938
+
939
+##### custom-clay.js
940
+
941
+```javascript
942
+module.exports = function(minified) {
943
+  var clayConfig = this;
944
+  var _ = minified._;
945
+  var $ = minified.$;
946
+  var HTML = minified.HTML;
947
+
948
+  function toggleBackground() {
949
+    if (this.get()) {
950
+      clayConfig.getItemByMessageKey('background').enable();
951
+    } else {
952
+      clayConfig.getItemByMessageKey('background').disable();
953
+    }
954
+  }
955
+
956
+  clayConfig.on(clayConfig.EVENTS.AFTER_BUILD, function() {
957
+    var coolStuffToggle = clayConfig.getItemByMessageKey('cool_stuff');
958
+    toggleBackground.call(coolStuffToggle);
959
+    coolStuffToggle.on('change', toggleBackground);
960
+    
961
+    // Hide the color picker for aplite
962
+    if (!clayConfig.meta.activeWatchInfo || clayConfig.meta.activeWatchInfo.platform === 'aplite') {
963
+      clayConfig.getItemByMessageKey('background').hide();
964
+    }
965
+    
966
+    // Set the value of an item based on the userData
967
+    $.request('get', 'https://some.cool/api', {token: clayConfig.meta.userData.token})
968
+      .then(function(result) {
969
+        // Do something interesting with the data from the server
970
+      })
971
+      .error(function(status, statusText, responseText) {
972
+        // Handle the error
973
+      });
974
+  });
975
+  
976
+};
977
+```
978
+
979
+## Clay API (Custom Function)
980
+
981
+### `ClayConfig([Object] settings, [Array] config, [$Minified] $rootContainer)`
982
+
983
+This is the main way of talking to your generated config page. An instance of this class will be passed as the context of your custom function when it runs on the generated config page. 
984
+
985
+#### Properties
986
+
987
+| Property | Type | Description |
988
+|----------|------|-------------|
989
+| `.EVENTS.BEFORE_BUILD` | String | Dispatched prior to building the page. |
990
+| `.EVENTS.AFTER_BUILD` | String | Dispatched after building the page. |
991
+| `.EVENTS.BEFORE_DESTROY` | String | Dispatched prior to destroying the page. |
992
+| `.EVENTS.AFTER_DESTROY` | String | Dispatched after destroying the page. |
993
+| `.config` | Array | Reference to the config passed to the constructor and used for generating the page. |
994
+| `.meta` | Object | Contains information about the current user and watch |
995
+| `.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). |
996
+| `.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). |
997
+| `.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). |
998
+| `.meta.userData` | Any | The data passed in the `options.userData` of the [Clay constructor.](#clayarray-config-function-customfn-object-options) |
999
+
1000
+
1001
+#### Methods
1002
+
1003
+| Method | Returns |
1004
+|--------|---------|
1005
+| `.getAllItems()` | `Array.<ConfigItem>` - an array of all config items. |
1006
+| `.getItemByMessageKey( [string] messageKey )` | `ConfigItem\|undefined` - a single `ConfigItem` that has the provided `messageKey`, otherwise `undefined`. |
1007
+| `.getItemById( [string] id )` | `ConfigItem\|undefined` - a single `ConfigItem` that has the provided `id`, otherwise `undefined`. |
1008
+| `.getItemsByType( [string] type )` | `Array.<ConfigItem>` - an array of config items that match the provided `type`. |
1009
+| `.getItemsByGroup( [string] group )` | `Array.<ConfigItem>` - an array of config items that match the provided `group`. |
1010
+| `.serialize()` | `Object` - an object representing all items with an `messageKey` where the key is the `messageKey` and the value is an object with the `value` property set to the result of running `.get()` on the Clay item. If the Clay item has a `precision` property set, it is included in the object |
1011
+| `.build()` <br> Builds the config page. Will dispatch the `BEFORE_BUILD` event prior to building the page, then the `AFTER_BUILD` event once it is complete. If the config page has already been built, then the `ClayConfig.destroy()` method will be executed prior to building the page again. | `ClayConfig` |
1012
+| `.destroy()` <br> Destroys the config page. Will dispatch the `BEFORE_DESTROY` event prior to destroying the page, then the `AFTER_DESTROY` event once it is complete. This method wipes the config page completely, including all existing items. You will need to make sure that you re-attach your event handlers for any items that are replaced | `ClayConfig` |
1013
+| `.on( [string] events, [function] handler )` <br> Register an event to the provided handler. The handler will be called with this instance of `ClayConfig` as the context. If you wish to register multiple events to the same handler, then separate the events with a space | `ClayConfig` |
1014
+| `.off( [function] handler )` <br> Remove the given event handler. **NOTE:** This will remove the handler from all registered events. | `ClayConfig` |
1015
+| `.trigger( [string] name, [object] eventObj={} )` <br> Trigger the provided event and optionally pass extra data to the handler. | `ClayConfig` |
1016
+| `.registerComponent( [ClayComponent] component )` <br> Registers a component. You must register all components prior to calling `.build()`. This method is also available statically. | `Boolean` - `true` if the component was registered successfully, otherwise `false`.  |
1017
+
1018
+---
1019
+
1020
+### `ClayItem( [Object] config )`
1021
+
1022
+#### Properties
1023
+
1024
+| Property | Type | Description |
1025
+|----------|------|-------------|
1026
+| `.id` | String | The ID of the item if provided in the config. |
1027
+| `.messageKey` | String | The messageKey of the item if provided in the config. |
1028
+| `.config` | Object | Reference to the config passed to the constructer. |
1029
+| `$element` | $Minified | A Minified list representing the root HTML element of the config item. |
1030
+| `$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. |
1031
+
1032
+
1033
+#### Methods
1034
+
1035
+| Method | Returns |
1036
+|--------|---------|
1037
+| `.initialize( [ClayConfig] clay)` <br> You shouldn't ever need to run this method manually as it will automatically be called when the config is built. | `ConfigItem` |
1038
+| `.on( [string] events, [function] handler )` <br> Register an event to the provided handler. The handler will be called with this instance of `ClayItem` as the context. If you wish to register multiple events to the same handler, then separate the events with a space. Events will be registered against the `$manipulatorTarget` so most DOM events such as **"change"** or **"click"** can be listened for. | `ClayItem` |
1039
+| `.off( [function] handler )` <br> Remove the given event handler. **NOTE:** This will remove the handler from all registered events. | `ClayItem` |
1040
+| `.trigger( [string] name, [object] eventObj={} )` <br> Trigger the provided event and optionally pass extra data to the handler. | `ClayItem` |
1041
+
1042
+In addition to the methods above, all the methods from the item's manipulator will be attached to the `ClayItem`. This includes `.set()` and `.get()`.
1043
+
1044
+---
1045
+
1046
+## Custom Components
1047
+
1048
+Clay is also able to be extended using custom components. This allows developers to share components with each other. 
1049
+
1050
+### Component Structure
1051
+
1052
+Components are simple objects with the following properties.
1053
+
1054
+#### `ClayComponent`
1055
+
1056
+| Property | Type | Required | Description | 
1057
+|----------|------|----------|-------------|
1058
+| `name` | string | yes | This is the unique way to identify the component and will be used by the config item's `type`. | 
1059
+| `template` | string (HTML) | yes | This is the actual HTML content of the component. Make sure there is only **one** root node in the HTML. This HTML will be passed to Minified's `HTML()` method. Any properties provided by the config item will be made available to the template, eg: `label`. The template will also be provided with `clayId` as a unique way to set input `name` attributes. |
1060
+| `style` | string | no | Any extra CSS styles you want to inject into the page. Make sure to namespace your CSS with a class that is unique to your component in order to avoid conflicts with other components. |
1061
+| `manipulator` | string / manipulator | yes | Provide a string here to use one of the built-in manipulators, such as `val`. If an object is provided, it must have both a `.set(value)` and `.get()` method. |
1062
+| `defaults` | object | Only if your template requires it. | An object of all the defaults your template requires. |
1063
+| `initialize` | function | no | Method which will be called after the item has been added to the page. It will be called with the `ClayItem` as the context (`this`) and with [`minified`](#minified) as the first parameter and [`clayConfig`](#clayconfigobject-settings-array-config-minified-rootcontainer) as the second parameter |
1064
+
1065
+### Registering a custom component. 
1066
+
1067
+Components must be registered before the config page is built. The easiest way to do this is in your `app.js` after you have initialized Clay:
1068
+
1069
+```javascript
1070
+var Clay = require('pebble-clay');
1071
+var clayConfig = require('./config.json');
1072
+var clay = new Clay(clayConfig);
1073
+
1074
+clay.registerComponent(require('./my-custom-component'));
1075
+```
1076
+
1077
+## Minified
1078
+
1079
+[Minified](http://minifiedjs.com) is a super light JQuery-like library. We only bundle in a small subset of its functionality. Visit the [Minified Docs](http://minifiedjs.com/api/) for more info on how to use Minified. Below is the subset of methods available in Clay.
1080
+
1081
+ - `$()`
1082
+ - `$$()`
1083
+ - `.get()`
1084
+ - `.select()`
1085
+ - `.set()`
1086
+ - `.add()`
1087
+ - `.ht()`
1088
+ - `HTML()`
1089
+ - `$.request()`
1090
+ - `promise.always()`
1091
+ - `promise.error()`
1092
+ - `$.off()`
1093
+ - `$.ready()`
1094
+ - `$.wait()`
1095
+ - `.on()`
1096
+ - `.each()`
1097
+ - `.find()`
1098
+ - `_()`
1099
+ - `_.copyObj()`
1100
+ - `_.eachObj()`
1101
+ - `_.extend()`
1102
+ - `_.format()`
1103
+ - `_.formatHtml()`
1104
+ - `_.template()`
1105
+ - `_.isObject()`
1106
+
1107
+# Migrating from v0.1.x to v1.x
1108
+
1109
+There were some changes in the 3.13 SDK that required Clay to undergo some major changes. For the majority of developers a simple find and replace over your config will do the trick.
1110
+
1111
+### appKey is now messageKey.
1112
+
1113
+You will need to update your config files and change any items that use `appKey` to `messageKey`
1114
+
1115
+##### Example
1116
+
1117
+```javascript
1118
+{
1119
+  "type": "toggle",
1120
+  "appKey": "invert",
1121
+  "label": "Invert Colors",
1122
+  "defaultValue": true
1123
+}
1124
+```
1125
+becomes:
1126
+
1127
+```javascript
1128
+{
1129
+  "type": "toggle",
1130
+  "messageKey": "invert",
1131
+  "label": "Invert Colors",
1132
+  "defaultValue": true
1133
+}
1134
+```
1135
+
1136
+### clayConfig.getItemByAppKey is now clayConfig.getItemByMessageKey.
1137
+
1138
+If you have a [custom function](#custom-function) and are using the `clayConfig.getItemByAppKey()` method you will need to change this to `clayConfig.getItemByMessageKey()`
1139
+
1140
+### clay.getSettings() will now by default, return an object where the keys are numbers.
1141
+
1142
+In the past, `clay.getSettings()` would return something that looked like:
1143
+
1144
+```javascript
1145
+{
1146
+  BACKGROUND_COLOR: 0,
1147
+  NAME: 'Jane Doe',
1148
+  ENABLE_TOOLS: 1
1149
+}
1150
+```
1151
+
1152
+It now uses the values provided in the `message_keys` module to construct this object.
1153
+The new format looks something like:
1154
+
1155
+```javascript
1156
+{
1157
+  10000: 0,
1158
+  10001: 'Jane Doe',
1159
+  10002: 1
1160
+}
1161
+```
1162
+
1163
+If you wish to find out what keys are associated with what values, you must use the `message_keys` module.
1164
+
1165
+```javascript
1166
+var messageKeys = require('message_keys');
1167
+
1168
+Pebble.addEventListener('webviewclosed', function(e) {
1169
+  // Get the keys and values from each config item
1170
+  var claySettings = clay.getSettings(e.response);
1171
+
1172
+  // In this example messageKeys.NAME is equal to 10001
1173
+  console.log('Name is ' + claySettings[messageKeys.NAME]); // Logs: "Name is Jane Doe"
1174
+});
1175
+```
1176
+
1177
+**NOTE:** The above only applies to the default behavior of the method. If you pass
1178
+`false` to the second argument, a standard object will be returned with the `messageKey`
1179
+as the key.
1180
+
1181
+```javascript
1182
+
1183
+Pebble.addEventListener('webviewclosed', function(e) {
1184
+
1185
+  clay.getSettings(e.response);
1186
+    /* returns:
1187
+    {
1188
+      10000: 0,
1189
+      10001: 'Jane Doe',
1190
+      10002: 1
1191
+    }
1192
+    */
1193
+
1194
+  clay.getSettings(e.response, false);
1195
+    /* returns:
1196
+    {
1197
+      BACKGROUND_COLOR: {value: 0},
1198
+      NAME: {value: 'Jane Doe'},
1199
+      ENABLE_TOOLS: {value: true}
1200
+    }
1201
+
1202
+    Notice that the value for ENABLE_TOOLS was not converted to a number from a boolean
1203
+    */
1204
+});
1205
+
1206
+```
1207
+
1208
+### Checkbox groups now use arrays.
1209
+
1210
+In the previous version of Clay, checkbox groups would split the values of the items with zeros. This made for clumsy usage on the C side. Checkbox groups are now much simpler to use thanks to message keys. You will however need to update you config to the new format.
1211
+
1212
+#### Changes:
1213
+ - `defaultValue` and the value that is returned by the `.get()` method is now an array of booleans.
1214
+ - `options` are now an array of labels and do not have their own value
1215
+ - Instead of splitting the result on the C side you now use the message key syntax. In the example below `MESSAGE_KEY_favorite_food + 2` would have a value of `1`
1216
+
1217
+#### Old Format
1218
+
1219
+```javascript
1220
+{
1221
+  "type": "checkboxgroup",
1222
+  "appKey": "favorite_food",
1223
+  "label": "Favorite Food",
1224
+  "defaultValue": ["sushi", "burgers"],
1225
+  "options": [
1226
+    {
1227
+      "label": "Sushi",
1228
+      "value": "sushi"
1229
+    },
1230
+    {
1231
+      "label": "Pizza",
1232
+      "value": "pizza"
1233
+    },
1234
+    {
1235
+      "label": "Burgers",
1236
+      "value": "burgers"
1237
+    }
1238
+  ]
1239
+}
1240
+```
1241
+
1242
+#### New Format
1243
+
1244
+```javascript
1245
+{
1246
+  "type": "checkboxgroup",
1247
+  "messageKey": "favorite_food",
1248
+  "label": "Favorite Food",
1249
+  "defaultValue": [true, false, true],
1250
+  "options": ["Sushi", "Pizza", "Burgers"]
1251
+}
1252
+```
1253
+
1254
+### Clay is now a pebble package
1255
+
1256
+You no longer need to download a file into your project. Clay is now a Pebble package so you can go ahead and delete your `clay.js` and follow the getting started guide above to install clay in your project.
1257
+
1258
+Prior to SDK 3.13, `require` paths were handled in a non-standard way. When requiring modules, the name of the module was sufficient (ie. `require('config.json')`). However, with the release of SDK 3.13, the require paths changed so that you now have to require the module by using its path relative to the file it's being required in. This means requiring the config module now is done in app.js by using `require('./clay-config.json')`. An incorrect path would result in an error similar to this:
1259
+   ```
1260
+   [14:16:03] javascript> JavaScript Error:
1261
+   Error: Cannot find module 'clay-config.json'
1262
+       at Object.loader.require (loader.js:66:11)
1263
+       at _require.require (loader.js:54:48)
1264
+       at Object.loader (src/js/app.js:1:1)
1265
+       at _require (loader.js:57:10)
1266
+       at Object.loader.require (loader.js:69:10)
1267
+   ```
0 1268
new file mode 100644
1 1269
Binary files /dev/null and b/node_modules/pebble-clay/dist.zip differ
2 1270
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+!<arch>
0 2
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+!<arch>
0 2
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+!<arch>
0 2
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+!<arch>
0 2
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+!<arch>
0 2
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#pragma once
2
+#include <stdint.h>
3
+
4
+//
5
+// AUTOGENERATED BY BUILD
6
+// DO NOT MODIFY - CHANGES WILL BE OVERWRITTEN
7
+//
8
+
0 9
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#pragma once
2
+#include <stdint.h>
3
+
4
+//
5
+// AUTOGENERATED BY BUILD
6
+// DO NOT MODIFY - CHANGES WILL BE OVERWRITTEN
7
+//
8
+
0 9
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#pragma once
2
+#include <stdint.h>
3
+
4
+//
5
+// AUTOGENERATED BY BUILD
6
+// DO NOT MODIFY - CHANGES WILL BE OVERWRITTEN
7
+//
8
+
0 9
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#pragma once
2
+#include <stdint.h>
3
+
4
+//
5
+// AUTOGENERATED BY BUILD
6
+// DO NOT MODIFY - CHANGES WILL BE OVERWRITTEN
7
+//
8
+
0 9
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#pragma once
2
+#include <stdint.h>
3
+
4
+//
5
+// AUTOGENERATED BY BUILD
6
+// DO NOT MODIFY - CHANGES WILL BE OVERWRITTEN
7
+//
8
+
0 9
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+#pragma once
2
+#include <stdint.h>
3
+
4
+//
5
+// AUTOGENERATED BY BUILD
6
+// DO NOT MODIFY - CHANGES WILL BE OVERWRITTEN
7
+//
8
+
0 9
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+/* Clay - https://github.com/pebble/clay - Version: 1.0.4 - Build Date: 2016-11-21T20:14:28.839Z */
2
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.pebbleClay=t()}}(function(){var t;return function e(t,n,r){function o(a,s){if(!n[a]){if(!t[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(i)return i(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};t[a][0].call(u.exports,function(e){var n=t[a][1][e];return o(n?n:e)},u,u.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,e,n){"use strict";function r(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===t[e-2]?2:"="===t[e-1]?1:0}function o(t){return 3*t.length/4-r(t)}function i(t){var e,n,o,i,a,s,c=t.length;a=r(t),s=new f(3*c/4-a),o=a>0?c-4:c;var l=0;for(e=0,n=0;e<o;e+=4,n+=3)i=u[t.charCodeAt(e)]<<18|u[t.charCodeAt(e+1)]<<12|u[t.charCodeAt(e+2)]<<6|u[t.charCodeAt(e+3)],s[l++]=i>>16&255,s[l++]=i>>8&255,s[l++]=255&i;return 2===a?(i=u[t.charCodeAt(e)]<<2|u[t.charCodeAt(e+1)]>>4,s[l++]=255&i):1===a&&(i=u[t.charCodeAt(e)]<<10|u[t.charCodeAt(e+1)]<<4|u[t.charCodeAt(e+2)]>>2,s[l++]=i>>8&255,s[l++]=255&i),s}function a(t){return l[t>>18&63]+l[t>>12&63]+l[t>>6&63]+l[63&t]}function s(t,e,n){for(var r,o=[],i=e;i<n;i+=3)r=(t[i]<<16)+(t[i+1]<<8)+t[i+2],o.push(a(r));return o.join("")}function c(t){for(var e,n=t.length,r=n%3,o="",i=[],a=16383,c=0,u=n-r;c<u;c+=a)i.push(s(t,c,c+a>u?u:c+a));return 1===r?(e=t[n-1],o+=l[e>>2],o+=l[e<<4&63],o+="=="):2===r&&(e=(t[n-2]<<8)+t[n-1],o+=l[e>>10],o+=l[e>>4&63],o+=l[e<<2&63],o+="="),i.push(o),i.join("")}n.byteLength=o,n.toByteArray=i,n.fromByteArray=c;for(var l=[],u=[],f="undefined"!=typeof Uint8Array?Uint8Array:Array,p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=0,h=p.length;d<h;++d)l[d]=p[d],u[p.charCodeAt(d)]=d;u["-".charCodeAt(0)]=62,u["_".charCodeAt(0)]=63},{}],2:[function(t,e,n){(function(e){/*!
3
+ * The buffer module from node.js, for the browser.
4
+ *
5
+ * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
6
+ * @license  MIT
7
+ */
8
+"use strict";function r(){try{var t=new Uint8Array(1);return t.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===t.foo()&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(e){return!1}}function o(){return a.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function i(t,e){if(o()<e)throw new RangeError("Invalid typed array length");return a.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e),t.__proto__=a.prototype):(null===t&&(t=new a(e)),t.length=e),t}function a(t,e,n){if(!(a.TYPED_ARRAY_SUPPORT||this instanceof a))return new a(t,e,n);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return u(this,t)}return s(this,t,e,n)}function s(t,e,n,r){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?d(t,e,n,r):"string"==typeof e?f(t,e,n):h(t,e)}function c(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function l(t,e,n,r){return c(e),e<=0?i(t,e):void 0!==n?"string"==typeof r?i(t,e).fill(n,r):i(t,e).fill(n):i(t,e)}function u(t,e){if(c(e),t=i(t,e<0?0:0|m(e)),!a.TYPED_ARRAY_SUPPORT)for(var n=0;n<e;++n)t[n]=0;return t}function f(t,e,n){if("string"==typeof n&&""!==n||(n="utf8"),!a.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|b(e,n);t=i(t,r);var o=t.write(e,n);return o!==r&&(t=t.slice(0,o)),t}function p(t,e){var n=e.length<0?0:0|m(e.length);t=i(t,n);for(var r=0;r<n;r+=1)t[r]=255&e[r];return t}function d(t,e,n,r){if(e.byteLength,n<0||e.byteLength<n)throw new RangeError("'offset' is out of bounds");if(e.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");return e=void 0===n&&void 0===r?new Uint8Array(e):void 0===r?new Uint8Array(e,n):new Uint8Array(e,n,r),a.TYPED_ARRAY_SUPPORT?(t=e,t.__proto__=a.prototype):t=p(t,e),t}function h(t,e){if(a.isBuffer(e)){var n=0|m(e.length);return t=i(t,n),0===t.length?t:(e.copy(t,0,0,n),t)}if(e){if("undefined"!=typeof ArrayBuffer&&e.buffer instanceof ArrayBuffer||"length"in e)return"number"!=typeof e.length||H(e.length)?i(t,0):p(t,e);if("Buffer"===e.type&&_(e.data))return p(t,e.data)}throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}function m(t){if(t>=o())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o().toString(16)+" bytes");return 0|t}function g(t){return+t!=t&&(t=0),a.alloc(+t)}function b(t,e){if(a.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var r=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return W(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(t).length;default:if(r)return W(t).length;e=(""+e).toLowerCase(),r=!0}}function y(t,e,n){var r=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if(n>>>=0,e>>>=0,n<=e)return"";for(t||(t="utf8");;)switch(t){case"hex":return D(this,e,n);case"utf8":case"utf-8":return E(this,e,n);case"ascii":return B(this,e,n);case"latin1":case"binary":return S(this,e,n);case"base64":return O(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}function v(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function A(t,e,n,r,o){if(0===t.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(o)return-1;n=t.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof e&&(e=a.from(e,r)),a.isBuffer(e))return 0===e.length?-1:w(t,e,n,r,o);if("number"==typeof e)return e=255&e,a.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):w(t,[e],n,r,o);throw new TypeError("val must be string, number or Buffer")}function w(t,e,n,r,o){function i(t,e){return 1===a?t[e]:t.readUInt16BE(e*a)}var a=1,s=t.length,c=e.length;if(void 0!==r&&(r=String(r).toLowerCase(),"ucs2"===r||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(t.length<2||e.length<2)return-1;a=2,s/=2,c/=2,n/=2}var l;if(o){var u=-1;for(l=n;l<s;l++)if(i(t,l)===i(e,u===-1?0:l-u)){if(u===-1&&(u=l),l-u+1===c)return u*a}else u!==-1&&(l-=l-u),u=-1}else for(n+c>s&&(n=s-c),l=n;l>=0;l--){for(var f=!0,p=0;p<c;p++)if(i(t,l+p)!==i(e,p)){f=!1;break}if(f)return l}return-1}function k(t,e,n,r){n=Number(n)||0;var o=t.length-n;r?(r=Number(r),r>o&&(r=o)):r=o;var i=e.length;if(i%2!==0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a<r;++a){var s=parseInt(e.substr(2*a,2),16);if(isNaN(s))return a;t[n+a]=s}return a}function x(t,e,n,r){return q(W(e,t.length-n),t,n,r)}function M(t,e,n,r){return q(Z(e),t,n,r)}function T(t,e,n,r){return M(t,e,n,r)}function R(t,e,n,r){return q(U(e),t,n,r)}function P(t,e,n,r){return q(J(e,t.length-n),t,n,r)}function O(t,e,n){return 0===e&&n===t.length?Q.fromByteArray(t):Q.fromByteArray(t.slice(e,n))}function E(t,e,n){n=Math.min(t.length,n);for(var r=[],o=e;o<n;){var i=t[o],a=null,s=i>239?4:i>223?3:i>191?2:1;if(o+s<=n){var c,l,u,f;switch(s){case 1:i<128&&(a=i);break;case 2:c=t[o+1],128===(192&c)&&(f=(31&i)<<6|63&c,f>127&&(a=f));break;case 3:c=t[o+1],l=t[o+2],128===(192&c)&&128===(192&l)&&(f=(15&i)<<12|(63&c)<<6|63&l,f>2047&&(f<55296||f>57343)&&(a=f));break;case 4:c=t[o+1],l=t[o+2],u=t[o+3],128===(192&c)&&128===(192&l)&&128===(192&u)&&(f=(15&i)<<18|(63&c)<<12|(63&l)<<6|63&u,f>65535&&f<1114112&&(a=f))}}null===a?(a=65533,s=1):a>65535&&(a-=65536,r.push(a>>>10&1023|55296),a=56320|1023&a),r.push(a),o+=s}return j(r)}function j(t){var e=t.length;if(e<=tt)return String.fromCharCode.apply(String,t);for(var n="",r=0;r<e;)n+=String.fromCharCode.apply(String,t.slice(r,r+=tt));return n}function B(t,e,n){var r="";n=Math.min(t.length,n);for(var o=e;o<n;++o)r+=String.fromCharCode(127&t[o]);return r}function S(t,e,n){var r="";n=Math.min(t.length,n);for(var o=e;o<n;++o)r+=String.fromCharCode(t[o]);return r}function D(t,e,n){var r=t.length;(!e||e<0)&&(e=0),(!n||n<0||n>r)&&(n=r);for(var o="",i=e;i<n;++i)o+=V(t[i]);return o}function N(t,e,n){for(var r=t.slice(e,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function Y(t,e,n){if(t%1!==0||t<0)throw new RangeError("offset is not uint");if(t+e>n)throw new RangeError("Trying to access beyond buffer length")}function F(t,e,n,r,o,i){if(!a.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||e<i)throw new RangeError('"value" argument is out of bounds');if(n+r>t.length)throw new RangeError("Index out of range")}function z(t,e,n,r){e<0&&(e=65535+e+1);for(var o=0,i=Math.min(t.length-n,2);o<i;++o)t[n+o]=(e&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function I(t,e,n,r){e<0&&(e=4294967295+e+1);for(var o=0,i=Math.min(t.length-n,4);o<i;++o)t[n+o]=e>>>8*(r?o:3-o)&255}function L(t,e,n,r,o,i){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function K(t,e,n,r,o){return o||L(t,e,n,4,3.4028234663852886e38,-3.4028234663852886e38),$.write(t,e,n,r,23,4),n+4}function G(t,e,n,r,o){return o||L(t,e,n,8,1.7976931348623157e308,-1.7976931348623157e308),$.write(t,e,n,r,52,8),n+8}function C(t){if(t=X(t).replace(et,""),t.length<2)return"";for(;t.length%4!==0;)t+="=";return t}function X(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function V(t){return t<16?"0"+t.toString(16):t.toString(16)}function W(t,e){e=e||1/0;for(var n,r=t.length,o=null,i=[],a=0;a<r;++a){if(n=t.charCodeAt(a),n>55295&&n<57344){if(!o){if(n>56319){(e-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(e-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(e-=3)>-1&&i.push(239,191,189),o=n;continue}n=(o-55296<<10|n-56320)+65536}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((e-=1)<0)break;i.push(n)}else if(n<2048){if((e-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function Z(t){for(var e=[],n=0;n<t.length;++n)e.push(255&t.charCodeAt(n));return e}function J(t,e){for(var n,r,o,i=[],a=0;a<t.length&&!((e-=2)<0);++a)n=t.charCodeAt(a),r=n>>8,o=n%256,i.push(o),i.push(r);return i}function U(t){return Q.toByteArray(C(t))}function q(t,e,n,r){for(var o=0;o<r&&!(o+n>=e.length||o>=t.length);++o)e[o+n]=t[o];return o}function H(t){return t!==t}var Q=t("base64-js"),$=t("ieee754"),_=t("isarray");n.Buffer=a,n.SlowBuffer=g,n.INSPECT_MAX_BYTES=50,a.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:r(),n.kMaxLength=o(),a.poolSize=8192,a._augment=function(t){return t.__proto__=a.prototype,t},a.from=function(t,e,n){return s(null,t,e,n)},a.TYPED_ARRAY_SUPPORT&&(a.prototype.__proto__=Uint8Array.prototype,a.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&a[Symbol.species]===a&&Object.defineProperty(a,Symbol.species,{value:null,configurable:!0})),a.alloc=function(t,e,n){return l(null,t,e,n)},a.allocUnsafe=function(t){return u(null,t)},a.allocUnsafeSlow=function(t){return u(null,t)},a.isBuffer=function(t){return!(null==t||!t._isBuffer)},a.compare=function(t,e){if(!a.isBuffer(t)||!a.isBuffer(e))throw new TypeError("Arguments must be Buffers");if(t===e)return 0;for(var n=t.length,r=e.length,o=0,i=Math.min(n,r);o<i;++o)if(t[o]!==e[o]){n=t[o],r=e[o];break}return n<r?-1:r<n?1:0},a.isEncoding=function(t){switch(String(t).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},a.concat=function(t,e){if(!_(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return a.alloc(0);var n;if(void 0===e)for(e=0,n=0;n<t.length;++n)e+=t[n].length;var r=a.allocUnsafe(e),o=0;for(n=0;n<t.length;++n){var i=t[n];if(!a.isBuffer(i))throw new TypeError('"list" argument must be an Array of Buffers');i.copy(r,o),o+=i.length}return r},a.byteLength=b,a.prototype._isBuffer=!0,a.prototype.swap16=function(){var t=this.length;if(t%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var e=0;e<t;e+=2)v(this,e,e+1);return this},a.prototype.swap32=function(){var t=this.length;if(t%4!==0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var e=0;e<t;e+=4)v(this,e,e+3),v(this,e+1,e+2);return this},a.prototype.swap64=function(){var t=this.length;if(t%8!==0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var e=0;e<t;e+=8)v(this,e,e+7),v(this,e+1,e+6),v(this,e+2,e+5),v(this,e+3,e+4);return this},a.prototype.toString=function(){var t=0|this.length;return 0===t?"":0===arguments.length?E(this,0,t):y.apply(this,arguments)},a.prototype.equals=function(t){if(!a.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===a.compare(this,t)},a.prototype.inspect=function(){var t="",e=n.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,e).match(/.{2}/g).join(" "),this.length>e&&(t+=" ... ")),"<Buffer "+t+">"},a.prototype.compare=function(t,e,n,r,o){if(!a.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),e<0||n>t.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&e>=n)return 0;if(r>=o)return-1;if(e>=n)return 1;if(e>>>=0,n>>>=0,r>>>=0,o>>>=0,this===t)return 0;for(var i=o-r,s=n-e,c=Math.min(i,s),l=this.slice(r,o),u=t.slice(e,n),f=0;f<c;++f)if(l[f]!==u[f]){i=l[f],s=u[f];break}return i<s?-1:s<i?1:0},a.prototype.includes=function(t,e,n){return this.indexOf(t,e,n)!==-1},a.prototype.indexOf=function(t,e,n){return A(this,t,e,n,!0)},a.prototype.lastIndexOf=function(t,e,n){return A(this,t,e,n,!1)},a.prototype.write=function(t,e,n,r){if(void 0===e)r="utf8",n=this.length,e=0;else if(void 0===n&&"string"==typeof e)r=e,n=this.length,e=0;else{if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e=0|e,isFinite(n)?(n=0|n,void 0===r&&(r="utf8")):(r=n,n=void 0)}var o=this.length-e;if((void 0===n||n>o)&&(n=o),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return k(this,t,e,n);case"utf8":case"utf-8":return x(this,t,e,n);case"ascii":return M(this,t,e,n);case"latin1":case"binary":return T(this,t,e,n);case"base64":return R(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return P(this,t,e,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},a.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var tt=4096;a.prototype.slice=function(t,e){var n=this.length;t=~~t,e=void 0===e?n:~~e,t<0?(t+=n,t<0&&(t=0)):t>n&&(t=n),e<0?(e+=n,e<0&&(e=0)):e>n&&(e=n),e<t&&(e=t);var r;if(a.TYPED_ARRAY_SUPPORT)r=this.subarray(t,e),r.__proto__=a.prototype;else{var o=e-t;r=new a(o,(void 0));for(var i=0;i<o;++i)r[i]=this[i+t]}return r},a.prototype.readUIntLE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=this[t],o=1,i=0;++i<e&&(o*=256);)r+=this[t+i]*o;return r},a.prototype.readUIntBE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=this[t+--e],o=1;e>0&&(o*=256);)r+=this[t+--e]*o;return r},a.prototype.readUInt8=function(t,e){return e||Y(t,1,this.length),this[t]},a.prototype.readUInt16LE=function(t,e){return e||Y(t,2,this.length),this[t]|this[t+1]<<8},a.prototype.readUInt16BE=function(t,e){return e||Y(t,2,this.length),this[t]<<8|this[t+1]},a.prototype.readUInt32LE=function(t,e){return e||Y(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},a.prototype.readUInt32BE=function(t,e){return e||Y(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},a.prototype.readIntLE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=this[t],o=1,i=0;++i<e&&(o*=256);)r+=this[t+i]*o;return o*=128,r>=o&&(r-=Math.pow(2,8*e)),r},a.prototype.readIntBE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=e,o=1,i=this[t+--r];r>0&&(o*=256);)i+=this[t+--r]*o;return o*=128,i>=o&&(i-=Math.pow(2,8*e)),i},a.prototype.readInt8=function(t,e){return e||Y(t,1,this.length),128&this[t]?(255-this[t]+1)*-1:this[t]},a.prototype.readInt16LE=function(t,e){e||Y(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},a.prototype.readInt16BE=function(t,e){e||Y(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},a.prototype.readInt32LE=function(t,e){return e||Y(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},a.prototype.readInt32BE=function(t,e){return e||Y(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},a.prototype.readFloatLE=function(t,e){return e||Y(t,4,this.length),$.read(this,t,!0,23,4)},a.prototype.readFloatBE=function(t,e){return e||Y(t,4,this.length),$.read(this,t,!1,23,4)},a.prototype.readDoubleLE=function(t,e){return e||Y(t,8,this.length),$.read(this,t,!0,52,8)},a.prototype.readDoubleBE=function(t,e){return e||Y(t,8,this.length),$.read(this,t,!1,52,8)},a.prototype.writeUIntLE=function(t,e,n,r){if(t=+t,e=0|e,n=0|n,!r){var o=Math.pow(2,8*n)-1;F(this,t,e,n,o,0)}var i=1,a=0;for(this[e]=255&t;++a<n&&(i*=256);)this[e+a]=t/i&255;return e+n},a.prototype.writeUIntBE=function(t,e,n,r){if(t=+t,e=0|e,n=0|n,!r){var o=Math.pow(2,8*n)-1;F(this,t,e,n,o,0)}var i=n-1,a=1;for(this[e+i]=255&t;--i>=0&&(a*=256);)this[e+i]=t/a&255;return e+n},a.prototype.writeUInt8=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,1,255,0),a.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},a.prototype.writeUInt16LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):z(this,t,e,!0),e+2},a.prototype.writeUInt16BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):z(this,t,e,!1),e+2},a.prototype.writeUInt32LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):I(this,t,e,!0),e+4},a.prototype.writeUInt32BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):I(this,t,e,!1),e+4},a.prototype.writeIntLE=function(t,e,n,r){if(t=+t,e=0|e,!r){var o=Math.pow(2,8*n-1);F(this,t,e,n,o-1,-o)}var i=0,a=1,s=0;for(this[e]=255&t;++i<n&&(a*=256);)t<0&&0===s&&0!==this[e+i-1]&&(s=1),this[e+i]=(t/a>>0)-s&255;return e+n},a.prototype.writeIntBE=function(t,e,n,r){if(t=+t,e=0|e,!r){var o=Math.pow(2,8*n-1);F(this,t,e,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[e+i]=255&t;--i>=0&&(a*=256);)t<0&&0===s&&0!==this[e+i+1]&&(s=1),this[e+i]=(t/a>>0)-s&255;return e+n},a.prototype.writeInt8=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,1,127,-128),a.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},a.prototype.writeInt16LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):z(this,t,e,!0),e+2},a.prototype.writeInt16BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):z(this,t,e,!1),e+2},a.prototype.writeInt32LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,2147483647,-2147483648),a.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):I(this,t,e,!0),e+4},a.prototype.writeInt32BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):I(this,t,e,!1),e+4},a.prototype.writeFloatLE=function(t,e,n){return K(this,t,e,!0,n)},a.prototype.writeFloatBE=function(t,e,n){return K(this,t,e,!1,n)},a.prototype.writeDoubleLE=function(t,e,n){return G(this,t,e,!0,n)},a.prototype.writeDoubleBE=function(t,e,n){return G(this,t,e,!1,n)},a.prototype.copy=function(t,e,n,r){if(n||(n=0),r||0===r||(r=this.length),e>=t.length&&(e=t.length),e||(e=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===t.length||0===this.length)return 0;if(e<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),t.length-e<r-n&&(r=t.length-e+n);var o,i=r-n;if(this===t&&n<e&&e<r)for(o=i-1;o>=0;--o)t[o+e]=this[o+n];else if(i<1e3||!a.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)t[o+e]=this[o+n];else Uint8Array.prototype.set.call(t,this.subarray(n,n+i),e);return i},a.prototype.fill=function(t,e,n,r){if("string"==typeof t){if("string"==typeof e?(r=e,e=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===t.length){var o=t.charCodeAt(0);o<256&&(t=o)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!a.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof t&&(t=255&t);if(e<0||this.length<e||this.length<n)throw new RangeError("Out of range index");if(n<=e)return this;e>>>=0,n=void 0===n?this.length:n>>>0,t||(t=0);var i;if("number"==typeof t)for(i=e;i<n;++i)this[i]=t;else{var s=a.isBuffer(t)?t:W(new a(t,r).toString()),c=s.length;for(i=0;i<n-e;++i)this[i+e]=s[i%c]}return this};var et=/[^+\/0-9A-Za-z-_]/g}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"base64-js":1,ieee754:4,isarray:5}],3:[function(e,n,r){(function(e){/*!
9
+ * @license deepcopy.js Copyright(c) 2013 sasa+1
10
+ * https://github.com/sasaplus1/deepcopy.js
11
+ * Released under the MIT license.
12
+ */
13
+!function(e,o){"object"==typeof r&&"object"==typeof n?n.exports=o():"function"==typeof t&&t.amd?t([],o):"object"==typeof r?r.deepcopy=o():e.deepcopy=o()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";t.exports=n(3)},function(t,n){"use strict";function r(t,e){if("[object Array]"!==o.call(t))throw new TypeError("array must be an Array");var n=void 0,r=void 0,i=void 0;for(n=0,r=t.length;r>n;++n)if(i=t[n],i===e||i!==i&&e!==e)return n;return-1}n.__esModule=!0;var o=Object.prototype.toString,i="undefined"!=typeof e?function(t){return e.isBuffer(t)}:function(){return!1},a="function"==typeof Object.keys?function(t){return Object.keys(t)}:function(t){var e=typeof t;if(null===t||"function"!==e&&"object"!==e)throw new TypeError("obj must be an Object");var n=[],r=void 0;for(r in t)Object.prototype.hasOwnProperty.call(t,r)&&n.push(r);return n},s="function"==typeof Symbol?function(t){return Object.getOwnPropertySymbols(t)}:function(){return[]};n.getKeys=a,n.getSymbols=s,n.indexOf=r,n.isBuffer=i},function(t,n,r){"use strict";function o(t,e){var n=a(t);return null!==n?n:i(t,e)}function i(t,n){if("function"!=typeof n)throw new TypeError("customizer is must be a Function");if("function"==typeof t){var r=String(t);return/^\s*function\s*\S*\([^\)]*\)\s*{\s*\[native code\]\s*}/.test(r)?t:new Function("return "+String(r))()}var o=c.call(t);if("[object Array]"===o)return[];if("[object Object]"===o&&t.constructor===Object)return{};if("[object Date]"===o)return new Date(t.getTime());if("[object RegExp]"===o){var i=String(t),a=i.lastIndexOf("/");return new RegExp(i.slice(1,a),i.slice(a+1))}if((0,s.isBuffer)(t)){var l=new e(t.length);return t.copy(l),l}var u=n(t);return void 0!==u?u:null}function a(t){var e=typeof t;return null!==t&&"object"!==e&&"function"!==e?t:null}n.__esModule=!0,n.copyValue=n.copyCollection=n.copy=void 0;var s=r(1),c=Object.prototype.toString;n.copy=o,n.copyCollection=i,n.copyValue=a},function(t,e,n){"use strict";function r(t){}function o(t){var e=arguments.length<=1||void 0===arguments[1]?r:arguments[1];if(null===t)return null;var n=(0,a.copyValue)(t);if(null!==n)return n;var o=(0,a.copyCollection)(t,e),s=null!==o?o:t,c=[t],l=[s];return i(t,e,s,c,l)}function i(t,e,n,r,o){if(null===t)return null;var c=(0,a.copyValue)(t);if(null!==c)return c;var l=(0,s.getKeys)(t).concat((0,s.getSymbols)(t)),u=void 0,f=void 0,p=void 0,d=void 0,h=void 0,m=void 0,g=void 0,b=void 0;for(u=0,f=l.length;f>u;++u)p=l[u],d=t[p],h=(0,s.indexOf)(r,d),m=void 0,g=void 0,b=void 0,-1===h?(m=(0,a.copy)(d,e),g=null!==m?m:d,null!==d&&/^(?:function|object)$/.test(typeof d)&&(r.push(d),o.push(g))):b=o[h],n[p]=b||i(d,e,g,r,o);return n}e.__esModule=!0;var a=n(2),s=n(1);e["default"]=o,t.exports=e["default"]}])})}).call(this,e("buffer").Buffer)},{buffer:2}],4:[function(t,e,n){n.read=function(t,e,n,r,o){var i,a,s=8*o-r-1,c=(1<<s)-1,l=c>>1,u=-7,f=n?o-1:0,p=n?-1:1,d=t[e+f];for(f+=p,i=d&(1<<-u)-1,d>>=-u,u+=s;u>0;i=256*i+t[e+f],f+=p,u-=8);for(a=i&(1<<-u)-1,i>>=-u,u+=r;u>0;a=256*a+t[e+f],f+=p,u-=8);if(0===i)i=1-l;else{if(i===c)return a?NaN:(d?-1:1)*(1/0);a+=Math.pow(2,r),i-=l}return(d?-1:1)*a*Math.pow(2,i-r)},n.write=function(t,e,n,r,o,i){var a,s,c,l=8*i-o-1,u=(1<<l)-1,f=u>>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,d=r?0:i-1,h=r?1:-1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,a=u):(a=Math.floor(Math.log(e)/Math.LN2),e*(c=Math.pow(2,-a))<1&&(a--,c*=2),e+=a+f>=1?p/c:p*Math.pow(2,1-f),e*c>=2&&(a++,c/=2),a+f>=u?(s=0,a=u):a+f>=1?(s=(e*c-1)*Math.pow(2,o),a+=f):(s=e*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;t[n+d]=255&s,d+=h,s/=256,o-=8);for(a=a<<o|s,l+=o;l>0;t[n+d]=255&a,d+=h,a/=256,l-=8);t[n+d-h]|=128*m}},{}],5:[function(t,e,n){var r={}.toString;e.exports=Array.isArray||function(t){return"[object Array]"==r.call(t)}},{}],6:[function(t,e,n){function r(t){return/^[a-z_$][0-9a-z_$]*$/gi.test(t)&&!i.test(t)}function o(t){if(a)return t.toString();var e=t.source.replace(/\//g,function(t,e,n){return 0===e||"\\"!==n[e-1]?"\\/":"/"}),n=(t.global&&"g"||"")+(t.ignoreCase&&"i"||"")+(t.multiline&&"m"||"");return"/"+e+"/"+n}/* toSource by Marcello Bastea-Forte - zlib license */
14
+e.exports=function(t,e,n,i){function a(t,e,n,i,s){function c(t){return n.slice(1)+t.join(","+(n&&"\n")+l)+(n?" ":"")}var l=i+n;switch(t=e?e(t):t,typeof t){case"string":return JSON.stringify(t);case"boolean":case"number":case"undefined":return""+t;case"function":return t.toString()}if(null===t)return"null";if(t instanceof RegExp)return o(t);if(t instanceof Date)return"new Date("+t.getTime()+")";var u=s.indexOf(t)+1;if(u>0)return"{$circularReference:"+u+"}";if(s.push(t),Array.isArray(t))return"["+c(t.map(function(t){return a(t,e,n,l,s.slice())}))+"]";var f=Object.keys(t);return f.length?"{"+c(f.map(function(o){return(r(o)?o:JSON.stringify(o))+":"+a(t[o],e,n,l,s.slice())}))+"}":"{}"}var s=[];return a(t,e,void 0===n?"  ":n||"",i||"",s)};var i=/^(abstract|boolean|break|byte|case|catch|char|class|const|continue|debugger|default|delete|do|double|else|enum|export|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|undefined|var|void|volatile|while|with)$/,a="\\/"===new RegExp("/").source},{}],7:[function(t,e,n){e.exports={name:"pebble-clay",version:"1.0.4",description:"Pebble Config Framework",scripts:{"test-travis":"./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --single-run --browsers chromeTravisCI && ./node_modules/.bin/eslint ./","test-debug":"(export DEBUG=true && ./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --no-single-run)",test:"./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --single-run",lint:"./node_modules/.bin/eslint ./",build:"gulp",dev:"gulp dev","pebble-clean":"rm -rf tmp src/js/index.js && pebble clean","pebble-publish":"npm run pebble-clean && npm run build && pebble build && pebble package publish && npm run pebble-clean","pebble-build":"npm run build && pebble build"},repository:{type:"git",url:"git+https://github.com/pebble/clay.git"},keywords:["pebble","config","configuration","pebble-package"],author:"Pebble Technology",license:"MIT",bugs:{url:"https://github.com/pebble/clay/issues"},pebble:{projectType:"package",sdkVersion:"3",targetPlatforms:["aplite","basalt","chalk","diorite","emery"],resources:{media:[]},capabilities:["configurable"]},homepage:"https://github.com/pebble/clay#readme",devDependencies:{autoprefixer:"^6.3.1",bourbon:"^4.2.6",browserify:"^13.0.0","browserify-istanbul":"^0.2.1",chai:"^3.4.1",deamdify:"^0.2.0",deepcopy:"^0.6.1",del:"^2.0.2",eslint:"^1.5.1","eslint-config-pebble":"^1.2.0","eslint-plugin-standard":"^1.3.1",gulp:"^3.9.0","gulp-autoprefixer":"^3.1.0","gulp-htmlmin":"^1.3.0","gulp-inline":"0.0.15","gulp-insert":"^0.5.0","gulp-sass":"^2.1.1","gulp-sourcemaps":"^1.6.0","gulp-uglify":"^1.5.2",joi:"^6.10.1",karma:"^0.13.19","karma-browserify":"^5.0.1","karma-chrome-launcher":"^0.2.2","karma-coverage":"^0.5.3","karma-mocha":"^0.2.1","karma-mocha-reporter":"^1.1.5","karma-source-map-support":"^1.1.0","karma-threshold-reporter":"^0.1.15",mocha:"^2.3.4",postcss:"^5.0.14","require-from-string":"^1.1.0",sassify:"^0.9.1",sinon:"^1.17.3",stringify:"^3.2.0",through:"^2.3.8",tosource:"^1.0.0","vinyl-buffer":"^1.0.0","vinyl-source-stream":"^1.1.0",watchify:"^3.7.0"},dependencies:{}}},{}],8:[function(t,e,n){"use strict";e.exports={name:"button",template:t("../../templates/components/button.tpl"),style:t("../../styles/clay/components/button.scss"),manipulator:"button",defaults:{primary:!1,attributes:{},description:""}}},{"../../styles/clay/components/button.scss":21,"../../templates/components/button.tpl":30}],9:[function(t,e,n){"use strict";e.exports={name:"checkboxgroup",template:t("../../templates/components/checkboxgroup.tpl"),style:t("../../styles/clay/components/checkboxgroup.scss"),manipulator:"checkboxgroup",defaults:{label:"",options:[],description:""}}},{"../../styles/clay/components/checkboxgroup.scss":22,"../../templates/components/checkboxgroup.tpl":31}],10:[function(t,e,n){"use strict";e.exports={name:"color",template:t("../../templates/components/color.tpl"),style:t("../../styles/clay/components/color.scss"),manipulator:"color",defaults:{label:"",description:""},initialize:function(t,e){function n(t){if("number"==typeof t)t=t.toString(16);else if(!t)return"transparent";return t=r(t),"#"+(f?p[t]:t)}function r(t){for(t=t.toLowerCase();t.length<6;)t="0"+t;return t}function o(t){switch(typeof t){case"number":return r(t.toString(16));case"string":return t.replace(/^#|^0x/,"");default:return t}}function i(t){return t.reduce(function(t,e){return t.concat(e)},[])}function a(t){t=t.replace(/^#|^0x/,"");var e=parseInt(t.slice(0,2),16)/255,n=parseInt(t.slice(2,4),16)/255,r=parseInt(t.slice(4),16)/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92,r=r>.04045?Math.pow((r+.055)/1.055,2.4):r/12.92;var o=(.4124*e+.3576*n+.1805*r)/.95047,i=(.2126*e+.7152*n+.0722*r)/1,a=(.0193*e+.1192*n+.9505*r)/1.08883;return o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,i=i>.008856?Math.pow(i,1/3):7.787*i+16/116,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,[116*i-16,500*(o-i),200*(i-a)]}function s(t,e){var n=t[0]-e[0],r=t[1]-e[1],o=t[2]-e[2];return Math.sqrt(Math.pow(n,2)+Math.pow(r,2)+Math.pow(o,2))}function c(){return!e.meta.activeWatchInfo||2===e.meta.activeWatchInfo.firmware.major||["aplite","diorite"].indexOf(e.meta.activeWatchInfo.platform)>-1&&!u.config.allowGray?d.BLACK_WHITE:["aplite","diorite"].indexOf(e.meta.activeWatchInfo.platform)>-1&&u.config.allowGray?d.GRAY:d.COLOR}var l=t.HTML,u=this;u.roundColorToLayout=function(t){var e=o(t);if(m.indexOf(e)===-1){var n=a(e),r=m.map(function(t){var e=a(o(t));return s(n,e)}),i=Math.min.apply(Math,r),c=r.indexOf(i);e=m[c]}return parseInt(e,16)};var f=u.config.sunlight!==!1,p={"000000":"000000","000055":"001e41","0000aa":"004387","0000ff":"0068ca","005500":"2b4a2c","005555":"27514f","0055aa":"16638d","0055ff":"007dce","00aa00":"5e9860","00aa55":"5c9b72","00aaaa":"57a5a2","00aaff":"4cb4db","00ff00":"8ee391","00ff55":"8ee69e","00ffaa":"8aebc0","00ffff":"84f5f1",550000:"4a161b",550055:"482748","5500aa":"40488a","5500ff":"2f6bcc",555500:"564e36",555555:"545454","5555aa":"4f6790","5555ff":"4180d0","55aa00":"759a64","55aa55":"759d76","55aaaa":"71a6a4","55aaff":"69b5dd","55ff00":"9ee594","55ff55":"9de7a0","55ffaa":"9becc2","55ffff":"95f6f2",aa0000:"99353f",aa0055:"983e5a",aa00aa:"955694",aa00ff:"8f74d2",aa5500:"9d5b4d",aa5555:"9d6064",aa55aa:"9a7099",aa55ff:"9587d5",aaaa00:"afa072",aaaa55:"aea382",aaaaaa:"ababab",ffffff:"ffffff",aaaaff:"a7bae2",aaff00:"c9e89d",aaff55:"c9eaa7",aaffaa:"c7f0c8",aaffff:"c3f9f7",ff0000:"e35462",ff0055:"e25874",ff00aa:"e16aa3",ff00ff:"de83dc",ff5500:"e66e6b",ff5555:"e6727c",ff55aa:"e37fa7",ff55ff:"e194df",ffaa00:"f1aa86",ffaa55:"f1ad93",ffaaaa:"efb5b8",ffaaff:"ecc3eb",ffff00:"ffeeab",ffff55:"fff1b5",ffffaa:"fff6d3"},d={COLOR:[[!1,!1,"55ff00","aaff55",!1,"ffff55","ffffaa",!1,!1],[!1,"aaffaa","55ff55","00ff00","aaff00","ffff00","ffaa55","ffaaaa",!1],["55ffaa","00ff55","00aa00","55aa00","aaaa55","aaaa00","ffaa00","ff5500","ff5555"],["aaffff","00ffaa","00aa55","55aa55","005500","555500","aa5500","ff0000","ff0055"],[!1,"55aaaa","00aaaa","005555","ffffff","000000","aa5555","aa0000",!1],["55ffff","00ffff","00aaff","0055aa","aaaaaa","555555","550000","aa0055","ff55aa"],["55aaff","0055ff","0000ff","0000aa","000055","550055","aa00aa","ff00aa","ffaaff"],[!1,"5555aa","5555ff","5500ff","5500aa","aa00ff","ff00ff","ff55ff",!1],[!1,!1,!1,"aaaaff","aa55ff","aa55aa",!1,!1,!1]],GRAY:[["000000","aaaaaa","ffffff"]],BLACK_WHITE:[["000000","ffffff"]]},h=u.config.layout||c();"string"==typeof h&&(h=d[h]),Array.isArray(h[0])||(h=[h]);var m=i(h).map(function(t){return o(t)}).filter(function(t){return t}),g="",b=h.length,y=0;h.forEach(function(t){y=t.length>y?t.length:y});for(var v=100/y,A=100/b,w=u.$element,k=0;k<b;k++)for(var x=0;x<y;x++){var M=o(h[k][x]),T=M?" selectable":"",R=0===k&&0===x||0===k&&!h[k][x-1]||!h[k][x-1]&&!h[k-1][x]?" rounded-tl":"",P=0===k&&!h[k][x+1]||!h[k][x+1]&&!h[k-1][x]?" rounded-tr ":"",O=k===h.length-1&&0===x||k===h.length-1&&!h[k][x-1]||!h[k][x-1]&&!h[k+1][x]?" rounded-bl":"",E=k===h.length-1&&!h[k][x+1]||!h[k][x+1]&&!h[k+1][x]?" rounded-br":"";g+='<i class="color-box '+T+R+P+O+E+'" '+(M?'data-value="'+parseInt(M,16)+'" ':"")+'style="width:'+v+"%; height:"+A+"%; background:"+n(M)+';"></i>'}var j=0;3===y&&(j=5),2===y&&(j=8);var B=j*v/A+"%",S=j+"%";w.select(".color-box-container").add(l(g)).set("$paddingTop",B).set("$paddingRight",S).set("$paddingBottom",B).set("$paddingLeft",S),w.select(".color-box-wrap").set("$paddingBottom",v/A*100+"%");var D=w.select(".value"),N=w.select(".picker-wrap"),Y=u.$manipulatorTarget.get("disabled");w.select("label").on("click",function(){Y||N.set("show")}),u.on("change",function(){var t=u.get();D.set("$background-color",n(t)),w.select(".color-box").set("-selected"),w.select('.color-box[data-value="'+t+'"]').set("+selected")}),w.select(".color-box.selectable").on("click",function(t){u.set(parseInt(t.target.dataset.value,10)),N.set("-show")}),N.on("click",function(){N.set("-show")}),u.on("disabled",function(){Y=!0}),u.on("enabled",function(){Y=!1}),u._layout=h}}},{"../../styles/clay/components/color.scss":23,"../../templates/components/color.tpl":32}],11:[function(t,e,n){"use strict";e.exports={name:"footer",template:t("../../templates/components/footer.tpl"),manipulator:"html"}},{"../../templates/components/footer.tpl":33}],12:[function(t,e,n){"use strict";e.exports={name:"heading",template:t("../../templates/components/heading.tpl"),manipulator:"html",defaults:{size:4}}},{"../../templates/components/heading.tpl":34}],13:[function(t,e,n){"use strict";e.exports={color:t("./color"),footer:t("./footer"),heading:t("./heading"),input:t("./input"),select:t("./select"),submit:t("./submit"),text:t("./text"),toggle:t("./toggle"),radiogroup:t("./radiogroup"),checkboxgroup:t("./checkboxgroup"),button:t("./button"),slider:t("./slider")}},{"./button":8,"./checkboxgroup":9,"./color":10,"./footer":11,"./heading":12,"./input":14,"./radiogroup":15,"./select":16,"./slider":17,"./submit":18,"./text":19,"./toggle":20}],14:[function(t,e,n){"use strict";e.exports={name:"input",template:t("../../templates/components/input.tpl"),style:t("../../styles/clay/components/input.scss"),manipulator:"val",defaults:{label:"",description:"",attributes:{}}}},{"../../styles/clay/components/input.scss":24,"../../templates/components/input.tpl":35}],15:[function(t,e,n){"use strict";e.exports={name:"radiogroup",template:t("../../templates/components/radiogroup.tpl"),style:t("../../styles/clay/components/radiogroup.scss"),manipulator:"radiogroup",defaults:{label:"",options:[],description:"",attributes:{}}}},{"../../styles/clay/components/radiogroup.scss":25,"../../templates/components/radiogroup.tpl":36}],16:[function(t,e,n){"use strict";e.exports={name:"select",template:t("../../templates/components/select.tpl"),style:t("../../styles/clay/components/select.scss"),manipulator:"val",defaults:{label:"",options:[],description:"",attributes:{}},initialize:function(){function t(){var t=e.$manipulatorTarget.get("selectedIndex"),r=e.$manipulatorTarget.select("option"),o=r[t]&&r[t].innerHTML;n.set("innerHTML",o)}var e=this,n=e.$element.select(".value");t(),e.on("change",t)}}},{"../../styles/clay/components/select.scss":26,"../../templates/components/select.tpl":37}],17:[function(t,e,n){"use strict";e.exports={name:"slider",template:t("../../templates/components/slider.tpl"),style:t("../../styles/clay/components/slider.scss"),manipulator:"slider",defaults:{label:"",description:"",min:0,max:100,step:1,attributes:{}},initialize:function(){function t(){var t=e.get().toFixed(e.precision);n.set("value",t),r.set("innerHTML",t)}var e=this,n=e.$element.select(".value"),r=e.$element.select(".value-pad"),o=e.$manipulatorTarget,i=o.get("step");i=i.toString(10).split(".")[1],e.precision=i?i.length:0,e.on("change",t),o.on("|input",t),t(),n.on("|input",function(){r.set("innerHTML",this.get("value"))}),n.on("|change",function(){e.set(this.get("value")),t()})}}},{"../../styles/clay/components/slider.scss":27,"../../templates/components/slider.tpl":38}],18:[function(t,e,n){"use strict";e.exports={name:"submit",template:t("../../templates/components/submit.tpl"),style:t("../../styles/clay/components/submit.scss"),manipulator:"button",defaults:{attributes:{}}}},{"../../styles/clay/components/submit.scss":28,"../../templates/components/submit.tpl":39}],19:[function(t,e,n){"use strict";e.exports={name:"text",template:t("../../templates/components/text.tpl"),manipulator:"html"}},{"../../templates/components/text.tpl":40}],20:[function(t,e,n){"use strict";e.exports={name:"toggle",template:t("../../templates/components/toggle.tpl"),style:t("../../styles/clay/components/toggle.scss"),manipulator:"checked",defaults:{label:"",description:"",attributes:{}}}},{"../../styles/clay/components/toggle.scss":29,"../../templates/components/toggle.tpl":41}],21:[function(t,e,n){e.exports=".component-button { text-align: center; }\n\n.section .component-button { padding-bottom: 0; }\n\n.component-button .description { padding-left: 0; padding-right: 0; }\n"},{}],22:[function(t,e,n){e.exports=".component-checkbox { display: block; }\n\n.section .component-checkbox { padding-right: 0.375rem; }\n\n.component-checkbox > .label { display: block; padding-bottom: 0.35rem; }\n\n.component-checkbox .checkbox-group { padding-bottom: 0.35rem; }\n\n.component-checkbox .checkbox-group label { padding: 0.35rem 0.375rem; }\n\n.component-checkbox .checkbox-group .label { font-size: 0.9em; }\n\n.component-checkbox .checkbox-group input { opacity: 0; position: absolute; }\n\n.component-checkbox .checkbox-group i { display: block; position: relative; border-radius: 0.25rem; width: 1.4rem; height: 1.4rem; border: 0.11765rem solid #767676; -webkit-flex-shrink: 0; flex-shrink: 0; }\n\n.component-checkbox .checkbox-group input:checked + i { border-color: #ff4700; background: #ff4700; }\n\n.component-checkbox .checkbox-group input:checked + i:after { content: ''; box-sizing: border-box; -webkit-transform: rotate(45deg); transform: rotate(45deg); position: absolute; left: 0.35rem; top: -0.05rem; display: block; width: 0.5rem; height: 1rem; border: 0 solid #ffffff; border-right-width: 0.11765rem; border-bottom-width: 0.11765rem; }\n\n.component-checkbox .description { padding-left: 0; padding-right: 0; }\n"},{}],23:[function(t,e,n){e.exports=".section .component-color { padding: 0; }\n\n.component-color .value { width: 2.2652rem; height: 1.4rem; border-radius: 0.7rem; box-shadow: 0 0.1rem 0.1rem #2f2f2f; display: block; background: #000; }\n\n.component-color .picker-wrap { left: 0; top: 0; right: 0; bottom: 0; position: fixed; padding: 0.7rem 0.375rem; background: rgba(0, 0, 0, 0.65); opacity: 0; -webkit-transition: opacity 100ms ease-in 175ms; transition: opacity 100ms ease-in 175ms; pointer-events: none; z-index: 100; display: -webkit-box; display: -webkit-flex; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; flex-direction: column; -webkit-box-pack: center; -webkit-justify-content: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; align-items: center; }\n\n.component-color .picker-wrap .picker { padding: 0.7rem 0.75rem; background: #484848; box-shadow: 0 0.17647rem 0.88235rem rgba(0, 0, 0, 0.4); border-radius: 0.25rem; width: 100%; max-width: 26rem; overflow: auto; }\n\n.component-color .picker-wrap.show { -webkit-transition-delay: 0ms; transition-delay: 0ms; pointer-events: auto; opacity: 1; }\n\n.component-color .color-box-wrap { box-sizing: border-box; position: relative; height: 0; width: 100%; padding: 0 0 100% 0; }\n\n.component-color .color-box-wrap .color-box-container { position: absolute; height: 99.97%; width: 100%; left: 0; top: 0; }\n\n.component-color .color-box-wrap .color-box-container .color-box { float: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-tl { border-top-left-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-tr { border-top-right-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-bl { border-bottom-left-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-br { border-bottom-right-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.selected { -webkit-transform: scale(1.1); transform: scale(1.1); border-radius: 0.25rem; box-shadow: #111 0 0 0.24rem; position: relative; z-index: 100; }\n"},{}],24:[function(t,e,n){e.exports=".section .component-input { padding: 0; }\n\n.component-input label { display: block; }\n\n.component-input .label { padding-bottom: 0.7rem; }\n\n.component-input .input { position: relative; min-width: 100%; margin-top: 0.7rem; margin-left: 0; }\n\n.component-input input { display: block; width: 100%; background: #333333; border-radius: 0.25rem; padding: 0.35rem 0.375rem; border: none; vertical-align: baseline; color: #ffffff; font-size: inherit; -webkit-appearance: none; appearance: none; min-height: 2.1rem; }\n\n.component-input input::-webkit-input-placeholder { color: #858585; }\n\n.component-input input::-moz-placeholder { color: #858585; }\n\n.component-input input:-moz-placeholder { color: #858585; }\n\n.component-input input:-ms-input-placeholder { color: #858585; }\n\n.component-input input:focus { border: none; box-shadow: none; }\n\n.component-input input:focus::-webkit-input-placeholder { color: #666666; }\n\n.component-input input:focus::-moz-placeholder { color: #666666; }\n\n.component-input input:focus:-moz-placeholder { color: #666666; }\n\n.component-input input:focus:-ms-input-placeholder { color: #666666; }\n"},{}],25:[function(t,e,n){e.exports=".component-radio { display: block; }\n\n.section .component-radio { padding-right: 0.375rem; }\n\n.component-radio > .label { display: block; padding-bottom: 0.35rem; }\n\n.component-radio .radio-group { padding-bottom: 0.35rem; }\n\n.component-radio .radio-group label { padding: 0.35rem 0.375rem; }\n\n.component-radio .radio-group .label { font-size: 0.9em; }\n\n.component-radio .radio-group input { opacity: 0; position: absolute; }\n\n.component-radio .radio-group i { display: block; position: relative; border-radius: 1.4rem; width: 1.4rem; height: 1.4rem; border: 2px solid #767676; -webkit-flex-shrink: 0; flex-shrink: 0; }\n\n.component-radio .radio-group input:checked + i { border-color: #ff4700; }\n\n.component-radio .radio-group input:checked + i:after { content: ''; display: block; position: absolute; left: 15%; right: 15%; top: 15%; bottom: 15%; border-radius: 1.4rem; background: #ff4700; }\n\n.component-radio .description { padding-left: 0; padding-right: 0; }\n"},{}],26:[function(t,e,n){e.exports='.section .component-select { padding: 0; }\n\n.component-select label { position: relative; }\n\n.component-select .value { position: relative; padding-right: 1.1rem; display: block; }\n\n.component-select .value:after { content: ""; position: absolute; right: 0; top: 50%; margin-top: -0.1rem; height: 0; width: 0; border-left: 0.425rem solid transparent; border-right: 0.425rem solid transparent; border-top: 0.425rem solid #ff4700; }\n\n.component-select select { opacity: 0; position: absolute; display: block; left: 0; right: 0; top: 0; bottom: 0; width: 100%; border: none; margin: 0; padding: 0; }\n'},{}],27:[function(t,e,n){e.exports=".section .component-slider { padding: 0; }\n\n.component-slider label { display: block; }\n\n.component-slider .label-container { display: -webkit-box; display: -webkit-flex; display: flex; -webkit-box-align: center; -webkit-align-items: center; align-items: center; width: 100%; padding-bottom: 0.7rem; }\n\n.component-slider .label { -webkit-box-flex: 1; -webkit-flex: 1; flex: 1; min-width: 1rem; display: block; padding-right: 0.75rem; }\n\n.component-slider .value-wrap { display: block; position: relative; }\n\n.component-slider .value, .component-slider .value-pad { display: block; background: #333333; border-radius: 0.25rem; padding: 0.35rem 0.375rem; border: none; vertical-align: baseline; color: #ffffff; text-align: right; margin: 0; min-width: 1rem; }\n\n.component-slider .value-pad { visibility: hidden; }\n\n.component-slider .value-pad:before { content: ' '; display: inline-block; }\n\n.component-slider .value { max-width: 100%; position: absolute; left: 0; top: 0; }\n\n.component-slider .input-wrap { padding: 0 0.75rem 0.7rem; }\n\n.component-slider .input { display: block; position: relative; min-width: 100%; height: 1.4rem; overflow: hidden; margin-left: 0; }\n\n.component-slider .input:before { content: ''; display: block; position: absolute; height: 0.17647rem; background: #666666; width: 100%; top: 0.61176rem; }\n\n.component-slider .input .slider { display: block; width: 100%; -webkit-appearance: none; appearance: none; position: relative; height: 1.4rem; margin: 0; background-color: transparent; }\n\n.component-slider .input .slider:focus { outline: none; }\n\n.component-slider .input .slider::-webkit-slider-runnable-track { border: none; height: 1.4rem; width: 100%; background-color: transparent; }\n\n.component-slider .input .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; position: relative; height: 1.4rem; width: 1.4rem; background-color: #ff4700; border-radius: 50%; }\n\n.component-slider .input .slider::-webkit-slider-thumb:before { content: \"\"; position: absolute; left: -1000px; top: 0.61176rem; height: 0.17647rem; width: 1001px; background: #ff4700; }\n"},{}],28:[function(t,e,n){e.exports=".component-submit { text-align: center; }\n"},{}],29:[function(t,e,n){e.exports=".section .component-toggle { padding: 0; }\n\n.component-toggle input { display: none; }\n\n.component-toggle .graphic { display: inline-block; position: relative; }\n\n.component-toggle .graphic .slide { display: block; border-radius: 1.05rem; height: 1.05rem; width: 2.2652rem; background: #2f2f2f; -webkit-transition: background-color 150ms linear; transition: background-color 150ms linear; }\n\n.component-toggle .graphic .marker { background: #ececec; width: 1.4rem; height: 1.4rem; border-radius: 1.4rem; position: absolute; left: 0; display: block; top: -0.175rem; -webkit-transition: -webkit-transform 150ms linear; transition: -webkit-transform 150ms linear; transition: transform 150ms linear; transition: transform 150ms linear, -webkit-transform 150ms linear; box-shadow: 0 0.1rem 0.1rem #2f2f2f; }\n\n.component-toggle input:checked + .graphic .slide { background: #993d19; }\n\n.component-toggle input:checked + .graphic .marker { background: #ff4700; -webkit-transform: translateX(0.8652rem); transform: translateX(0.8652rem); }\n"},{}],30:[function(t,e,n){e.exports='<div class="component component-button">\n  <button\n    type="button"\n    data-manipulator-target\n    class="{{primary ? \'primary\' : \'\'}}"\n    {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n  ></button>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],31:[function(t,e,n){e.exports='<div class="component component-checkbox">\n  <span class="label">{{{label}}}</span>\n  <div class="checkbox-group">\n    {{each options}}\n      <label class="tap-highlight">\n        <span class="label">{{{this}}}</span>\n        <input type="checkbox" value="1" name="clay-{{clayId}}" />\n        <i></i>\n      </label>\n    {{/each}}\n  </div>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],32:[function(t,e,n){e.exports='<div class="component component-color">\n  <label class="tap-highlight">\n    <input\n      data-manipulator-target\n      type="hidden"\n    />\n    <span class="label">{{{label}}}</span>\n    <span class="value"></span>\n  </label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n  <div class="picker-wrap">\n    <div class="picker">\n      <div class="color-box-wrap">\n        <div class="color-box-container"></div>\n      </div>\n    </div>\n  </div>\n</div>\n'},{}],33:[function(t,e,n){e.exports='<footer data-manipulator-target class="component component-footer"></footer>\n'},{}],34:[function(t,e,n){e.exports='<div class="component component-heading">\n  <h{{size}} data-manipulator-target></h{{size}}>\n</div>\n'},{}],35:[function(t,e,n){e.exports='<div class="component component-input">\n  <label class="tap-highlight">\n    <span class="label">{{{label}}}</span>\n    <span class="input">\n      <input\n      data-manipulator-target\n        {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n    />\n    </span>\n  </label>\n\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],36:[function(t,e,n){e.exports='<div class="component component-radio">\n  <span class="label">{{{label}}}</span>\n  <div class="radio-group">\n    {{each options}}\n      <label class="tap-highlight">\n        <span class="label">{{{this.label}}}</span>\n        <input\n          type="radio"\n          value="{{this.value}}"\n          name="clay-{{clayId}}"\n          {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n        />\n        <i></i>\n      </label>\n    {{/each}}\n  </div>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],37:[function(t,e,n){e.exports='<div class="component component-select">\n  <label class="tap-highlight">\n    <span class="label">{{{label}}}</span>\n    <span class="value"></span>\n    <select data-manipulator-target {{each key: attributes}}{{key}}="{{this}}"{{/each}}>\n      {{each options}}\n        {{if Array.isArray(this.value)}}\n          <optgroup label="{{this.label}}">\n            {{each this.value}}\n              <option value="{{this.value}}" class="item-select-option">{{this.label}}</option>\n            {{/each}}\n          </optgroup>\n        {{else}}\n          <option value="{{this.value}}" class="item-select-option">{{this.label}}</option>\n        {{/if}}\n      {{/each}}\n    </select>\n  </label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],38:[function(t,e,n){e.exports='<div class="component component-slider">\n  <label class="tap-highlight">\n    <span class="label-container">\n      <span class="label">{{{label}}}</span>\n      <span class="value-wrap">\n        <span class="value-pad"></span>\n        <input type="text" class="value" />\n      </span>\n    </span>\n    <span class="input">\n      <input\n        data-manipulator-target\n        class="slider"\n        type="range"\n        min="{{min}}"\n        max="{{max}}"\n        step="{{step}}"\n        {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n      />\n    </span>\n</label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],39:[function(t,e,n){e.exports='<div class="component component-submit">\n  <button\n    data-manipulator-target\n    type="submit"\n    {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n  ></button>\n</div>\n'},{}],40:[function(t,e,n){e.exports='<div class="component component-text">\n  <p data-manipulator-target></p>\n</div>\n'},{}],41:[function(t,e,n){e.exports='<div class="component component-toggle">\n  <label class="tap-highlight">\n    <span class="label">{{{label}}}</span>\n    <span class="input">\n      <input\n        data-manipulator-target\n        type="checkbox"\n        {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n      />\n      <span class="graphic">\n        <span class="slide"></span>\n        <span class="marker"></span>\n      </span>\n    </span>\n  </label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],42:[function(t,e,n){e.exports='<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><style>@font-face{font-family:PFDinDisplayProRegularWebfont;src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:400;font-style:normal}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;outline:0;font-size:100%;font:inherit;vertical-align:baseline}button,input,textarea{outline:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote:after,blockquote:before,q:after,q:before{content:\'\';content:none}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}body,html{font-weight:400;font-family:PFDinDisplayPro-Regular,PFDinDisplayProRegularWebfont,sans-serif;-webkit-font-smoothing:antialiased;font-size:17px;line-height:1.4;height:100%;color:#fff}body.platform-ios,html.platform-ios{font-size:16px}body{background-color:#333;padding:0 .75rem .7rem}em{font-style:italic}strong{font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;color:#ff4700}.platform-android strong{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}a{color:#858585}a:hover{color:inherit}h1,h2,h3,h4{text-transform:uppercase;font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;text-transform:uppercase;position:relative;top:.05rem;line-height:.9}.platform-android h1,.platform-android h2,.platform-android h3,.platform-android h4{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}h1{font-size:2rem;line-height:2.8rem}h2{font-size:1.8rem;line-height:2.8rem}h3{font-size:1.5rem;line-height:2.8rem}h4{font-size:1.2rem;line-height:1.4rem}h5{font-size:1rem;line-height:1.4rem}h6{font-size:.8rem;line-height:1.4rem}input{font-family:inherit;font-size:inherit;line-height:inherit}label{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;align-items:center;padding:.7rem .75rem}label .input{white-space:nowrap;display:-webkit-box;display:-webkit-flex;display:flex;max-width:50%;margin-left:.75rem}label.invalid .input:after{content:"!";display:inline-block;color:#fff;background:#ff4700;border-radius:.55rem;width:1.1rem;text-align:center;height:1.1rem;font-size:.825rem;vertical-align:middle;line-height:1.1rem;box-shadow:0 .1rem .1rem #2f2f2f;font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;-webkit-box-flex:0;-webkit-flex:0 0 1.1rem;flex:0 0 1.1rem;margin-left:.3rem}.platform-android label.invalid .input:after{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}.hide{display:none!important}.tap-highlight{-webkit-tap-highlight-color:rgba(255,255,255,.1);border-radius:.25rem}.tap-highlight:active{background-color:rgba(255,255,255,.1)}.component{padding-top:.7rem}.component.disabled{pointer-events:none}.component.disabled>*{opacity:.25}.section{background:#484848;border-radius:.25rem;box-shadow:#2f2f2f 0 .15rem .25rem}.section>.component{padding-bottom:.7rem;padding-right:.75rem;padding-left:.75rem;position:relative;margin-top:1rem}.section>.component:not(.hide)~.component{margin-top:0}.section>.component:first-child:after{display:none}.section>.component:after{content:"";background:#666;display:block;position:absolute;top:0;left:.375rem;right:.375rem;height:1px;pointer-events:none}.section>.component:not(.hide):after{display:none}.section>.component:not(.hide)~.component:not(.hide):after{display:block}.section>.component-heading:first-child{background:#414141;border-radius:.25rem .25rem 0 0}.section>.component-heading:first-child:after,.section>.component-heading:first-child~.component:not(.hide):after{display:none}.section>.component-heading:first-child~.component:not(.hide)~.component:not(.hide):after{display:block}.description{padding:0 .75rem .7rem;font-size:.9rem;line-height:1.4rem;color:#a4a4a4;text-align:left}.inputs{display:block;width:100%;border-collapse:collapse}.button,button{font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;font-size:1rem;line-height:1.4rem;text-transform:uppercase;background-color:#767676;border-radius:.25rem;border:none;display:inline-block;color:#fff;min-width:12rem;text-align:center;margin:0 auto .7rem;padding:.6rem;-webkit-tap-highlight-color:#858585}.platform-android .button,.platform-android button{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}.button:active,button:active{background-color:#858585}.platform-ios .button,.platform-ios button{padding:.5rem}.button.primary,.button[type=submit],button.primary,button[type=submit]{background-color:#ff4700;-webkit-tap-highlight-color:red}.button.primary:active,.button[type=submit]:active,button.primary:active,button[type=submit]:active{background-color:red}a.button{text-decoration:none;color:#fff}</style><meta name="viewport"content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><script>window.returnTo="$$RETURN_TO$$",window.clayConfig=$$CONFIG$$,window.claySettings=$$SETTINGS$$,window.customFn=$$CUSTOM_FN$$,window.clayComponents=$$COMPONENTS$$,window.clayMeta=$$META$$</script></head><body><form id="main-form"class="inputs"></form><script>!function t(e,n,r){function i(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(o)return o(a,!0);var c=new Error("Cannot find module \'"+a+"\'");throw c.code="MODULE_NOT_FOUND",c}var f=n[a]={exports:{}};e[a][0].call(f.exports,function(t){var n=e[a][1][t];return i(n?n:t)},f,f.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<r.length;a++)i(r[a]);return i}({1:[function(t,e,n){"use strict";var r=t("./vendor/minified"),i=t("./lib/clay-config"),o=r.$,a=r._,u=a.extend([],window.clayConfig||[]),s=a.extend({},window.claySettings||{}),c=window.returnTo||"pebblejs://close#",f=window.customFn||function(){},l=window.clayComponents||{},h=window.clayMeta||{},m=window.navigator.userAgent.match(/android/i)?"android":"ios";document.documentElement.classList.add("platform-"+m),a.eachObj(l,function(t,e){i.registerComponent(e)});var p=o("#main-form"),d=new i(s,u,p,h);p.on("submit",function(){location.href=c+encodeURIComponent(JSON.stringify(d.serialize()))}),f.call(d,r),d.build()},{"./lib/clay-config":2,"./vendor/minified":8}],2:[function(t,e,n){"use strict";function r(t,e,n,c){function f(){m=[],p={},d={},g=!1}function l(t,e){if(Array.isArray(t))t.forEach(function(t){l(t,e)});else if(u.includesCapability(c.activeWatchInfo,t.capabilities))if("section"===t.type){var n=i(\'<div class="section">\');e.add(n),l(t.items,n)}else{var r=o.copyObj(t);r.clayId=m.length;var s=new a(r).initialize(v);r.id&&(p[r.id]=s),r.messageKey&&(d[r.messageKey]=s),m.push(s);var f="undefined"!=typeof y[r.messageKey]?y[r.messageKey]:r.defaultValue;s.set("undefined"!=typeof f?f:""),e.add(s.$element)}}function h(t){if(!g)throw new Error("ClayConfig not built. build() must be run before you can run "+t+"()");return!0}var m,p,d,g,v=this,y=o.copyObj(t);v.meta=c,v.$rootContainer=n,v.EVENTS={BEFORE_BUILD:"BEFORE_BUILD",AFTER_BUILD:"AFTER_BUILD",BEFORE_DESTROY:"BEFORE_DESTROY",AFTER_DESTROY:"AFTER_DESTROY"},u.updateProperties(v.EVENTS,{writable:!1}),v.getAllItems=function(){return h("getAllItems"),m},v.getItemByMessageKey=function(t){return h("getItemByMessageKey"),d[t]},v.getItemById=function(t){return h("getItemById"),p[t]},v.getItemsByType=function(t){return h("getItemsByType"),m.filter(function(e){return e.config.type===t})},v.getItemsByGroup=function(t){return h("getItemsByGroup"),m.filter(function(e){return e.config.group===t})},v.serialize=function(){return h("serialize"),y={},o.eachObj(d,function(t,e){y[t]={value:e.get()},e.precision&&(y[t].precision=e.precision)}),y},v.registerComponent=r.registerComponent,v.destroy=function(){var t=n[0];for(v.trigger(v.EVENTS.BEFORE_DESTROY);t.firstChild;)t.removeChild(t.firstChild);return f(),v.trigger(v.EVENTS.AFTER_DESTROY),v},v.build=function(){return g&&v.destroy(),v.trigger(v.EVENTS.BEFORE_BUILD),l(v.config,n),g=!0,v.trigger(v.EVENTS.AFTER_BUILD),v},f(),s.call(v,n),u.updateProperties(v,{writable:!1,configurable:!1}),v.config=e}var i=t("../vendor/minified").HTML,o=t("../vendor/minified")._,a=t("./clay-item"),u=t("../lib/utils"),s=t("./clay-events"),c=t("./component-registry"),f=t("./manipulators");r.registerComponent=function(t){var e=o.copyObj(t);if(c[e.name])return console.warn("Component: "+e.name+" is already registered. If you wish to override the existing functionality, you must provide a new name"),!1;if("string"==typeof e.manipulator&&(e.manipulator=f[t.manipulator],!e.manipulator))throw new Error("The manipulator: "+t.manipulator+" does not exist in the built-in manipulators.");if(!e.manipulator)throw new Error("The manipulator must be defined");if("function"!=typeof e.manipulator.set||"function"!=typeof e.manipulator.get)throw new Error("The manipulator must have both a `get` and `set` method");if(e.style){var n=document.createElement("style");n.type="text/css",n.appendChild(document.createTextNode(e.style)),document.head.appendChild(n)}return c[e.name]=e,!0},e.exports=r},{"../lib/utils":7,"../vendor/minified":8,"./clay-events":3,"./clay-item":4,"./component-registry":5,"./manipulators":6}],3:[function(t,e,n){"use strict";function r(t){function e(t){return t.split(" ").map(function(t){return"|"+t.replace(/^\\|/,"")}).join(" ")}function n(t,e){var n=o.find(u,function(e){return e.handler===t?e:null});return n||(n={handler:t,proxy:e},u.push(n)),n.proxy}function r(t){return o.find(u,function(e){return e.handler===t?e.proxy:null})}var a=this,u=[];a.on=function(r,i){var o=e(r),a=this,u=n(i,function(){i.apply(a,arguments)});return t.on(o,u),a},a.off=function(t){var e=r(t);return e&&i.off(e),a},a.trigger=function(e,n){return t.trigger(e,n),a}}var i=t("../vendor/minified").$,o=t("../vendor/minified")._;e.exports=r},{"../vendor/minified":8}],4:[function(t,e,n){"use strict";function r(t){var e=this,n=i[t.type];if(!n)throw new Error("The component: "+t.type+" is not registered. Make sure to register it with ClayConfig.registerComponent()");var r={i18n:{foo:"bar"}},f=s.extend({},n.defaults||{},t,r),l=s.formatHtml(n.template.trim(),f);e.id=t.id||null,e.messageKey=t.messageKey||null,e.config=t,e.$element=c(l,f),e.$manipulatorTarget=e.$element.select("[data-manipulator-target]"),e.$manipulatorTarget.length||(e.$manipulatorTarget=e.$element),e.initialize=function(t){return"function"==typeof n.initialize&&n.initialize.call(e,o,t),e},u.call(e,e.$manipulatorTarget),s.eachObj(n.manipulator,function(t,n){e[t]=n.bind(e)}),a.updateProperties(e,{writable:!1,configurable:!1})}var i=t("./component-registry"),o=t("../vendor/minified"),a=t("../lib/utils"),u=t("./clay-events"),s=o._,c=o.HTML;e.exports=r},{"../lib/utils":7,"../vendor/minified":8,"./clay-events":3,"./component-registry":5}],5:[function(t,e,n){"use strict";e.exports={}},{}],6:[function(t,e,n){"use strict";function r(){return this.$manipulatorTarget.get("disabled")?this:(this.$element.set("+disabled"),this.$manipulatorTarget.set("disabled",!0),this.trigger("disabled"))}function i(){return this.$manipulatorTarget.get("disabled")?(this.$element.set("-disabled"),this.$manipulatorTarget.set("disabled",!1),this.trigger("enabled")):this}function o(){return this.$element[0].classList.contains("hide")?this:(this.$element.set("+hide"),this.trigger("hide"))}function a(){return this.$element[0].classList.contains("hide")?(this.$element.set("-hide"),this.trigger("show")):this}var u=t("../vendor/minified")._;e.exports={html:{get:function(){return this.$manipulatorTarget.get("innerHTML")},set:function(t){return this.get()===t.toString(10)?this:(this.$manipulatorTarget.set("innerHTML",t),this.trigger("change"))},hide:o,show:a},button:{get:function(){return this.$manipulatorTarget.get("innerHTML")},set:function(t){return this.get()===t.toString(10)?this:(this.$manipulatorTarget.set("innerHTML",t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},val:{get:function(){return this.$manipulatorTarget.get("value")},set:function(t){return this.get()===t.toString(10)?this:(this.$manipulatorTarget.set("value",t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},slider:{get:function(){return parseFloat(this.$manipulatorTarget.get("value"))},set:function(t){var e=this.get();return this.$manipulatorTarget.set("value",t),this.get()===e?this:this.trigger("change")},disable:r,enable:i,hide:o,show:a},checked:{get:function(){return this.$manipulatorTarget.get("checked")},set:function(t){return!this.get()==!t?this:(this.$manipulatorTarget.set("checked",!!t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},radiogroup:{get:function(){return this.$element.select("input:checked").get("value")},set:function(t){return this.get()===t.toString(10)?this:(this.$element.select(\'input[value="\'+t.replace(\'"\',\'\\\\"\')+\'"]\').set("checked",!0),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},checkboxgroup:{get:function(){var t=[];return this.$element.select("input").each(function(e){t.push(!!e.checked)}),t},set:function(t){var e=this;for(t=Array.isArray(t)?t:[];t.length<this.get().length;)t.push(!1);return u.equals(this.get(),t)?this:(e.$element.select("input").set("checked",!1).each(function(e,n){e.checked=!!t[n]}),e.trigger("change"))},disable:r,enable:i,hide:o,show:a},color:{get:function(){return parseInt(this.$manipulatorTarget.get("value"),10)||0},set:function(t){return t=this.roundColorToLayout(t||0),this.get()===t?this:(this.$manipulatorTarget.set("value",t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a}}},{"../vendor/minified":8}],7:[function(t,e,n){"use strict";e.exports.updateProperties=function(t,e){Object.getOwnPropertyNames(t).forEach(function(n){Object.defineProperty(t,n,e)})},e.exports.capabilityMap={PLATFORM_APLITE:{platforms:["aplite"],minFwMajor:0,minFwMinor:0},PLATFORM_BASALT:{platforms:["basalt"],minFwMajor:0,minFwMinor:0},PLATFORM_CHALK:{platforms:["chalk"],minFwMajor:0,minFwMinor:0},PLATFORM_DIORITE:{platforms:["diorite"],minFwMajor:0,minFwMinor:0},PLATFORM_EMERY:{platforms:["emery"],minFwMajor:0,minFwMinor:0},BW:{platforms:["aplite","diorite"],minFwMajor:0,minFwMinor:0},COLOR:{platforms:["basalt","chalk","emery"],minFwMajor:0,minFwMinor:0},MICROPHONE:{platforms:["basalt","chalk","diorite","emery"],minFwMajor:0,minFwMinor:0},SMARTSTRAP:{platforms:["basalt","chalk","diorite","emery"],minFwMajor:3,minFwMinor:4},SMARTSTRAP_POWER:{platforms:["basalt","chalk","emery"],minFwMajor:3,minFwMinor:4},HEALTH:{platforms:["basalt","chalk","diorite","emery"],minFwMajor:3,minFwMinor:10},RECT:{platforms:["aplite","basalt","diorite","emery"],minFwMajor:0,minFwMinor:0},ROUND:{platforms:["chalk"],minFwMajor:0,minFwMinor:0},DISPLAY_144x168:{platforms:["aplite","basalt","diorite"],minFwMajor:0,minFwMinor:0},DISPLAY_180x180_ROUND:{platforms:["chalk"],minFwMajor:0,minFwMinor:0},DISPLAY_200x228:{platforms:["emery"],minFwMajor:0,minFwMinor:0}},e.exports.includesCapability=function(t,n){var r=/^NOT_/,i=[];if(!n||!n.length)return!0;for(var o=n.length-1;o>=0;o--){var a=n[o],u=e.exports.capabilityMap[a.replace(r,"")];!u||u.platforms.indexOf(t.platform)===-1||u.minFwMajor>t.firmware.major||u.minFwMajor===t.firmware.major&&u.minFwMinor>t.firmware.minor?i.push(!!a.match(r)):i.push(!a.match(r))}return i.indexOf(!1)===-1}},{}],8:[function(t,e,n){e.exports=function(){function t(t){return t.substr(0,3)}function e(t){return t!=lt?""+t:""}function n(t,e){return typeof t==e}function r(t){return n(t,"string")}function i(t){return!!t&&n(t,"object")}function o(t){return t&&t.nodeType}function a(t){return n(t,"number")}function u(t){return i(t)&&!!t.getDay}function s(t){return t===!0||t===!1}function c(t){var e=typeof t;return"object"==e?!(!t||!t.getDay):"string"==e||"number"==e||s(t)}function f(t){return t}function l(t,n,r){return e(t).replace(n,r!=lt?r:"")}function h(t){return l(t,/^\\s+|\\s+$/g)}function m(t,e,n){for(var r in t)t.hasOwnProperty(r)&&e.call(n||t,r,t[r]);return t}function p(t,e,n){if(t)for(var r=0;r<t.length;r++)e.call(n||t,t[r],r);return t}function d(t,e,n){var r=[],i=B(e)?e:function(t){return e!=t};return p(t,function(e,o){i.call(n||t,e,o)&&r.push(e)}),r}function g(t,e,n,r){var i=[];return t(e,function(t,o){P(t=n.call(r||e,t,o))?p(t,function(t){i.push(t)}):t!=lt&&i.push(t)}),i}function v(t){var e=0;return m(t,function(t){e++}),e}function y(t){var e=[];return m(t,function(t){e.push(t)}),e}function b(t,e,n){var r=[];return p(t,function(i,o){r.push(e.call(n||t,i,o))}),r}function w(t,e){var n={};return p(t,function(t,r){n[t]=e}),n}function $(t,e){var n=e||{};for(var r in t)n[r]=t[r];return n}function T(t,e){for(var n=e,r=0;r<t.length;r++)n=$(t[r],n);return n}function M(t){return B(t)?t:function(e,n){if(t===e)return n}}function E(t,e,n){return e==lt?n:e<0?Math.max(t.length+e,0):Math.min(t.length,e)}function F(t,e,n,r){for(var i,o=M(e),a=E(t,r,t.length),u=E(t,n,0);u<a;u++)if((i=o.call(t,t[u],u))!=lt)return i}function x(t,e,n){var r=[];if(t)for(var i=E(t,n,t.length),o=E(t,e,0);o<i;o++)r.push(t[o]);return r}function O(t){return b(t,f)}function j(t,e){var n,r=B(t)?t():t,i=B(e)?e():e;return r==i||r!=lt&&i!=lt&&(c(r)||c(i)?u(r)&&u(i)&&+r==+i:P(r)?r.length==i.length&&!F(r,function(t,e){if(!j(t,i[e]))return!0}):!P(i)&&(n=y(r)).length==v(i)&&!F(n,function(t){if(!j(r[t],i[t]))return!0}))}function A(t,e,n){if(B(t))return t.apply(n&&e,b(n||e,f))}function R(t,e,n){return b(t,function(t){return A(t,e,n)})}function L(t){return"\\\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)}function S(t){return l(t,/[\\x00-\\x1f\'"\\u2028\\u2029]/g,L)}function _(t,e){return t.split(e)}function C(t,e){if(dt[t])return dt[t];var n="with(_.isObject(obj)?obj:{}){"+b(_(t,/{{|}}}?/g),function(t,e){var n,r=h(t),i=l(r,/^{/),o=r==i?"esc(":"";return e%2?(n=/^each\\b(\\s+([\\w_]+(\\s*,\\s*[\\w_]+)?)\\s*:)?(.*)/.exec(i))?"each("+(h(n[4])?n[4]:"this")+", function("+n[2]+"){":(n=/^if\\b(.*)/.exec(i))?"if("+n[1]+"){":(n=/^else\\b\\s*(if\\b(.*))?/.exec(i))?"}else "+(n[1]?"if("+n[2]+")":"")+"{":(n=/^\\/(if)?/.exec(i))?n[1]?"}\\n":"});\\n":(n=/^(var\\s.*)/.exec(i))?n[1]+";":(n=/^#(.*)/.exec(i))?n[1]:(n=/(.*)::\\s*(.*)/.exec(i))?"print("+o+\'_.formatValue("\'+S(n[2])+\'",\'+(h(n[1])?n[1]:"this")+(o&&")")+"));\\n":"print("+o+(h(i)?i:"this")+(o&&")")+");\\n":t?\'print("\'+S(t)+\'");\\n\':void 0}).join("")+"}",r=new Function("obj","each","esc","print","_",n),i=function(t,n){var i=[];return r.call(n||t,t,function(t,e){P(t)?p(t,function(t,n){e.call(t,t,n)}):m(t,function(t,n){e.call(n,t,n)})},e||f,function(){A(i.push,i,arguments)},rt),i.join("")};return gt.push(i)>pt&&delete dt[gt.shift()],dt[t]=i}function I(t){return l(t,/[<>\'"&]/g,function(t){return"&#"+t.charCodeAt(0)+";"})}function N(t,e){return C(t,I)(e)}function D(t){return function(e,n,r){return t(this,e,n,r)}}function B(t){return"function"==typeof t&&!t.item}function P(t){return t&&t.length!=lt&&!r(t)&&!o(t)&&!B(t)&&t!==ot}function H(t){return parseFloat(l(t,/^[^\\d-]+/))}function k(t){return t[at]=t[at]||++ct}function q(t,e){var n,r=[],i={};return Q(t,function(t){Q(e(t),function(t){i[n=k(t)]||(r.push(t),i[n]=!0)})}),r}function U(t,e){var n={$position:"absolute",$visibility:"hidden",$display:"block",$height:lt},r=t.get(n),i=t.set(n).get("clientHeight");return t.set(r),i*e+"px"}function Y(t,n,i,o,a){return B(n)?this.on(lt,t,n,i,o):r(o)?this.on(t,n,i,lt,o):this.each(function(r,u){Q(t?G(t,r):r,function(t){Q(e(n).split(/\\s/),function(e){function n(e,n,r){var f=!a,l=a?r:t;if(a)for(var h=Z(a,t);l&&l!=t&&!(f=h(l));)l=l.parentNode;return!f||s!=e||i.apply(X(l),o||[n,u])&&"?"==c||"|"==c}function r(t){n(s,t,t.target)||(t.preventDefault(),t.stopPropagation())}var s=l(e,/[?|]/g),c=l(e,/[^?|]/g),h=("blur"==s||"focus"==s)&&!!a,m=ct++;t.addEventListener(s,r,h),t.M||(t.M={}),t.M[m]=n,i.M=g(Q,[i.M,function(){t.removeEventListener(s,r,h),delete t.M[m]}],f)})})})}function K(t){R(t.M),t.M=lt}function V(t){ft?ft.push(t):setTimeout(t,0)}function z(t,e,n){return G(t,e,n)[0]}function W(t,e,n){var r=X(document.createElement(t));return P(e)||e!=lt&&!i(e)?r.add(e):r.set(e).add(n)}function J(t){return g(Q,t,function(t){var e;return P(t)?J(t):o(t)?(e=t.cloneNode(!0),e.removeAttribute&&e.removeAttribute("id"),e):t})}function X(t,e,n){return B(t)?V(t):new nt(G(t,e,n))}function G(t,e,n){function i(t){return P(t)?g(Q,t,i):t}function a(t){return d(g(Q,t,i),function(t){for(var r=t;r=r.parentNode;)if(r==e[0]||n)return r==e[0]})}return e?1!=(e=G(e)).length?q(e,function(e){return G(t,e,n)}):r(t)?1!=o(e[0])?[]:n?a(e[0].querySelectorAll(t)):e[0].querySelectorAll(t):a(t):r(t)?document.querySelectorAll(t):g(Q,t,i)}function Z(t,e){function n(t,e){var n=RegExp("(^|\\\\s+)"+t+"(?=$|\\\\s)","i");return function(r){return!t||n.test(r[e])}}var i={},u=i;if(B(t))return t;if(a(t))return function(e,n){return n==t};if(!t||"*"==t||r(t)&&(u=/^([\\w-]*)\\.?([\\w-]*)$/.exec(t))){var s=n(u[1],"tagName"),c=n(u[2],"className");return function(t){return 1==o(t)&&s(t)&&c(t)}}return e?function(n){return X(t,e).find(n)!=lt}:(X(t).each(function(t){i[k(t)]=!0}),function(t){return i[k(t)]})}function Q(t,e){return P(t)?p(t,e):t!=lt&&e(t,0),t}function tt(){this.state=null,this.values=[],this.parent=null}function et(){var t=[],e=arguments,n=e.length,r=0,o=0,a=new tt;a.errHandled=function(){o++,a.parent&&a.parent.errHandled()};var u=a.fire=function(e,n){return null==a.state&&null!=e&&(a.state=!!e,a.values=P(n)?n:[n],setTimeout(function(){p(t,function(t){t()})},0)),a};p(e,function c(t,e){try{t.then?t.then(function(t){var o;(i(t)||B(t))&&B(o=t.then)?c(t,e):(a.values[e]=O(arguments),++r==n&&u(!0,n<2?a.values[e]:a.values))},function(t){a.values[e]=O(arguments),u(!1,n<2?a.values[e]:[a.values[e][0],a.values,e])}):t(function(){u(!0,O(arguments))},function(){u(!1,O(arguments))})}catch(o){u(!1,[o,a.values,e])}}),a.stop=function(){return p(e,function(t){t.stop&&t.stop()}),a.stop0&&A(a.stop0)};var s=a.then=function(e,n){var r=et(),u=function(){try{var t=a.state?e:n;B(t)?!function s(t){try{var e,n=0;if((i(t)||B(t))&&B(e=t.then)){if(t===r)throw new TypeError;e.call(t,function(t){n++||s(t)},function(t){n++||r.fire(!1,[t])}),r.stop0=t.stop}else r.fire(!0,[t])}catch(a){if(!n++&&(r.fire(!1,[a]),!o))throw a}}(A(t,it,a.values)):r.fire(a.state,a.values)}catch(u){if(r.fire(!1,[u]),!o)throw u}};return B(n)&&a.errHandled(),r.stop0=a.stop,r.parent=a,null!=a.state?setTimeout(u,0):t.push(u),r};return a.always=function(t){return s(t,t)},a.error=function(t){return s(0,t)},a}function nt(t,e){var n=this,r=0;if(t)for(var i=0,o=t.length;i<o;i++){var a=t[i];if(e&&P(a))for(var u=0,s=a.length;u<s;u++)n[r++]=a[u];else n[r++]=a}else n[r++]=e;n.length=r,n._=!0}function rt(){return new nt(arguments,(!0))}var it,ot=window,at="Nia",ut={},st={},ct=1,ft=/^[ic]/.test(document.readyState)?lt:[],lt=null,ht=_("January,February,March,April,May,June,July,August,September,October,November,December",/,/g),mt=(b(ht,t),_("Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",/,/g)),pt=(b(mt,t),_("am,pm",/,/g),_("am,am,am,am,am,am,am,am,am,am,am,am,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm",/,/g),99),dt={},gt=[];return $({each:D(p),equals:D(j),find:D(F),dummySort:0,select:function(t,e){return X(t,this,e)},get:function(t,e){var n=this,i=n[0];if(i){if(r(t)){var o,a=/^(\\W*)(.*)/.exec(l(t,/^%/,"@data-")),u=a[1];return o=st[u]?st[u](this,a[2]):"$"==t?n.get("className"):"$$"==t?n.get("@style"):"$$slide"==t?n.get("$height"):"$$fade"==t||"$$show"==t?"hidden"==n.get("$visibility")||"none"==n.get("$display")?0:"$$fade"==t?isNaN(n.get("$opacity",!0))?1:n.get("$opacity",!0):1:"$"==u?ot.getComputedStyle(i,lt).getPropertyValue(l(a[2],/[A-Z]/g,function(t){return"-"+t.toLowerCase()})):"@"==u?i.getAttribute(a[2]):i[a[2]],e?H(o):o}var s={};return(P(t)?Q:m)(t,function(t){s[t]=n.get(t,e)}),s}},set:function(t,e){var n=this;if(e!==it){var i=/^(\\W*)(.*)/.exec(l(l(t,/^\\$float$/,"cssFloat"),/^%/,"@data-")),o=i[1];ut[o]?ut[o](this,i[2],e):"$$fade"==t?this.set({$visibility:e?"visible":"hidden",$opacity:e}):"$$slide"==t?n.set({$visibility:e?"visible":"hidden",$overflow:"hidden",$height:/px/.test(e)?e:function(t,n,r){return U(X(r),e)}}):"$$show"==t?e?n.set({$visibility:e?"visible":"hidden",$display:""}).set({$display:function(t){return"none"==t?"block":t}}):n.set({$display:"none"}):"$$"==t?n.set("@style",e):Q(this,function(n,r){var a=B(e)?e(X(n).get(t),r,n):e;"$"==o?i[2]?n.style[i[2]]=a:Q(a&&a.split(/\\s+/),function(t){var e=l(t,/^[+-]/);/^\\+/.test(t)?n.classList.add(e):/^-/.test(t)?n.classList.remove(e):n.classList.toggle(e)}):"$$scrollX"==t?n.scroll(a,X(n).get("$$scrollY")):"$$scrollY"==t?n.scroll(X(n).get("$$scrollX"),a):"@"==o?a==lt?n.removeAttribute(i[2]):n.setAttribute(i[2],a):n[i[2]]=a})}else r(t)||B(t)?n.set("$",t):m(t,function(t,e){n.set(t,e)});return n},add:function(t,e){return this.each(function(n,r){function i(t){if(P(t))Q(t,i);else if(B(t))i(t(n,r));else if(t!=lt){var u=o(t)?t:document.createTextNode(t);a?a.parentNode.insertBefore(u,a.nextSibling):e?e(u,n,n.parentNode):n.appendChild(u),a=u}}var a;i(r&&!B(t)?J(t):t)})},on:Y,trigger:function(t,e){return this.each(function(n,r){for(var i=!0,o=n;o&&i;)m(o.M,function(r,o){i=i&&o(t,e,n)}),o=o.parentNode})},ht:function(t,e){var n=arguments.length>2?T(x(arguments,1)):e;return this.set("innerHTML",B(t)?t(n):/{{/.test(t)?N(t,n):/^#\\S+$/.test(t)?N(z(t).text,n):t)}},nt.prototype),$({request:function(t,n,r,i){var o,a=i||{},u=0,s=et(),c=r&&r.constructor==a.constructor;try{s.xhr=o=new XMLHttpRequest,s.stop0=function(){o.abort()},c&&(r=g(m,r,function(t,e){return g(Q,e,function(e){return encodeURIComponent(t)+(e!=lt?"="+encodeURIComponent(e):"")})}).join("&")),r==lt||/post/i.test(t)||(n+="?"+r,r=lt),o.open(t,n,!0,a.user,a.pass),c&&/post/i.test(t)&&o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),m(a.headers,function(t,e){o.setRequestHeader(t,e)}),m(a.xhr,function(t,e){o[t]=e}),o.onreadystatechange=function(){4!=o.readyState||u++||(o.status>=200&&o.status<300?s.fire(!0,[o.responseText,o]):s.fire(!1,[o.status,o.responseText,o]))},o.send(r)}catch(f){u||s.fire(!1,[0,lt,e(f)])}return s},ready:V,off:K,wait:function(t,e){var n=et(),r=setTimeout(function(){n.fire(!0,e)},t);return n.stop0=function(){n.fire(!1),clearTimeout(r)},n}},X),$({each:p,toObject:w,find:F,equals:j,copyObj:$,extend:function(t){return T(x(arguments,1),t)},eachObj:m,isObject:i,format:function(t,e,n){return C(t,n)(e)},template:C,formatHtml:N,promise:et},rt),document.addEventListener("DOMContentLoaded",function(){R(ft),ft=lt},!1),{HTML:function(){var t=W("div");return rt(A(t.ht,t,arguments)[0].childNodes)},_:rt,$:X,$$:z,M:nt,getter:st,setter:ut}}()},{}]},{},[1])</script></body></html>';
15
+},{}],"pebble-clay":[function(t,e,n){"use strict";function r(t,e,n){function r(){i.meta={activeWatchInfo:Pebble.getActiveWatchInfo&&Pebble.getActiveWatchInfo(),accountToken:Pebble.getAccountToken(),watchToken:Pebble.getWatchToken(),userData:s(n.userData||{})}}function o(t,e,n){Array.isArray(t)?t.forEach(function(t){o(t,e,n)}):"section"===t.type?o(t.items,e,n):e(t)&&n(t)}var i=this;if(!Array.isArray(t))throw new Error("config must be an Array");if(e&&"function"!=typeof e)throw new Error('customFn must be a function or "null"');n=n||{},i.config=s(t),i.customFn=e||function(){},i.components={},i.meta={activeWatchInfo:null,accountToken:"",watchToken:"",userData:{}},i.version=c,n.autoHandleEvents!==!1&&"undefined"!=typeof Pebble?(Pebble.addEventListener("showConfiguration",function(){r(),Pebble.openURL(i.generateUrl())}),Pebble.addEventListener("webviewclosed",function(t){t&&t.response&&Pebble.sendAppMessage(i.getSettings(t.response),function(){console.log("Sent config data to Pebble")},function(t){console.log("Failed to send config data!"),console.log(JSON.stringify(t))})})):"undefined"!=typeof Pebble&&Pebble.addEventListener("ready",function(){r()}),o(i.config,function(t){return a[t.type]},function(t){i.registerComponent(a[t.type])}),o(i.config,function(t){return t.appKey},function(){throw new Error("appKeys are no longer supported. Please follow the migration guide to upgrade your project")})}var o=t("./tmp/config-page.html"),i=t("tosource"),a=t("./src/scripts/components"),s=t("deepcopy/build/deepcopy.min"),c=t("./package.json").version,l=t("message_keys");r.prototype.registerComponent=function(t){this.components[t.name]=t},r.prototype.generateUrl=function(){var t={},e=!Pebble||"pypkjs"===Pebble.platform,n=e?"$$$RETURN_TO$$$":"pebblejs://close#";try{t=JSON.parse(localStorage.getItem("clay-settings"))||{}}catch(a){console.error(a.toString())}var s=o.replace("$$RETURN_TO$$",n).replace("$$CUSTOM_FN$$",i(this.customFn)).replace("$$CONFIG$$",i(this.config)).replace("$$SETTINGS$$",i(t)).replace("$$COMPONENTS$$",i(this.components)).replace("$$META$$",i(this.meta));return e?r.encodeDataUri(s,"http://clay.pebble.com.s3-website-us-west-2.amazonaws.com/#"):r.encodeDataUri(s)},r.prototype.getSettings=function(t,e){var n={};t=t.match(/^\{/)?t:decodeURIComponent(t);try{n=JSON.parse(t)}catch(o){throw new Error("The provided response was not valid JSON")}var i={};return Object.keys(n).forEach(function(t){"object"==typeof n[t]&&n[t]?i[t]=n[t].value:i[t]=n[t]}),localStorage.setItem("clay-settings",JSON.stringify(i)),e===!1?n:r.prepareSettingsForAppMessage(n)},r.prototype.setSettings=function(t,e){var n={};try{n=JSON.parse(localStorage.getItem("clay-settings"))||{}}catch(r){console.error(r.toString())}if("object"==typeof t){var o=t;Object.keys(o).forEach(function(t){n[t]=o[t]})}else n[t]=e;localStorage.setItem("clay-settings",JSON.stringify(n))},r.encodeDataUri=function(t,e){return e="undefined"!=typeof e?e:"data:text/html;charset=utf-8,",e+encodeURIComponent(t)},r.prepareForAppMessage=function(t){function e(t,e){return Math.floor(t*Math.pow(10,e||0))}var n;return Array.isArray(t)?(n=[],t.forEach(function(t,e){n[e]=r.prepareForAppMessage(t)})):n="object"==typeof t&&t?"number"==typeof t.value?e(t.value,t.precision):Array.isArray(t.value)?t.value.map(function(n){return"number"==typeof n?e(n,t.precision):n}):r.prepareForAppMessage(t.value):"boolean"==typeof t?t?1:0:t,n},r.prepareSettingsForAppMessage=function(t){var e={};Object.keys(t).forEach(function(n){var r=t[n],o=n.match(/(.+?)(?:\[(\d*)\])?$/);if(!o[2])return void(e[n]=r);var i=parseInt(o[2],10);n=o[1],"undefined"==typeof e[n]&&(e[n]=[]),e[n][i]=r});var n={};return Object.keys(e).forEach(function(t){var o=l[t],i=r.prepareForAppMessage(e[t]);i=Array.isArray(i)?i:[i],i.forEach(function(t,e){n[o+e]=t})}),Object.keys(n).forEach(function(t){if(Array.isArray(n[t]))throw new Error('Clay does not support 2 dimensional arrays for item values. Make sure you are not attempting to use array syntax (eg: "myMessageKey[2]") in the messageKey for components that return an array, such as a checkboxgroup')}),n},e.exports=r},{"./package.json":7,"./src/scripts/components":13,"./tmp/config-page.html":42,"deepcopy/build/deepcopy.min":3,message_keys:void 0,tosource:6}]},{},["pebble-clay"])("pebble-clay")});
0 16
\ No newline at end of file
1 17
new file mode 100644
... ...
@@ -0,0 +1,379 @@
1
+'use strict';
2
+
3
+var configPageHtml = require('./tmp/config-page.html');
4
+var toSource = require('tosource');
5
+var standardComponents = require('./src/scripts/components');
6
+var deepcopy = require('deepcopy/build/deepcopy.min');
7
+var version = require('./package.json').version;
8
+var messageKeys = require('message_keys');
9
+
10
+/**
11
+ * @param {Array} config - the Clay config
12
+ * @param {function} [customFn] - Custom code to run from the config page. Will run
13
+ *   with the ClayConfig instance as context
14
+ * @param {Object} [options] - Additional options to pass to Clay
15
+ * @param {boolean} [options.autoHandleEvents=true] - If false, Clay will not
16
+ *   automatically handle the 'showConfiguration' and 'webviewclosed' events
17
+ * @param {*} [options.userData={}] - Arbitrary data to pass to the config page. Will
18
+ *   be available as `clayConfig.meta.userData`
19
+ * @constructor
20
+ */
21
+function Clay(config, customFn, options) {
22
+  var self = this;
23
+
24
+  if (!Array.isArray(config)) {
25
+    throw new Error('config must be an Array');
26
+  }
27
+
28
+  if (customFn && typeof customFn !== 'function') {
29
+    throw new Error('customFn must be a function or "null"');
30
+  }
31
+
32
+  options = options || {};
33
+
34
+  self.config = deepcopy(config);
35
+  self.customFn = customFn || function() {};
36
+  self.components = {};
37
+  self.meta = {
38
+    activeWatchInfo: null,
39
+    accountToken: '',
40
+    watchToken: '',
41
+    userData: {}
42
+  };
43
+  self.version = version;
44
+
45
+  /**
46
+   * Populate the meta with data from the Pebble object. Make sure to run this inside
47
+   * either the "showConfiguration" or "ready" event handler
48
+   * @return {void}
49
+   */
50
+  function _populateMeta() {
51
+    self.meta = {
52
+      activeWatchInfo: Pebble.getActiveWatchInfo && Pebble.getActiveWatchInfo(),
53
+      accountToken: Pebble.getAccountToken(),
54
+      watchToken: Pebble.getWatchToken(),
55
+      userData: deepcopy(options.userData || {})
56
+    };
57
+  }
58
+
59
+  // Let Clay handle all the magic
60
+  if (options.autoHandleEvents !== false && typeof Pebble !== 'undefined') {
61
+
62
+    Pebble.addEventListener('showConfiguration', function() {
63
+      _populateMeta();
64
+      Pebble.openURL(self.generateUrl());
65
+    });
66
+
67
+    Pebble.addEventListener('webviewclosed', function(e) {
68
+
69
+      if (!e || !e.response) { return; }
70
+
71
+      // Send settings to Pebble watchapp
72
+      Pebble.sendAppMessage(self.getSettings(e.response), function() {
73
+        console.log('Sent config data to Pebble');
74
+      }, function(error) {
75
+        console.log('Failed to send config data!');
76
+        console.log(JSON.stringify(error));
77
+      });
78
+    });
79
+  } else if (typeof Pebble !== 'undefined') {
80
+    Pebble.addEventListener('ready', function() {
81
+      _populateMeta();
82
+    });
83
+  }
84
+
85
+  /**
86
+   * If this function returns true then the callback will be executed
87
+   * @callback _scanConfig_testFn
88
+   * @param {Clay~ConfigItem} item
89
+   */
90
+
91
+  /**
92
+   * @callback _scanConfig_callback
93
+   * @param {Clay~ConfigItem} item
94
+   */
95
+
96
+  /**
97
+   * Scan over the config and run the callback if the testFn resolves to true
98
+   * @private
99
+   * @param {Clay~ConfigItem|Array} item
100
+   * @param {_scanConfig_testFn} testFn
101
+   * @param {_scanConfig_callback} callback
102
+   * @return {void}
103
+   */
104
+  function _scanConfig(item, testFn, callback) {
105
+    if (Array.isArray(item)) {
106
+      item.forEach(function(item) {
107
+        _scanConfig(item, testFn, callback);
108
+      });
109
+    } else if (item.type === 'section') {
110
+      _scanConfig(item.items, testFn, callback);
111
+    } else if (testFn(item)) {
112
+      callback(item);
113
+    }
114
+  }
115
+
116
+  // register standard components
117
+  _scanConfig(self.config, function(item) {
118
+    return standardComponents[item.type];
119
+  }, function(item) {
120
+    self.registerComponent(standardComponents[item.type]);
121
+  });
122
+
123
+  // validate config against teh use of appKeys
124
+  _scanConfig(self.config, function(item) {
125
+    return item.appKey;
126
+  }, function() {
127
+    throw new Error('appKeys are no longer supported. ' +
128
+                    'Please follow the migration guide to upgrade your project');
129
+  });
130
+}
131
+
132
+/**
133
+ * Register a component to Clay.
134
+ * @param {Object} component - the clay component to register
135
+ * @param {string} component.name - the name of the component
136
+ * @param {string} component.template - HTML template to use for the component
137
+ * @param {string|Object} component.manipulator - methods to attach to the component
138
+ * @param {function} component.manipulator.set - set manipulator method
139
+ * @param {function} component.manipulator.get - get manipulator method
140
+ * @param {Object} [component.defaults] - template defaults
141
+ * @param {function} [component.initialize] - method to scaffold the component
142
+ * @return {boolean} - Returns true if component was registered correctly
143
+ */
144
+Clay.prototype.registerComponent = function(component) {
145
+  this.components[component.name] = component;
146
+};
147
+
148
+/**
149
+ * Generate the Data URI used by the config Page with settings injected
150
+ * @return {string}
151
+ */
152
+Clay.prototype.generateUrl = function() {
153
+  var settings = {};
154
+  var emulator = !Pebble || Pebble.platform === 'pypkjs';
155
+  var returnTo = emulator ? '$$$RETURN_TO$$$' : 'pebblejs://close#';
156
+
157
+  try {
158
+    settings = JSON.parse(localStorage.getItem('clay-settings')) || {};
159
+  } catch (e) {
160
+    console.error(e.toString());
161
+  }
162
+
163
+  var compiledHtml = configPageHtml
164
+    .replace('$$RETURN_TO$$', returnTo)
165
+    .replace('$$CUSTOM_FN$$', toSource(this.customFn))
166
+    .replace('$$CONFIG$$', toSource(this.config))
167
+    .replace('$$SETTINGS$$', toSource(settings))
168
+    .replace('$$COMPONENTS$$', toSource(this.components))
169
+    .replace('$$META$$', toSource(this.meta));
170
+
171
+  // if we are in the emulator then we need to proxy the data via a webpage to
172
+  // obtain the return_to.
173
+  // @todo calculate this from the Pebble object or something
174
+  if (emulator) {
175
+    return Clay.encodeDataUri(
176
+      compiledHtml,
177
+      'http://clay.pebble.com.s3-website-us-west-2.amazonaws.com/#'
178
+    );
179
+  }
180
+
181
+  return Clay.encodeDataUri(compiledHtml);
182
+};
183
+
184
+/**
185
+ * Parse the response from the webviewclosed event data
186
+ * @param {string} response
187
+ * @param {boolean} [convert=true]
188
+ * @returns {Object}
189
+ */
190
+Clay.prototype.getSettings = function(response, convert) {
191
+  // Decode and parse config data as JSON
192
+  var settings = {};
193
+  response = response.match(/^\{/) ? response : decodeURIComponent(response);
194
+
195
+  try {
196
+    settings = JSON.parse(response);
197
+  } catch (e) {
198
+    throw new Error('The provided response was not valid JSON');
199
+  }
200
+
201
+  // flatten the settings for localStorage
202
+  var settingsStorage = {};
203
+  Object.keys(settings).forEach(function(key) {
204
+    if (typeof settings[key] === 'object' && settings[key]) {
205
+      settingsStorage[key] = settings[key].value;
206
+    } else {
207
+      settingsStorage[key] = settings[key];
208
+    }
209
+  });
210
+
211
+  localStorage.setItem('clay-settings', JSON.stringify(settingsStorage));
212
+
213
+  return convert === false ? settings : Clay.prepareSettingsForAppMessage(settings);
214
+};
215
+
216
+/**
217
+ * Updates the settings with the given value(s).
218
+ *
219
+ * @signature `clay.setSettings(key, value)`
220
+ * @param {String} key - The property to set.
221
+ * @param {*} value - the value assigned to _key_.
222
+ * @return {undefined}
223
+ *
224
+ * @signature `clay.setSettings(settings)`
225
+ * @param {Object} settings - an object containing the key/value pairs to be set.
226
+ * @return {undefined}
227
+ */
228
+Clay.prototype.setSettings = function(key, value) {
229
+  var settingsStorage = {};
230
+
231
+  try {
232
+    settingsStorage = JSON.parse(localStorage.getItem('clay-settings')) || {};
233
+  } catch (e) {
234
+    console.error(e.toString());
235
+  }
236
+
237
+  if (typeof key === 'object') {
238
+    var settings = key;
239
+    Object.keys(settings).forEach(function(key) {
240
+      settingsStorage[key] = settings[key];
241
+    });
242
+  } else {
243
+    settingsStorage[key] = value;
244
+  }
245
+
246
+  localStorage.setItem('clay-settings', JSON.stringify(settingsStorage));
247
+};
248
+
249
+/**
250
+ * @param {string} input
251
+ * @param {string} [prefix='data:text/html;charset=utf-8,']
252
+ * @returns {string}
253
+ */
254
+Clay.encodeDataUri = function(input, prefix) {
255
+  prefix = typeof prefix !== 'undefined' ? prefix : 'data:text/html;charset=utf-8,';
256
+  return prefix + encodeURIComponent(input);
257
+};
258
+
259
+/**
260
+ * Converts the val into a type compatible with Pebble.sendAppMessage().
261
+ *  - Strings will be returned without modification
262
+ *  - Numbers will be returned without modification
263
+ *  - Booleans will be converted to a 0 or 1
264
+ *  - Arrays that contain strings will be returned without modification
265
+ *    eg: ['one', 'two'] becomes ['one', 'two']
266
+ *  - Arrays that contain numbers will be returned without modification
267
+ *    eg: [1, 2] becomes [1, 2]
268
+ *  - Arrays that contain booleans will be converted to a 0 or 1
269
+ *    eg: [true, false] becomes [1, 0]
270
+ *  - Arrays must be single dimensional
271
+ *  - Objects that have a "value" property will apply the above rules to the type of
272
+ *    value. If the value is a number or an array of numbers and the optional
273
+ *    property: "precision" is provided, then the number will be multiplied by 10 to
274
+ *    the power of precision (value * 10 ^ precision) and then floored.
275
+ *    Eg: 1.4567 with a precision set to 3 will become 1456
276
+ * @param {number|string|boolean|Array|Object} val
277
+ * @param {number|string|boolean|Array} val.value
278
+ * @param {number|undefined} [val.precision=0]
279
+ * @returns {number|string|Array}
280
+ */
281
+Clay.prepareForAppMessage = function(val) {
282
+
283
+  /**
284
+   * moves the decimal place of a number by precision then drop any remaining decimal
285
+   * places.
286
+   * @param {number} number
287
+   * @param {number} precision - number of decimal places to move
288
+   * @returns {number}
289
+   * @private
290
+   */
291
+  function _normalizeToPrecision(number, precision) {
292
+    return Math.floor(number * Math.pow(10, precision || 0));
293
+  }
294
+
295
+  var result;
296
+
297
+  if (Array.isArray(val)) {
298
+    result = [];
299
+    val.forEach(function(item, index) {
300
+      result[index] = Clay.prepareForAppMessage(item);
301
+    });
302
+  } else if (typeof val === 'object' && val) {
303
+    if (typeof val.value === 'number') {
304
+      result = _normalizeToPrecision(val.value, val.precision);
305
+    } else if (Array.isArray(val.value)) {
306
+      result = val.value.map(function(item) {
307
+        if (typeof item === 'number') {
308
+          return _normalizeToPrecision(item, val.precision);
309
+        }
310
+        return item;
311
+      });
312
+    } else {
313
+      result = Clay.prepareForAppMessage(val.value);
314
+    }
315
+  } else if (typeof val === 'boolean') {
316
+    result = val ? 1 : 0;
317
+  } else {
318
+    result = val;
319
+  }
320
+
321
+  return result;
322
+};
323
+
324
+/**
325
+ * Converts a Clay settings dict into one that is compatible with
326
+ * Pebble.sendAppMessage(); It also uses the provided messageKeys to correctly
327
+ * assign arrays into individual keys
328
+ * @see {prepareForAppMessage}
329
+ * @param {Object} settings
330
+ * @returns {{}}
331
+ */
332
+Clay.prepareSettingsForAppMessage = function(settings) {
333
+
334
+  // flatten settings
335
+  var flatSettings = {};
336
+  Object.keys(settings).forEach(function(key) {
337
+    var val = settings[key];
338
+    var matches = key.match(/(.+?)(?:\[(\d*)\])?$/);
339
+
340
+    if (!matches[2]) {
341
+      flatSettings[key] = val;
342
+      return;
343
+    }
344
+
345
+    var position = parseInt(matches[2], 10);
346
+    key = matches[1];
347
+
348
+    if (typeof flatSettings[key] === 'undefined') {
349
+      flatSettings[key] = [];
350
+    }
351
+
352
+    flatSettings[key][position] = val;
353
+  });
354
+
355
+  var result = {};
356
+  Object.keys(flatSettings).forEach(function(key) {
357
+    var messageKey = messageKeys[key];
358
+    var settingArr = Clay.prepareForAppMessage(flatSettings[key]);
359
+    settingArr = Array.isArray(settingArr) ? settingArr : [settingArr];
360
+
361
+    settingArr.forEach(function(setting, index) {
362
+      result[messageKey + index] = setting;
363
+    });
364
+  });
365
+
366
+  // validate the settings
367
+  Object.keys(result).forEach(function(key) {
368
+    if (Array.isArray(result[key])) {
369
+      throw new Error('Clay does not support 2 dimensional arrays for item ' +
370
+                      'values. Make sure you are not attempting to use array ' +
371
+                      'syntax (eg: "myMessageKey[2]") in the messageKey for ' +
372
+                      'components that return an array, such as a checkboxgroup');
373
+    }
374
+  });
375
+
376
+  return result;
377
+};
378
+
379
+module.exports = Clay;
0 380
new file mode 100644
... ...
@@ -0,0 +1,151 @@
1
+{
2
+  "_args": [
3
+    [
4
+      "pebble-clay@^1.0.0",
5
+      "/mnt/c/Users/louisj/repos/agenda_sommeil"
6
+    ]
7
+  ],
8
+  "_from": "pebble-clay@>=1.0.0 <2.0.0",
9
+  "_id": "pebble-clay@1.0.4",
10
+  "_inCache": true,
11
+  "_installable": true,
12
+  "_location": "/pebble-clay",
13
+  "_nodeVersion": "6.9.1",
14
+  "_npmOperationalInternal": {
15
+    "host": "packages-12-west.internal.npmjs.com",
16
+    "tmp": "tmp/pebble-clay-1.0.4.tgz_1479759281024_0.1520081793423742"
17
+  },
18
+  "_npmUser": {
19
+    "email": "webteam@getpebble.com",
20
+    "name": "pebble-tech"
21
+  },
22
+  "_npmVersion": "3.10.8",
23
+  "_phantomChildren": {},
24
+  "_requested": {
25
+    "name": "pebble-clay",
26
+    "raw": "pebble-clay@^1.0.0",
27
+    "rawSpec": "^1.0.0",
28
+    "scope": null,
29
+    "spec": ">=1.0.0 <2.0.0",
30
+    "type": "range"
31
+  },
32
+  "_requiredBy": [
33
+    "/"
34
+  ],
35
+  "_resolved": "https://registry.npmjs.org/pebble-clay/-/pebble-clay-1.0.4.tgz",
36
+  "_shasum": "fdf92f0fdc770a979c06874eaa2457cc2e762344",
37
+  "_shrinkwrap": null,
38
+  "_spec": "pebble-clay@^1.0.0",
39
+  "_where": "/mnt/c/Users/louisj/repos/agenda_sommeil",
40
+  "author": {
41
+    "name": "Pebble Technology"
42
+  },
43
+  "bugs": {
44
+    "url": "https://github.com/pebble/clay/issues"
45
+  },
46
+  "dependencies": {},
47
+  "description": "Pebble Config Framework",
48
+  "devDependencies": {
49
+    "autoprefixer": "^6.3.1",
50
+    "bourbon": "^4.2.6",
51
+    "browserify": "^13.0.0",
52
+    "browserify-istanbul": "^0.2.1",
53
+    "chai": "^3.4.1",
54
+    "deamdify": "^0.2.0",
55
+    "deepcopy": "^0.6.1",
56
+    "del": "^2.0.2",
57
+    "eslint": "^1.5.1",
58
+    "eslint-config-pebble": "^1.2.0",
59
+    "eslint-plugin-standard": "^1.3.1",
60
+    "gulp": "^3.9.0",
61
+    "gulp-autoprefixer": "^3.1.0",
62
+    "gulp-htmlmin": "^1.3.0",
63
+    "gulp-inline": "0.0.15",
64
+    "gulp-insert": "^0.5.0",
65
+    "gulp-sass": "^2.1.1",
66
+    "gulp-sourcemaps": "^1.6.0",
67
+    "gulp-uglify": "^1.5.2",
68
+    "joi": "^6.10.1",
69
+    "karma": "^0.13.19",
70
+    "karma-browserify": "^5.0.1",
71
+    "karma-chrome-launcher": "^0.2.2",
72
+    "karma-coverage": "^0.5.3",
73
+    "karma-mocha": "^0.2.1",
74
+    "karma-mocha-reporter": "^1.1.5",
75
+    "karma-source-map-support": "^1.1.0",
76
+    "karma-threshold-reporter": "^0.1.15",
77
+    "mocha": "^2.3.4",
78
+    "postcss": "^5.0.14",
79
+    "require-from-string": "^1.1.0",
80
+    "sassify": "^0.9.1",
81
+    "sinon": "^1.17.3",
82
+    "stringify": "^3.2.0",
83
+    "through": "^2.3.8",
84
+    "tosource": "^1.0.0",
85
+    "vinyl-buffer": "^1.0.0",
86
+    "vinyl-source-stream": "^1.1.0",
87
+    "watchify": "^3.7.0"
88
+  },
89
+  "dist": {
90
+    "integrity": "sha512-/rXxmltdW8JyohDzXINdea+d2wnFJVNFiTXfuZsKpySURZSCFMMucX9sZPZvbHnEA4xFINM4iicyhBbvY4ALfw==",
91
+    "shasum": "fdf92f0fdc770a979c06874eaa2457cc2e762344",
92
+    "signatures": [
93
+      {
94
+        "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
95
+        "sig": "MEUCIFA12PX5bVibhTGVMnkJFWBxPBU/x5R6Jz2B7RvpzD2ZAiEA6HfjOjccw0U1kuU5M+yix7faMroR6wImCgOwGEIEN/Q="
96
+      }
97
+    ],
98
+    "tarball": "https://registry.npmjs.org/pebble-clay/-/pebble-clay-1.0.4.tgz"
99
+  },
100
+  "gitHead": "1bf6db08092ab464974d1762a953ea7cbd24efb8",
101
+  "homepage": "https://github.com/pebble/clay#readme",
102
+  "keywords": [
103
+    "config",
104
+    "configuration",
105
+    "pebble",
106
+    "pebble-package"
107
+  ],
108
+  "license": "MIT",
109
+  "maintainers": [
110
+    {
111
+      "name": "pebble-tech",
112
+      "email": "webteam@getpebble.com"
113
+    }
114
+  ],
115
+  "name": "pebble-clay",
116
+  "optionalDependencies": {},
117
+  "pebble": {
118
+    "capabilities": [
119
+      "configurable"
120
+    ],
121
+    "projectType": "package",
122
+    "resources": {
123
+      "media": []
124
+    },
125
+    "sdkVersion": "3",
126
+    "targetPlatforms": [
127
+      "aplite",
128
+      "basalt",
129
+      "chalk",
130
+      "diorite",
131
+      "emery"
132
+    ]
133
+  },
134
+  "readme": "ERROR: No README data found!",
135
+  "repository": {
136
+    "type": "git",
137
+    "url": "git+https://github.com/pebble/clay.git"
138
+  },
139
+  "scripts": {
140
+    "build": "gulp",
141
+    "dev": "gulp dev",
142
+    "lint": "eslint ./",
143
+    "pebble-build": "npm run build && pebble build",
144
+    "pebble-clean": "rm -rf tmp src/js/index.js && pebble clean",
145
+    "pebble-publish": "npm run pebble-clean && npm run build && pebble build && pebble package publish && npm run pebble-clean",
146
+    "test": "gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --single-run",
147
+    "test-debug": "(export DEBUG=true && ./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --no-single-run)",
148
+    "test-travis": "gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --single-run --browsers chromeTravisCI && ./node_modules/.bin/eslint ./"
149
+  },
150
+  "version": "1.0.4"
151
+}
0 152
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+  <head>
4
+    <meta charset="utf-8" />
5
+    <link rel="stylesheet" href="../tmp/config-page.css">
6
+    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
7
+    <script>
8
+      window.returnTo = '$$RETURN_TO$$';
9
+      window.clayConfig = $$CONFIG$$;
10
+      window.claySettings = $$SETTINGS$$;
11
+      window.customFn = $$CUSTOM_FN$$;
12
+      window.clayComponents = $$COMPONENTS$$;
13
+      window.clayMeta = $$META$$;
14
+    </script>
15
+  </head>
16
+  <body>
17
+    <form id="main-form" class="inputs"></form>
18
+    <script src="../tmp/config-page.js"></script>
19
+  </body>
20
+</html>
0 21
new file mode 100644
1 22
Binary files /dev/null and b/node_modules/pebble-clay/src/images/example.png differ
2 23
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+/* Clay - https://github.com/pebble/clay - Version: 1.0.4 - Build Date: 2016-11-21T20:14:28.839Z */
2
+!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.pebbleClay=t()}}(function(){var t;return function e(t,n,r){function o(a,s){if(!n[a]){if(!t[a]){var c="function"==typeof require&&require;if(!s&&c)return c(a,!0);if(i)return i(a,!0);var l=new Error("Cannot find module '"+a+"'");throw l.code="MODULE_NOT_FOUND",l}var u=n[a]={exports:{}};t[a][0].call(u.exports,function(e){var n=t[a][1][e];return o(n?n:e)},u,u.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a<r.length;a++)o(r[a]);return o}({1:[function(t,e,n){"use strict";function r(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");return"="===t[e-2]?2:"="===t[e-1]?1:0}function o(t){return 3*t.length/4-r(t)}function i(t){var e,n,o,i,a,s,c=t.length;a=r(t),s=new f(3*c/4-a),o=a>0?c-4:c;var l=0;for(e=0,n=0;e<o;e+=4,n+=3)i=u[t.charCodeAt(e)]<<18|u[t.charCodeAt(e+1)]<<12|u[t.charCodeAt(e+2)]<<6|u[t.charCodeAt(e+3)],s[l++]=i>>16&255,s[l++]=i>>8&255,s[l++]=255&i;return 2===a?(i=u[t.charCodeAt(e)]<<2|u[t.charCodeAt(e+1)]>>4,s[l++]=255&i):1===a&&(i=u[t.charCodeAt(e)]<<10|u[t.charCodeAt(e+1)]<<4|u[t.charCodeAt(e+2)]>>2,s[l++]=i>>8&255,s[l++]=255&i),s}function a(t){return l[t>>18&63]+l[t>>12&63]+l[t>>6&63]+l[63&t]}function s(t,e,n){for(var r,o=[],i=e;i<n;i+=3)r=(t[i]<<16)+(t[i+1]<<8)+t[i+2],o.push(a(r));return o.join("")}function c(t){for(var e,n=t.length,r=n%3,o="",i=[],a=16383,c=0,u=n-r;c<u;c+=a)i.push(s(t,c,c+a>u?u:c+a));return 1===r?(e=t[n-1],o+=l[e>>2],o+=l[e<<4&63],o+="=="):2===r&&(e=(t[n-2]<<8)+t[n-1],o+=l[e>>10],o+=l[e>>4&63],o+=l[e<<2&63],o+="="),i.push(o),i.join("")}n.byteLength=o,n.toByteArray=i,n.fromByteArray=c;for(var l=[],u=[],f="undefined"!=typeof Uint8Array?Uint8Array:Array,p="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",d=0,h=p.length;d<h;++d)l[d]=p[d],u[p.charCodeAt(d)]=d;u["-".charCodeAt(0)]=62,u["_".charCodeAt(0)]=63},{}],2:[function(t,e,n){(function(e){/*!
3
+ * The buffer module from node.js, for the browser.
4
+ *
5
+ * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
6
+ * @license  MIT
7
+ */
8
+"use strict";function r(){try{var t=new Uint8Array(1);return t.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===t.foo()&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(e){return!1}}function o(){return a.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function i(t,e){if(o()<e)throw new RangeError("Invalid typed array length");return a.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e),t.__proto__=a.prototype):(null===t&&(t=new a(e)),t.length=e),t}function a(t,e,n){if(!(a.TYPED_ARRAY_SUPPORT||this instanceof a))return new a(t,e,n);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return u(this,t)}return s(this,t,e,n)}function s(t,e,n,r){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?d(t,e,n,r):"string"==typeof e?f(t,e,n):h(t,e)}function c(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function l(t,e,n,r){return c(e),e<=0?i(t,e):void 0!==n?"string"==typeof r?i(t,e).fill(n,r):i(t,e).fill(n):i(t,e)}function u(t,e){if(c(e),t=i(t,e<0?0:0|m(e)),!a.TYPED_ARRAY_SUPPORT)for(var n=0;n<e;++n)t[n]=0;return t}function f(t,e,n){if("string"==typeof n&&""!==n||(n="utf8"),!a.isEncoding(n))throw new TypeError('"encoding" must be a valid string encoding');var r=0|b(e,n);t=i(t,r);var o=t.write(e,n);return o!==r&&(t=t.slice(0,o)),t}function p(t,e){var n=e.length<0?0:0|m(e.length);t=i(t,n);for(var r=0;r<n;r+=1)t[r]=255&e[r];return t}function d(t,e,n,r){if(e.byteLength,n<0||e.byteLength<n)throw new RangeError("'offset' is out of bounds");if(e.byteLength<n+(r||0))throw new RangeError("'length' is out of bounds");return e=void 0===n&&void 0===r?new Uint8Array(e):void 0===r?new Uint8Array(e,n):new Uint8Array(e,n,r),a.TYPED_ARRAY_SUPPORT?(t=e,t.__proto__=a.prototype):t=p(t,e),t}function h(t,e){if(a.isBuffer(e)){var n=0|m(e.length);return t=i(t,n),0===t.length?t:(e.copy(t,0,0,n),t)}if(e){if("undefined"!=typeof ArrayBuffer&&e.buffer instanceof ArrayBuffer||"length"in e)return"number"!=typeof e.length||H(e.length)?i(t,0):p(t,e);if("Buffer"===e.type&&_(e.data))return p(t,e.data)}throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}function m(t){if(t>=o())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+o().toString(16)+" bytes");return 0|t}function g(t){return+t!=t&&(t=0),a.alloc(+t)}function b(t,e){if(a.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var n=t.length;if(0===n)return 0;for(var r=!1;;)switch(e){case"ascii":case"latin1":case"binary":return n;case"utf8":case"utf-8":case void 0:return W(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*n;case"hex":return n>>>1;case"base64":return U(t).length;default:if(r)return W(t).length;e=(""+e).toLowerCase(),r=!0}}function y(t,e,n){var r=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===n||n>this.length)&&(n=this.length),n<=0)return"";if(n>>>=0,e>>>=0,n<=e)return"";for(t||(t="utf8");;)switch(t){case"hex":return D(this,e,n);case"utf8":case"utf-8":return E(this,e,n);case"ascii":return B(this,e,n);case"latin1":case"binary":return S(this,e,n);case"base64":return O(this,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,e,n);default:if(r)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),r=!0}}function v(t,e,n){var r=t[e];t[e]=t[n],t[n]=r}function A(t,e,n,r,o){if(0===t.length)return-1;if("string"==typeof n?(r=n,n=0):n>2147483647?n=2147483647:n<-2147483648&&(n=-2147483648),n=+n,isNaN(n)&&(n=o?0:t.length-1),n<0&&(n=t.length+n),n>=t.length){if(o)return-1;n=t.length-1}else if(n<0){if(!o)return-1;n=0}if("string"==typeof e&&(e=a.from(e,r)),a.isBuffer(e))return 0===e.length?-1:w(t,e,n,r,o);if("number"==typeof e)return e=255&e,a.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,e,n):Uint8Array.prototype.lastIndexOf.call(t,e,n):w(t,[e],n,r,o);throw new TypeError("val must be string, number or Buffer")}function w(t,e,n,r,o){function i(t,e){return 1===a?t[e]:t.readUInt16BE(e*a)}var a=1,s=t.length,c=e.length;if(void 0!==r&&(r=String(r).toLowerCase(),"ucs2"===r||"ucs-2"===r||"utf16le"===r||"utf-16le"===r)){if(t.length<2||e.length<2)return-1;a=2,s/=2,c/=2,n/=2}var l;if(o){var u=-1;for(l=n;l<s;l++)if(i(t,l)===i(e,u===-1?0:l-u)){if(u===-1&&(u=l),l-u+1===c)return u*a}else u!==-1&&(l-=l-u),u=-1}else for(n+c>s&&(n=s-c),l=n;l>=0;l--){for(var f=!0,p=0;p<c;p++)if(i(t,l+p)!==i(e,p)){f=!1;break}if(f)return l}return-1}function k(t,e,n,r){n=Number(n)||0;var o=t.length-n;r?(r=Number(r),r>o&&(r=o)):r=o;var i=e.length;if(i%2!==0)throw new TypeError("Invalid hex string");r>i/2&&(r=i/2);for(var a=0;a<r;++a){var s=parseInt(e.substr(2*a,2),16);if(isNaN(s))return a;t[n+a]=s}return a}function x(t,e,n,r){return q(W(e,t.length-n),t,n,r)}function M(t,e,n,r){return q(Z(e),t,n,r)}function T(t,e,n,r){return M(t,e,n,r)}function R(t,e,n,r){return q(U(e),t,n,r)}function P(t,e,n,r){return q(J(e,t.length-n),t,n,r)}function O(t,e,n){return 0===e&&n===t.length?Q.fromByteArray(t):Q.fromByteArray(t.slice(e,n))}function E(t,e,n){n=Math.min(t.length,n);for(var r=[],o=e;o<n;){var i=t[o],a=null,s=i>239?4:i>223?3:i>191?2:1;if(o+s<=n){var c,l,u,f;switch(s){case 1:i<128&&(a=i);break;case 2:c=t[o+1],128===(192&c)&&(f=(31&i)<<6|63&c,f>127&&(a=f));break;case 3:c=t[o+1],l=t[o+2],128===(192&c)&&128===(192&l)&&(f=(15&i)<<12|(63&c)<<6|63&l,f>2047&&(f<55296||f>57343)&&(a=f));break;case 4:c=t[o+1],l=t[o+2],u=t[o+3],128===(192&c)&&128===(192&l)&&128===(192&u)&&(f=(15&i)<<18|(63&c)<<12|(63&l)<<6|63&u,f>65535&&f<1114112&&(a=f))}}null===a?(a=65533,s=1):a>65535&&(a-=65536,r.push(a>>>10&1023|55296),a=56320|1023&a),r.push(a),o+=s}return j(r)}function j(t){var e=t.length;if(e<=tt)return String.fromCharCode.apply(String,t);for(var n="",r=0;r<e;)n+=String.fromCharCode.apply(String,t.slice(r,r+=tt));return n}function B(t,e,n){var r="";n=Math.min(t.length,n);for(var o=e;o<n;++o)r+=String.fromCharCode(127&t[o]);return r}function S(t,e,n){var r="";n=Math.min(t.length,n);for(var o=e;o<n;++o)r+=String.fromCharCode(t[o]);return r}function D(t,e,n){var r=t.length;(!e||e<0)&&(e=0),(!n||n<0||n>r)&&(n=r);for(var o="",i=e;i<n;++i)o+=V(t[i]);return o}function N(t,e,n){for(var r=t.slice(e,n),o="",i=0;i<r.length;i+=2)o+=String.fromCharCode(r[i]+256*r[i+1]);return o}function Y(t,e,n){if(t%1!==0||t<0)throw new RangeError("offset is not uint");if(t+e>n)throw new RangeError("Trying to access beyond buffer length")}function F(t,e,n,r,o,i){if(!a.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||e<i)throw new RangeError('"value" argument is out of bounds');if(n+r>t.length)throw new RangeError("Index out of range")}function z(t,e,n,r){e<0&&(e=65535+e+1);for(var o=0,i=Math.min(t.length-n,2);o<i;++o)t[n+o]=(e&255<<8*(r?o:1-o))>>>8*(r?o:1-o)}function I(t,e,n,r){e<0&&(e=4294967295+e+1);for(var o=0,i=Math.min(t.length-n,4);o<i;++o)t[n+o]=e>>>8*(r?o:3-o)&255}function L(t,e,n,r,o,i){if(n+r>t.length)throw new RangeError("Index out of range");if(n<0)throw new RangeError("Index out of range")}function K(t,e,n,r,o){return o||L(t,e,n,4,3.4028234663852886e38,-3.4028234663852886e38),$.write(t,e,n,r,23,4),n+4}function G(t,e,n,r,o){return o||L(t,e,n,8,1.7976931348623157e308,-1.7976931348623157e308),$.write(t,e,n,r,52,8),n+8}function C(t){if(t=X(t).replace(et,""),t.length<2)return"";for(;t.length%4!==0;)t+="=";return t}function X(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function V(t){return t<16?"0"+t.toString(16):t.toString(16)}function W(t,e){e=e||1/0;for(var n,r=t.length,o=null,i=[],a=0;a<r;++a){if(n=t.charCodeAt(a),n>55295&&n<57344){if(!o){if(n>56319){(e-=3)>-1&&i.push(239,191,189);continue}if(a+1===r){(e-=3)>-1&&i.push(239,191,189);continue}o=n;continue}if(n<56320){(e-=3)>-1&&i.push(239,191,189),o=n;continue}n=(o-55296<<10|n-56320)+65536}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,n<128){if((e-=1)<0)break;i.push(n)}else if(n<2048){if((e-=2)<0)break;i.push(n>>6|192,63&n|128)}else if(n<65536){if((e-=3)<0)break;i.push(n>>12|224,n>>6&63|128,63&n|128)}else{if(!(n<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;i.push(n>>18|240,n>>12&63|128,n>>6&63|128,63&n|128)}}return i}function Z(t){for(var e=[],n=0;n<t.length;++n)e.push(255&t.charCodeAt(n));return e}function J(t,e){for(var n,r,o,i=[],a=0;a<t.length&&!((e-=2)<0);++a)n=t.charCodeAt(a),r=n>>8,o=n%256,i.push(o),i.push(r);return i}function U(t){return Q.toByteArray(C(t))}function q(t,e,n,r){for(var o=0;o<r&&!(o+n>=e.length||o>=t.length);++o)e[o+n]=t[o];return o}function H(t){return t!==t}var Q=t("base64-js"),$=t("ieee754"),_=t("isarray");n.Buffer=a,n.SlowBuffer=g,n.INSPECT_MAX_BYTES=50,a.TYPED_ARRAY_SUPPORT=void 0!==e.TYPED_ARRAY_SUPPORT?e.TYPED_ARRAY_SUPPORT:r(),n.kMaxLength=o(),a.poolSize=8192,a._augment=function(t){return t.__proto__=a.prototype,t},a.from=function(t,e,n){return s(null,t,e,n)},a.TYPED_ARRAY_SUPPORT&&(a.prototype.__proto__=Uint8Array.prototype,a.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&a[Symbol.species]===a&&Object.defineProperty(a,Symbol.species,{value:null,configurable:!0})),a.alloc=function(t,e,n){return l(null,t,e,n)},a.allocUnsafe=function(t){return u(null,t)},a.allocUnsafeSlow=function(t){return u(null,t)},a.isBuffer=function(t){return!(null==t||!t._isBuffer)},a.compare=function(t,e){if(!a.isBuffer(t)||!a.isBuffer(e))throw new TypeError("Arguments must be Buffers");if(t===e)return 0;for(var n=t.length,r=e.length,o=0,i=Math.min(n,r);o<i;++o)if(t[o]!==e[o]){n=t[o],r=e[o];break}return n<r?-1:r<n?1:0},a.isEncoding=function(t){switch(String(t).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},a.concat=function(t,e){if(!_(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return a.alloc(0);var n;if(void 0===e)for(e=0,n=0;n<t.length;++n)e+=t[n].length;var r=a.allocUnsafe(e),o=0;for(n=0;n<t.length;++n){var i=t[n];if(!a.isBuffer(i))throw new TypeError('"list" argument must be an Array of Buffers');i.copy(r,o),o+=i.length}return r},a.byteLength=b,a.prototype._isBuffer=!0,a.prototype.swap16=function(){var t=this.length;if(t%2!==0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var e=0;e<t;e+=2)v(this,e,e+1);return this},a.prototype.swap32=function(){var t=this.length;if(t%4!==0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var e=0;e<t;e+=4)v(this,e,e+3),v(this,e+1,e+2);return this},a.prototype.swap64=function(){var t=this.length;if(t%8!==0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var e=0;e<t;e+=8)v(this,e,e+7),v(this,e+1,e+6),v(this,e+2,e+5),v(this,e+3,e+4);return this},a.prototype.toString=function(){var t=0|this.length;return 0===t?"":0===arguments.length?E(this,0,t):y.apply(this,arguments)},a.prototype.equals=function(t){if(!a.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===a.compare(this,t)},a.prototype.inspect=function(){var t="",e=n.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,e).match(/.{2}/g).join(" "),this.length>e&&(t+=" ... ")),"<Buffer "+t+">"},a.prototype.compare=function(t,e,n,r,o){if(!a.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===n&&(n=t?t.length:0),void 0===r&&(r=0),void 0===o&&(o=this.length),e<0||n>t.length||r<0||o>this.length)throw new RangeError("out of range index");if(r>=o&&e>=n)return 0;if(r>=o)return-1;if(e>=n)return 1;if(e>>>=0,n>>>=0,r>>>=0,o>>>=0,this===t)return 0;for(var i=o-r,s=n-e,c=Math.min(i,s),l=this.slice(r,o),u=t.slice(e,n),f=0;f<c;++f)if(l[f]!==u[f]){i=l[f],s=u[f];break}return i<s?-1:s<i?1:0},a.prototype.includes=function(t,e,n){return this.indexOf(t,e,n)!==-1},a.prototype.indexOf=function(t,e,n){return A(this,t,e,n,!0)},a.prototype.lastIndexOf=function(t,e,n){return A(this,t,e,n,!1)},a.prototype.write=function(t,e,n,r){if(void 0===e)r="utf8",n=this.length,e=0;else if(void 0===n&&"string"==typeof e)r=e,n=this.length,e=0;else{if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e=0|e,isFinite(n)?(n=0|n,void 0===r&&(r="utf8")):(r=n,n=void 0)}var o=this.length-e;if((void 0===n||n>o)&&(n=o),t.length>0&&(n<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");r||(r="utf8");for(var i=!1;;)switch(r){case"hex":return k(this,t,e,n);case"utf8":case"utf-8":return x(this,t,e,n);case"ascii":return M(this,t,e,n);case"latin1":case"binary":return T(this,t,e,n);case"base64":return R(this,t,e,n);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return P(this,t,e,n);default:if(i)throw new TypeError("Unknown encoding: "+r);r=(""+r).toLowerCase(),i=!0}},a.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var tt=4096;a.prototype.slice=function(t,e){var n=this.length;t=~~t,e=void 0===e?n:~~e,t<0?(t+=n,t<0&&(t=0)):t>n&&(t=n),e<0?(e+=n,e<0&&(e=0)):e>n&&(e=n),e<t&&(e=t);var r;if(a.TYPED_ARRAY_SUPPORT)r=this.subarray(t,e),r.__proto__=a.prototype;else{var o=e-t;r=new a(o,(void 0));for(var i=0;i<o;++i)r[i]=this[i+t]}return r},a.prototype.readUIntLE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=this[t],o=1,i=0;++i<e&&(o*=256);)r+=this[t+i]*o;return r},a.prototype.readUIntBE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=this[t+--e],o=1;e>0&&(o*=256);)r+=this[t+--e]*o;return r},a.prototype.readUInt8=function(t,e){return e||Y(t,1,this.length),this[t]},a.prototype.readUInt16LE=function(t,e){return e||Y(t,2,this.length),this[t]|this[t+1]<<8},a.prototype.readUInt16BE=function(t,e){return e||Y(t,2,this.length),this[t]<<8|this[t+1]},a.prototype.readUInt32LE=function(t,e){return e||Y(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},a.prototype.readUInt32BE=function(t,e){return e||Y(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},a.prototype.readIntLE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=this[t],o=1,i=0;++i<e&&(o*=256);)r+=this[t+i]*o;return o*=128,r>=o&&(r-=Math.pow(2,8*e)),r},a.prototype.readIntBE=function(t,e,n){t=0|t,e=0|e,n||Y(t,e,this.length);for(var r=e,o=1,i=this[t+--r];r>0&&(o*=256);)i+=this[t+--r]*o;return o*=128,i>=o&&(i-=Math.pow(2,8*e)),i},a.prototype.readInt8=function(t,e){return e||Y(t,1,this.length),128&this[t]?(255-this[t]+1)*-1:this[t]},a.prototype.readInt16LE=function(t,e){e||Y(t,2,this.length);var n=this[t]|this[t+1]<<8;return 32768&n?4294901760|n:n},a.prototype.readInt16BE=function(t,e){e||Y(t,2,this.length);var n=this[t+1]|this[t]<<8;return 32768&n?4294901760|n:n},a.prototype.readInt32LE=function(t,e){return e||Y(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},a.prototype.readInt32BE=function(t,e){return e||Y(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},a.prototype.readFloatLE=function(t,e){return e||Y(t,4,this.length),$.read(this,t,!0,23,4)},a.prototype.readFloatBE=function(t,e){return e||Y(t,4,this.length),$.read(this,t,!1,23,4)},a.prototype.readDoubleLE=function(t,e){return e||Y(t,8,this.length),$.read(this,t,!0,52,8)},a.prototype.readDoubleBE=function(t,e){return e||Y(t,8,this.length),$.read(this,t,!1,52,8)},a.prototype.writeUIntLE=function(t,e,n,r){if(t=+t,e=0|e,n=0|n,!r){var o=Math.pow(2,8*n)-1;F(this,t,e,n,o,0)}var i=1,a=0;for(this[e]=255&t;++a<n&&(i*=256);)this[e+a]=t/i&255;return e+n},a.prototype.writeUIntBE=function(t,e,n,r){if(t=+t,e=0|e,n=0|n,!r){var o=Math.pow(2,8*n)-1;F(this,t,e,n,o,0)}var i=n-1,a=1;for(this[e+i]=255&t;--i>=0&&(a*=256);)this[e+i]=t/a&255;return e+n},a.prototype.writeUInt8=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,1,255,0),a.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},a.prototype.writeUInt16LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):z(this,t,e,!0),e+2},a.prototype.writeUInt16BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,65535,0),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):z(this,t,e,!1),e+2},a.prototype.writeUInt32LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):I(this,t,e,!0),e+4},a.prototype.writeUInt32BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,4294967295,0),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):I(this,t,e,!1),e+4},a.prototype.writeIntLE=function(t,e,n,r){if(t=+t,e=0|e,!r){var o=Math.pow(2,8*n-1);F(this,t,e,n,o-1,-o)}var i=0,a=1,s=0;for(this[e]=255&t;++i<n&&(a*=256);)t<0&&0===s&&0!==this[e+i-1]&&(s=1),this[e+i]=(t/a>>0)-s&255;return e+n},a.prototype.writeIntBE=function(t,e,n,r){if(t=+t,e=0|e,!r){var o=Math.pow(2,8*n-1);F(this,t,e,n,o-1,-o)}var i=n-1,a=1,s=0;for(this[e+i]=255&t;--i>=0&&(a*=256);)t<0&&0===s&&0!==this[e+i+1]&&(s=1),this[e+i]=(t/a>>0)-s&255;return e+n},a.prototype.writeInt8=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,1,127,-128),a.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},a.prototype.writeInt16LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):z(this,t,e,!0),e+2},a.prototype.writeInt16BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,2,32767,-32768),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):z(this,t,e,!1),e+2},a.prototype.writeInt32LE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,2147483647,-2147483648),a.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):I(this,t,e,!0),e+4},a.prototype.writeInt32BE=function(t,e,n){return t=+t,e=0|e,n||F(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),a.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):I(this,t,e,!1),e+4},a.prototype.writeFloatLE=function(t,e,n){return K(this,t,e,!0,n)},a.prototype.writeFloatBE=function(t,e,n){return K(this,t,e,!1,n)},a.prototype.writeDoubleLE=function(t,e,n){return G(this,t,e,!0,n)},a.prototype.writeDoubleBE=function(t,e,n){return G(this,t,e,!1,n)},a.prototype.copy=function(t,e,n,r){if(n||(n=0),r||0===r||(r=this.length),e>=t.length&&(e=t.length),e||(e=0),r>0&&r<n&&(r=n),r===n)return 0;if(0===t.length||0===this.length)return 0;if(e<0)throw new RangeError("targetStart out of bounds");if(n<0||n>=this.length)throw new RangeError("sourceStart out of bounds");if(r<0)throw new RangeError("sourceEnd out of bounds");r>this.length&&(r=this.length),t.length-e<r-n&&(r=t.length-e+n);var o,i=r-n;if(this===t&&n<e&&e<r)for(o=i-1;o>=0;--o)t[o+e]=this[o+n];else if(i<1e3||!a.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)t[o+e]=this[o+n];else Uint8Array.prototype.set.call(t,this.subarray(n,n+i),e);return i},a.prototype.fill=function(t,e,n,r){if("string"==typeof t){if("string"==typeof e?(r=e,e=0,n=this.length):"string"==typeof n&&(r=n,n=this.length),1===t.length){var o=t.charCodeAt(0);o<256&&(t=o)}if(void 0!==r&&"string"!=typeof r)throw new TypeError("encoding must be a string");if("string"==typeof r&&!a.isEncoding(r))throw new TypeError("Unknown encoding: "+r)}else"number"==typeof t&&(t=255&t);if(e<0||this.length<e||this.length<n)throw new RangeError("Out of range index");if(n<=e)return this;e>>>=0,n=void 0===n?this.length:n>>>0,t||(t=0);var i;if("number"==typeof t)for(i=e;i<n;++i)this[i]=t;else{var s=a.isBuffer(t)?t:W(new a(t,r).toString()),c=s.length;for(i=0;i<n-e;++i)this[i+e]=s[i%c]}return this};var et=/[^+\/0-9A-Za-z-_]/g}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"base64-js":1,ieee754:4,isarray:5}],3:[function(e,n,r){(function(e){/*!
9
+ * @license deepcopy.js Copyright(c) 2013 sasa+1
10
+ * https://github.com/sasaplus1/deepcopy.js
11
+ * Released under the MIT license.
12
+ */
13
+!function(e,o){"object"==typeof r&&"object"==typeof n?n.exports=o():"function"==typeof t&&t.amd?t([],o):"object"==typeof r?r.deepcopy=o():e.deepcopy=o()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";t.exports=n(3)},function(t,n){"use strict";function r(t,e){if("[object Array]"!==o.call(t))throw new TypeError("array must be an Array");var n=void 0,r=void 0,i=void 0;for(n=0,r=t.length;r>n;++n)if(i=t[n],i===e||i!==i&&e!==e)return n;return-1}n.__esModule=!0;var o=Object.prototype.toString,i="undefined"!=typeof e?function(t){return e.isBuffer(t)}:function(){return!1},a="function"==typeof Object.keys?function(t){return Object.keys(t)}:function(t){var e=typeof t;if(null===t||"function"!==e&&"object"!==e)throw new TypeError("obj must be an Object");var n=[],r=void 0;for(r in t)Object.prototype.hasOwnProperty.call(t,r)&&n.push(r);return n},s="function"==typeof Symbol?function(t){return Object.getOwnPropertySymbols(t)}:function(){return[]};n.getKeys=a,n.getSymbols=s,n.indexOf=r,n.isBuffer=i},function(t,n,r){"use strict";function o(t,e){var n=a(t);return null!==n?n:i(t,e)}function i(t,n){if("function"!=typeof n)throw new TypeError("customizer is must be a Function");if("function"==typeof t){var r=String(t);return/^\s*function\s*\S*\([^\)]*\)\s*{\s*\[native code\]\s*}/.test(r)?t:new Function("return "+String(r))()}var o=c.call(t);if("[object Array]"===o)return[];if("[object Object]"===o&&t.constructor===Object)return{};if("[object Date]"===o)return new Date(t.getTime());if("[object RegExp]"===o){var i=String(t),a=i.lastIndexOf("/");return new RegExp(i.slice(1,a),i.slice(a+1))}if((0,s.isBuffer)(t)){var l=new e(t.length);return t.copy(l),l}var u=n(t);return void 0!==u?u:null}function a(t){var e=typeof t;return null!==t&&"object"!==e&&"function"!==e?t:null}n.__esModule=!0,n.copyValue=n.copyCollection=n.copy=void 0;var s=r(1),c=Object.prototype.toString;n.copy=o,n.copyCollection=i,n.copyValue=a},function(t,e,n){"use strict";function r(t){}function o(t){var e=arguments.length<=1||void 0===arguments[1]?r:arguments[1];if(null===t)return null;var n=(0,a.copyValue)(t);if(null!==n)return n;var o=(0,a.copyCollection)(t,e),s=null!==o?o:t,c=[t],l=[s];return i(t,e,s,c,l)}function i(t,e,n,r,o){if(null===t)return null;var c=(0,a.copyValue)(t);if(null!==c)return c;var l=(0,s.getKeys)(t).concat((0,s.getSymbols)(t)),u=void 0,f=void 0,p=void 0,d=void 0,h=void 0,m=void 0,g=void 0,b=void 0;for(u=0,f=l.length;f>u;++u)p=l[u],d=t[p],h=(0,s.indexOf)(r,d),m=void 0,g=void 0,b=void 0,-1===h?(m=(0,a.copy)(d,e),g=null!==m?m:d,null!==d&&/^(?:function|object)$/.test(typeof d)&&(r.push(d),o.push(g))):b=o[h],n[p]=b||i(d,e,g,r,o);return n}e.__esModule=!0;var a=n(2),s=n(1);e["default"]=o,t.exports=e["default"]}])})}).call(this,e("buffer").Buffer)},{buffer:2}],4:[function(t,e,n){n.read=function(t,e,n,r,o){var i,a,s=8*o-r-1,c=(1<<s)-1,l=c>>1,u=-7,f=n?o-1:0,p=n?-1:1,d=t[e+f];for(f+=p,i=d&(1<<-u)-1,d>>=-u,u+=s;u>0;i=256*i+t[e+f],f+=p,u-=8);for(a=i&(1<<-u)-1,i>>=-u,u+=r;u>0;a=256*a+t[e+f],f+=p,u-=8);if(0===i)i=1-l;else{if(i===c)return a?NaN:(d?-1:1)*(1/0);a+=Math.pow(2,r),i-=l}return(d?-1:1)*a*Math.pow(2,i-r)},n.write=function(t,e,n,r,o,i){var a,s,c,l=8*i-o-1,u=(1<<l)-1,f=u>>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,d=r?0:i-1,h=r?1:-1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(s=isNaN(e)?1:0,a=u):(a=Math.floor(Math.log(e)/Math.LN2),e*(c=Math.pow(2,-a))<1&&(a--,c*=2),e+=a+f>=1?p/c:p*Math.pow(2,1-f),e*c>=2&&(a++,c/=2),a+f>=u?(s=0,a=u):a+f>=1?(s=(e*c-1)*Math.pow(2,o),a+=f):(s=e*Math.pow(2,f-1)*Math.pow(2,o),a=0));o>=8;t[n+d]=255&s,d+=h,s/=256,o-=8);for(a=a<<o|s,l+=o;l>0;t[n+d]=255&a,d+=h,a/=256,l-=8);t[n+d-h]|=128*m}},{}],5:[function(t,e,n){var r={}.toString;e.exports=Array.isArray||function(t){return"[object Array]"==r.call(t)}},{}],6:[function(t,e,n){function r(t){return/^[a-z_$][0-9a-z_$]*$/gi.test(t)&&!i.test(t)}function o(t){if(a)return t.toString();var e=t.source.replace(/\//g,function(t,e,n){return 0===e||"\\"!==n[e-1]?"\\/":"/"}),n=(t.global&&"g"||"")+(t.ignoreCase&&"i"||"")+(t.multiline&&"m"||"");return"/"+e+"/"+n}/* toSource by Marcello Bastea-Forte - zlib license */
14
+e.exports=function(t,e,n,i){function a(t,e,n,i,s){function c(t){return n.slice(1)+t.join(","+(n&&"\n")+l)+(n?" ":"")}var l=i+n;switch(t=e?e(t):t,typeof t){case"string":return JSON.stringify(t);case"boolean":case"number":case"undefined":return""+t;case"function":return t.toString()}if(null===t)return"null";if(t instanceof RegExp)return o(t);if(t instanceof Date)return"new Date("+t.getTime()+")";var u=s.indexOf(t)+1;if(u>0)return"{$circularReference:"+u+"}";if(s.push(t),Array.isArray(t))return"["+c(t.map(function(t){return a(t,e,n,l,s.slice())}))+"]";var f=Object.keys(t);return f.length?"{"+c(f.map(function(o){return(r(o)?o:JSON.stringify(o))+":"+a(t[o],e,n,l,s.slice())}))+"}":"{}"}var s=[];return a(t,e,void 0===n?"  ":n||"",i||"",s)};var i=/^(abstract|boolean|break|byte|case|catch|char|class|const|continue|debugger|default|delete|do|double|else|enum|export|extends|false|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|null|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|true|try|typeof|undefined|var|void|volatile|while|with)$/,a="\\/"===new RegExp("/").source},{}],7:[function(t,e,n){e.exports={name:"pebble-clay",version:"1.0.4",description:"Pebble Config Framework",scripts:{"test-travis":"./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --single-run --browsers chromeTravisCI && ./node_modules/.bin/eslint ./","test-debug":"(export DEBUG=true && ./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --no-single-run)",test:"./node_modules/.bin/gulp && ./node_modules/.bin/karma start ./test/karma.conf.js --single-run",lint:"./node_modules/.bin/eslint ./",build:"gulp",dev:"gulp dev","pebble-clean":"rm -rf tmp src/js/index.js && pebble clean","pebble-publish":"npm run pebble-clean && npm run build && pebble build && pebble package publish && npm run pebble-clean","pebble-build":"npm run build && pebble build"},repository:{type:"git",url:"git+https://github.com/pebble/clay.git"},keywords:["pebble","config","configuration","pebble-package"],author:"Pebble Technology",license:"MIT",bugs:{url:"https://github.com/pebble/clay/issues"},pebble:{projectType:"package",sdkVersion:"3",targetPlatforms:["aplite","basalt","chalk","diorite","emery"],resources:{media:[]},capabilities:["configurable"]},homepage:"https://github.com/pebble/clay#readme",devDependencies:{autoprefixer:"^6.3.1",bourbon:"^4.2.6",browserify:"^13.0.0","browserify-istanbul":"^0.2.1",chai:"^3.4.1",deamdify:"^0.2.0",deepcopy:"^0.6.1",del:"^2.0.2",eslint:"^1.5.1","eslint-config-pebble":"^1.2.0","eslint-plugin-standard":"^1.3.1",gulp:"^3.9.0","gulp-autoprefixer":"^3.1.0","gulp-htmlmin":"^1.3.0","gulp-inline":"0.0.15","gulp-insert":"^0.5.0","gulp-sass":"^2.1.1","gulp-sourcemaps":"^1.6.0","gulp-uglify":"^1.5.2",joi:"^6.10.1",karma:"^0.13.19","karma-browserify":"^5.0.1","karma-chrome-launcher":"^0.2.2","karma-coverage":"^0.5.3","karma-mocha":"^0.2.1","karma-mocha-reporter":"^1.1.5","karma-source-map-support":"^1.1.0","karma-threshold-reporter":"^0.1.15",mocha:"^2.3.4",postcss:"^5.0.14","require-from-string":"^1.1.0",sassify:"^0.9.1",sinon:"^1.17.3",stringify:"^3.2.0",through:"^2.3.8",tosource:"^1.0.0","vinyl-buffer":"^1.0.0","vinyl-source-stream":"^1.1.0",watchify:"^3.7.0"},dependencies:{}}},{}],8:[function(t,e,n){"use strict";e.exports={name:"button",template:t("../../templates/components/button.tpl"),style:t("../../styles/clay/components/button.scss"),manipulator:"button",defaults:{primary:!1,attributes:{},description:""}}},{"../../styles/clay/components/button.scss":21,"../../templates/components/button.tpl":30}],9:[function(t,e,n){"use strict";e.exports={name:"checkboxgroup",template:t("../../templates/components/checkboxgroup.tpl"),style:t("../../styles/clay/components/checkboxgroup.scss"),manipulator:"checkboxgroup",defaults:{label:"",options:[],description:""}}},{"../../styles/clay/components/checkboxgroup.scss":22,"../../templates/components/checkboxgroup.tpl":31}],10:[function(t,e,n){"use strict";e.exports={name:"color",template:t("../../templates/components/color.tpl"),style:t("../../styles/clay/components/color.scss"),manipulator:"color",defaults:{label:"",description:""},initialize:function(t,e){function n(t){if("number"==typeof t)t=t.toString(16);else if(!t)return"transparent";return t=r(t),"#"+(f?p[t]:t)}function r(t){for(t=t.toLowerCase();t.length<6;)t="0"+t;return t}function o(t){switch(typeof t){case"number":return r(t.toString(16));case"string":return t.replace(/^#|^0x/,"");default:return t}}function i(t){return t.reduce(function(t,e){return t.concat(e)},[])}function a(t){t=t.replace(/^#|^0x/,"");var e=parseInt(t.slice(0,2),16)/255,n=parseInt(t.slice(2,4),16)/255,r=parseInt(t.slice(4),16)/255;e=e>.04045?Math.pow((e+.055)/1.055,2.4):e/12.92,n=n>.04045?Math.pow((n+.055)/1.055,2.4):n/12.92,r=r>.04045?Math.pow((r+.055)/1.055,2.4):r/12.92;var o=(.4124*e+.3576*n+.1805*r)/.95047,i=(.2126*e+.7152*n+.0722*r)/1,a=(.0193*e+.1192*n+.9505*r)/1.08883;return o=o>.008856?Math.pow(o,1/3):7.787*o+16/116,i=i>.008856?Math.pow(i,1/3):7.787*i+16/116,a=a>.008856?Math.pow(a,1/3):7.787*a+16/116,[116*i-16,500*(o-i),200*(i-a)]}function s(t,e){var n=t[0]-e[0],r=t[1]-e[1],o=t[2]-e[2];return Math.sqrt(Math.pow(n,2)+Math.pow(r,2)+Math.pow(o,2))}function c(){return!e.meta.activeWatchInfo||2===e.meta.activeWatchInfo.firmware.major||["aplite","diorite"].indexOf(e.meta.activeWatchInfo.platform)>-1&&!u.config.allowGray?d.BLACK_WHITE:["aplite","diorite"].indexOf(e.meta.activeWatchInfo.platform)>-1&&u.config.allowGray?d.GRAY:d.COLOR}var l=t.HTML,u=this;u.roundColorToLayout=function(t){var e=o(t);if(m.indexOf(e)===-1){var n=a(e),r=m.map(function(t){var e=a(o(t));return s(n,e)}),i=Math.min.apply(Math,r),c=r.indexOf(i);e=m[c]}return parseInt(e,16)};var f=u.config.sunlight!==!1,p={"000000":"000000","000055":"001e41","0000aa":"004387","0000ff":"0068ca","005500":"2b4a2c","005555":"27514f","0055aa":"16638d","0055ff":"007dce","00aa00":"5e9860","00aa55":"5c9b72","00aaaa":"57a5a2","00aaff":"4cb4db","00ff00":"8ee391","00ff55":"8ee69e","00ffaa":"8aebc0","00ffff":"84f5f1",550000:"4a161b",550055:"482748","5500aa":"40488a","5500ff":"2f6bcc",555500:"564e36",555555:"545454","5555aa":"4f6790","5555ff":"4180d0","55aa00":"759a64","55aa55":"759d76","55aaaa":"71a6a4","55aaff":"69b5dd","55ff00":"9ee594","55ff55":"9de7a0","55ffaa":"9becc2","55ffff":"95f6f2",aa0000:"99353f",aa0055:"983e5a",aa00aa:"955694",aa00ff:"8f74d2",aa5500:"9d5b4d",aa5555:"9d6064",aa55aa:"9a7099",aa55ff:"9587d5",aaaa00:"afa072",aaaa55:"aea382",aaaaaa:"ababab",ffffff:"ffffff",aaaaff:"a7bae2",aaff00:"c9e89d",aaff55:"c9eaa7",aaffaa:"c7f0c8",aaffff:"c3f9f7",ff0000:"e35462",ff0055:"e25874",ff00aa:"e16aa3",ff00ff:"de83dc",ff5500:"e66e6b",ff5555:"e6727c",ff55aa:"e37fa7",ff55ff:"e194df",ffaa00:"f1aa86",ffaa55:"f1ad93",ffaaaa:"efb5b8",ffaaff:"ecc3eb",ffff00:"ffeeab",ffff55:"fff1b5",ffffaa:"fff6d3"},d={COLOR:[[!1,!1,"55ff00","aaff55",!1,"ffff55","ffffaa",!1,!1],[!1,"aaffaa","55ff55","00ff00","aaff00","ffff00","ffaa55","ffaaaa",!1],["55ffaa","00ff55","00aa00","55aa00","aaaa55","aaaa00","ffaa00","ff5500","ff5555"],["aaffff","00ffaa","00aa55","55aa55","005500","555500","aa5500","ff0000","ff0055"],[!1,"55aaaa","00aaaa","005555","ffffff","000000","aa5555","aa0000",!1],["55ffff","00ffff","00aaff","0055aa","aaaaaa","555555","550000","aa0055","ff55aa"],["55aaff","0055ff","0000ff","0000aa","000055","550055","aa00aa","ff00aa","ffaaff"],[!1,"5555aa","5555ff","5500ff","5500aa","aa00ff","ff00ff","ff55ff",!1],[!1,!1,!1,"aaaaff","aa55ff","aa55aa",!1,!1,!1]],GRAY:[["000000","aaaaaa","ffffff"]],BLACK_WHITE:[["000000","ffffff"]]},h=u.config.layout||c();"string"==typeof h&&(h=d[h]),Array.isArray(h[0])||(h=[h]);var m=i(h).map(function(t){return o(t)}).filter(function(t){return t}),g="",b=h.length,y=0;h.forEach(function(t){y=t.length>y?t.length:y});for(var v=100/y,A=100/b,w=u.$element,k=0;k<b;k++)for(var x=0;x<y;x++){var M=o(h[k][x]),T=M?" selectable":"",R=0===k&&0===x||0===k&&!h[k][x-1]||!h[k][x-1]&&!h[k-1][x]?" rounded-tl":"",P=0===k&&!h[k][x+1]||!h[k][x+1]&&!h[k-1][x]?" rounded-tr ":"",O=k===h.length-1&&0===x||k===h.length-1&&!h[k][x-1]||!h[k][x-1]&&!h[k+1][x]?" rounded-bl":"",E=k===h.length-1&&!h[k][x+1]||!h[k][x+1]&&!h[k+1][x]?" rounded-br":"";g+='<i class="color-box '+T+R+P+O+E+'" '+(M?'data-value="'+parseInt(M,16)+'" ':"")+'style="width:'+v+"%; height:"+A+"%; background:"+n(M)+';"></i>'}var j=0;3===y&&(j=5),2===y&&(j=8);var B=j*v/A+"%",S=j+"%";w.select(".color-box-container").add(l(g)).set("$paddingTop",B).set("$paddingRight",S).set("$paddingBottom",B).set("$paddingLeft",S),w.select(".color-box-wrap").set("$paddingBottom",v/A*100+"%");var D=w.select(".value"),N=w.select(".picker-wrap"),Y=u.$manipulatorTarget.get("disabled");w.select("label").on("click",function(){Y||N.set("show")}),u.on("change",function(){var t=u.get();D.set("$background-color",n(t)),w.select(".color-box").set("-selected"),w.select('.color-box[data-value="'+t+'"]').set("+selected")}),w.select(".color-box.selectable").on("click",function(t){u.set(parseInt(t.target.dataset.value,10)),N.set("-show")}),N.on("click",function(){N.set("-show")}),u.on("disabled",function(){Y=!0}),u.on("enabled",function(){Y=!1}),u._layout=h}}},{"../../styles/clay/components/color.scss":23,"../../templates/components/color.tpl":32}],11:[function(t,e,n){"use strict";e.exports={name:"footer",template:t("../../templates/components/footer.tpl"),manipulator:"html"}},{"../../templates/components/footer.tpl":33}],12:[function(t,e,n){"use strict";e.exports={name:"heading",template:t("../../templates/components/heading.tpl"),manipulator:"html",defaults:{size:4}}},{"../../templates/components/heading.tpl":34}],13:[function(t,e,n){"use strict";e.exports={color:t("./color"),footer:t("./footer"),heading:t("./heading"),input:t("./input"),select:t("./select"),submit:t("./submit"),text:t("./text"),toggle:t("./toggle"),radiogroup:t("./radiogroup"),checkboxgroup:t("./checkboxgroup"),button:t("./button"),slider:t("./slider")}},{"./button":8,"./checkboxgroup":9,"./color":10,"./footer":11,"./heading":12,"./input":14,"./radiogroup":15,"./select":16,"./slider":17,"./submit":18,"./text":19,"./toggle":20}],14:[function(t,e,n){"use strict";e.exports={name:"input",template:t("../../templates/components/input.tpl"),style:t("../../styles/clay/components/input.scss"),manipulator:"val",defaults:{label:"",description:"",attributes:{}}}},{"../../styles/clay/components/input.scss":24,"../../templates/components/input.tpl":35}],15:[function(t,e,n){"use strict";e.exports={name:"radiogroup",template:t("../../templates/components/radiogroup.tpl"),style:t("../../styles/clay/components/radiogroup.scss"),manipulator:"radiogroup",defaults:{label:"",options:[],description:"",attributes:{}}}},{"../../styles/clay/components/radiogroup.scss":25,"../../templates/components/radiogroup.tpl":36}],16:[function(t,e,n){"use strict";e.exports={name:"select",template:t("../../templates/components/select.tpl"),style:t("../../styles/clay/components/select.scss"),manipulator:"val",defaults:{label:"",options:[],description:"",attributes:{}},initialize:function(){function t(){var t=e.$manipulatorTarget.get("selectedIndex"),r=e.$manipulatorTarget.select("option"),o=r[t]&&r[t].innerHTML;n.set("innerHTML",o)}var e=this,n=e.$element.select(".value");t(),e.on("change",t)}}},{"../../styles/clay/components/select.scss":26,"../../templates/components/select.tpl":37}],17:[function(t,e,n){"use strict";e.exports={name:"slider",template:t("../../templates/components/slider.tpl"),style:t("../../styles/clay/components/slider.scss"),manipulator:"slider",defaults:{label:"",description:"",min:0,max:100,step:1,attributes:{}},initialize:function(){function t(){var t=e.get().toFixed(e.precision);n.set("value",t),r.set("innerHTML",t)}var e=this,n=e.$element.select(".value"),r=e.$element.select(".value-pad"),o=e.$manipulatorTarget,i=o.get("step");i=i.toString(10).split(".")[1],e.precision=i?i.length:0,e.on("change",t),o.on("|input",t),t(),n.on("|input",function(){r.set("innerHTML",this.get("value"))}),n.on("|change",function(){e.set(this.get("value")),t()})}}},{"../../styles/clay/components/slider.scss":27,"../../templates/components/slider.tpl":38}],18:[function(t,e,n){"use strict";e.exports={name:"submit",template:t("../../templates/components/submit.tpl"),style:t("../../styles/clay/components/submit.scss"),manipulator:"button",defaults:{attributes:{}}}},{"../../styles/clay/components/submit.scss":28,"../../templates/components/submit.tpl":39}],19:[function(t,e,n){"use strict";e.exports={name:"text",template:t("../../templates/components/text.tpl"),manipulator:"html"}},{"../../templates/components/text.tpl":40}],20:[function(t,e,n){"use strict";e.exports={name:"toggle",template:t("../../templates/components/toggle.tpl"),style:t("../../styles/clay/components/toggle.scss"),manipulator:"checked",defaults:{label:"",description:"",attributes:{}}}},{"../../styles/clay/components/toggle.scss":29,"../../templates/components/toggle.tpl":41}],21:[function(t,e,n){e.exports=".component-button { text-align: center; }\n\n.section .component-button { padding-bottom: 0; }\n\n.component-button .description { padding-left: 0; padding-right: 0; }\n"},{}],22:[function(t,e,n){e.exports=".component-checkbox { display: block; }\n\n.section .component-checkbox { padding-right: 0.375rem; }\n\n.component-checkbox > .label { display: block; padding-bottom: 0.35rem; }\n\n.component-checkbox .checkbox-group { padding-bottom: 0.35rem; }\n\n.component-checkbox .checkbox-group label { padding: 0.35rem 0.375rem; }\n\n.component-checkbox .checkbox-group .label { font-size: 0.9em; }\n\n.component-checkbox .checkbox-group input { opacity: 0; position: absolute; }\n\n.component-checkbox .checkbox-group i { display: block; position: relative; border-radius: 0.25rem; width: 1.4rem; height: 1.4rem; border: 0.11765rem solid #767676; -webkit-flex-shrink: 0; flex-shrink: 0; }\n\n.component-checkbox .checkbox-group input:checked + i { border-color: #ff4700; background: #ff4700; }\n\n.component-checkbox .checkbox-group input:checked + i:after { content: ''; box-sizing: border-box; -webkit-transform: rotate(45deg); transform: rotate(45deg); position: absolute; left: 0.35rem; top: -0.05rem; display: block; width: 0.5rem; height: 1rem; border: 0 solid #ffffff; border-right-width: 0.11765rem; border-bottom-width: 0.11765rem; }\n\n.component-checkbox .description { padding-left: 0; padding-right: 0; }\n"},{}],23:[function(t,e,n){e.exports=".section .component-color { padding: 0; }\n\n.component-color .value { width: 2.2652rem; height: 1.4rem; border-radius: 0.7rem; box-shadow: 0 0.1rem 0.1rem #2f2f2f; display: block; background: #000; }\n\n.component-color .picker-wrap { left: 0; top: 0; right: 0; bottom: 0; position: fixed; padding: 0.7rem 0.375rem; background: rgba(0, 0, 0, 0.65); opacity: 0; -webkit-transition: opacity 100ms ease-in 175ms; transition: opacity 100ms ease-in 175ms; pointer-events: none; z-index: 100; display: -webkit-box; display: -webkit-flex; display: flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; flex-direction: column; -webkit-box-pack: center; -webkit-justify-content: center; justify-content: center; -webkit-box-align: center; -webkit-align-items: center; align-items: center; }\n\n.component-color .picker-wrap .picker { padding: 0.7rem 0.75rem; background: #484848; box-shadow: 0 0.17647rem 0.88235rem rgba(0, 0, 0, 0.4); border-radius: 0.25rem; width: 100%; max-width: 26rem; overflow: auto; }\n\n.component-color .picker-wrap.show { -webkit-transition-delay: 0ms; transition-delay: 0ms; pointer-events: auto; opacity: 1; }\n\n.component-color .color-box-wrap { box-sizing: border-box; position: relative; height: 0; width: 100%; padding: 0 0 100% 0; }\n\n.component-color .color-box-wrap .color-box-container { position: absolute; height: 99.97%; width: 100%; left: 0; top: 0; }\n\n.component-color .color-box-wrap .color-box-container .color-box { float: left; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-tl { border-top-left-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-tr { border-top-right-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-bl { border-bottom-left-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.rounded-br { border-bottom-right-radius: 0.25rem; }\n\n.component-color .color-box-wrap .color-box-container .color-box.selected { -webkit-transform: scale(1.1); transform: scale(1.1); border-radius: 0.25rem; box-shadow: #111 0 0 0.24rem; position: relative; z-index: 100; }\n"},{}],24:[function(t,e,n){e.exports=".section .component-input { padding: 0; }\n\n.component-input label { display: block; }\n\n.component-input .label { padding-bottom: 0.7rem; }\n\n.component-input .input { position: relative; min-width: 100%; margin-top: 0.7rem; margin-left: 0; }\n\n.component-input input { display: block; width: 100%; background: #333333; border-radius: 0.25rem; padding: 0.35rem 0.375rem; border: none; vertical-align: baseline; color: #ffffff; font-size: inherit; -webkit-appearance: none; appearance: none; min-height: 2.1rem; }\n\n.component-input input::-webkit-input-placeholder { color: #858585; }\n\n.component-input input::-moz-placeholder { color: #858585; }\n\n.component-input input:-moz-placeholder { color: #858585; }\n\n.component-input input:-ms-input-placeholder { color: #858585; }\n\n.component-input input:focus { border: none; box-shadow: none; }\n\n.component-input input:focus::-webkit-input-placeholder { color: #666666; }\n\n.component-input input:focus::-moz-placeholder { color: #666666; }\n\n.component-input input:focus:-moz-placeholder { color: #666666; }\n\n.component-input input:focus:-ms-input-placeholder { color: #666666; }\n"},{}],25:[function(t,e,n){e.exports=".component-radio { display: block; }\n\n.section .component-radio { padding-right: 0.375rem; }\n\n.component-radio > .label { display: block; padding-bottom: 0.35rem; }\n\n.component-radio .radio-group { padding-bottom: 0.35rem; }\n\n.component-radio .radio-group label { padding: 0.35rem 0.375rem; }\n\n.component-radio .radio-group .label { font-size: 0.9em; }\n\n.component-radio .radio-group input { opacity: 0; position: absolute; }\n\n.component-radio .radio-group i { display: block; position: relative; border-radius: 1.4rem; width: 1.4rem; height: 1.4rem; border: 2px solid #767676; -webkit-flex-shrink: 0; flex-shrink: 0; }\n\n.component-radio .radio-group input:checked + i { border-color: #ff4700; }\n\n.component-radio .radio-group input:checked + i:after { content: ''; display: block; position: absolute; left: 15%; right: 15%; top: 15%; bottom: 15%; border-radius: 1.4rem; background: #ff4700; }\n\n.component-radio .description { padding-left: 0; padding-right: 0; }\n"},{}],26:[function(t,e,n){e.exports='.section .component-select { padding: 0; }\n\n.component-select label { position: relative; }\n\n.component-select .value { position: relative; padding-right: 1.1rem; display: block; }\n\n.component-select .value:after { content: ""; position: absolute; right: 0; top: 50%; margin-top: -0.1rem; height: 0; width: 0; border-left: 0.425rem solid transparent; border-right: 0.425rem solid transparent; border-top: 0.425rem solid #ff4700; }\n\n.component-select select { opacity: 0; position: absolute; display: block; left: 0; right: 0; top: 0; bottom: 0; width: 100%; border: none; margin: 0; padding: 0; }\n'},{}],27:[function(t,e,n){e.exports=".section .component-slider { padding: 0; }\n\n.component-slider label { display: block; }\n\n.component-slider .label-container { display: -webkit-box; display: -webkit-flex; display: flex; -webkit-box-align: center; -webkit-align-items: center; align-items: center; width: 100%; padding-bottom: 0.7rem; }\n\n.component-slider .label { -webkit-box-flex: 1; -webkit-flex: 1; flex: 1; min-width: 1rem; display: block; padding-right: 0.75rem; }\n\n.component-slider .value-wrap { display: block; position: relative; }\n\n.component-slider .value, .component-slider .value-pad { display: block; background: #333333; border-radius: 0.25rem; padding: 0.35rem 0.375rem; border: none; vertical-align: baseline; color: #ffffff; text-align: right; margin: 0; min-width: 1rem; }\n\n.component-slider .value-pad { visibility: hidden; }\n\n.component-slider .value-pad:before { content: ' '; display: inline-block; }\n\n.component-slider .value { max-width: 100%; position: absolute; left: 0; top: 0; }\n\n.component-slider .input-wrap { padding: 0 0.75rem 0.7rem; }\n\n.component-slider .input { display: block; position: relative; min-width: 100%; height: 1.4rem; overflow: hidden; margin-left: 0; }\n\n.component-slider .input:before { content: ''; display: block; position: absolute; height: 0.17647rem; background: #666666; width: 100%; top: 0.61176rem; }\n\n.component-slider .input .slider { display: block; width: 100%; -webkit-appearance: none; appearance: none; position: relative; height: 1.4rem; margin: 0; background-color: transparent; }\n\n.component-slider .input .slider:focus { outline: none; }\n\n.component-slider .input .slider::-webkit-slider-runnable-track { border: none; height: 1.4rem; width: 100%; background-color: transparent; }\n\n.component-slider .input .slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; position: relative; height: 1.4rem; width: 1.4rem; background-color: #ff4700; border-radius: 50%; }\n\n.component-slider .input .slider::-webkit-slider-thumb:before { content: \"\"; position: absolute; left: -1000px; top: 0.61176rem; height: 0.17647rem; width: 1001px; background: #ff4700; }\n"},{}],28:[function(t,e,n){e.exports=".component-submit { text-align: center; }\n"},{}],29:[function(t,e,n){e.exports=".section .component-toggle { padding: 0; }\n\n.component-toggle input { display: none; }\n\n.component-toggle .graphic { display: inline-block; position: relative; }\n\n.component-toggle .graphic .slide { display: block; border-radius: 1.05rem; height: 1.05rem; width: 2.2652rem; background: #2f2f2f; -webkit-transition: background-color 150ms linear; transition: background-color 150ms linear; }\n\n.component-toggle .graphic .marker { background: #ececec; width: 1.4rem; height: 1.4rem; border-radius: 1.4rem; position: absolute; left: 0; display: block; top: -0.175rem; -webkit-transition: -webkit-transform 150ms linear; transition: -webkit-transform 150ms linear; transition: transform 150ms linear; transition: transform 150ms linear, -webkit-transform 150ms linear; box-shadow: 0 0.1rem 0.1rem #2f2f2f; }\n\n.component-toggle input:checked + .graphic .slide { background: #993d19; }\n\n.component-toggle input:checked + .graphic .marker { background: #ff4700; -webkit-transform: translateX(0.8652rem); transform: translateX(0.8652rem); }\n"},{}],30:[function(t,e,n){e.exports='<div class="component component-button">\n  <button\n    type="button"\n    data-manipulator-target\n    class="{{primary ? \'primary\' : \'\'}}"\n    {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n  ></button>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],31:[function(t,e,n){e.exports='<div class="component component-checkbox">\n  <span class="label">{{{label}}}</span>\n  <div class="checkbox-group">\n    {{each options}}\n      <label class="tap-highlight">\n        <span class="label">{{{this}}}</span>\n        <input type="checkbox" value="1" name="clay-{{clayId}}" />\n        <i></i>\n      </label>\n    {{/each}}\n  </div>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],32:[function(t,e,n){e.exports='<div class="component component-color">\n  <label class="tap-highlight">\n    <input\n      data-manipulator-target\n      type="hidden"\n    />\n    <span class="label">{{{label}}}</span>\n    <span class="value"></span>\n  </label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n  <div class="picker-wrap">\n    <div class="picker">\n      <div class="color-box-wrap">\n        <div class="color-box-container"></div>\n      </div>\n    </div>\n  </div>\n</div>\n'},{}],33:[function(t,e,n){e.exports='<footer data-manipulator-target class="component component-footer"></footer>\n'},{}],34:[function(t,e,n){e.exports='<div class="component component-heading">\n  <h{{size}} data-manipulator-target></h{{size}}>\n</div>\n'},{}],35:[function(t,e,n){e.exports='<div class="component component-input">\n  <label class="tap-highlight">\n    <span class="label">{{{label}}}</span>\n    <span class="input">\n      <input\n      data-manipulator-target\n        {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n    />\n    </span>\n  </label>\n\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],36:[function(t,e,n){e.exports='<div class="component component-radio">\n  <span class="label">{{{label}}}</span>\n  <div class="radio-group">\n    {{each options}}\n      <label class="tap-highlight">\n        <span class="label">{{{this.label}}}</span>\n        <input\n          type="radio"\n          value="{{this.value}}"\n          name="clay-{{clayId}}"\n          {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n        />\n        <i></i>\n      </label>\n    {{/each}}\n  </div>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],37:[function(t,e,n){e.exports='<div class="component component-select">\n  <label class="tap-highlight">\n    <span class="label">{{{label}}}</span>\n    <span class="value"></span>\n    <select data-manipulator-target {{each key: attributes}}{{key}}="{{this}}"{{/each}}>\n      {{each options}}\n        {{if Array.isArray(this.value)}}\n          <optgroup label="{{this.label}}">\n            {{each this.value}}\n              <option value="{{this.value}}" class="item-select-option">{{this.label}}</option>\n            {{/each}}\n          </optgroup>\n        {{else}}\n          <option value="{{this.value}}" class="item-select-option">{{this.label}}</option>\n        {{/if}}\n      {{/each}}\n    </select>\n  </label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],38:[function(t,e,n){e.exports='<div class="component component-slider">\n  <label class="tap-highlight">\n    <span class="label-container">\n      <span class="label">{{{label}}}</span>\n      <span class="value-wrap">\n        <span class="value-pad"></span>\n        <input type="text" class="value" />\n      </span>\n    </span>\n    <span class="input">\n      <input\n        data-manipulator-target\n        class="slider"\n        type="range"\n        min="{{min}}"\n        max="{{max}}"\n        step="{{step}}"\n        {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n      />\n    </span>\n</label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],39:[function(t,e,n){e.exports='<div class="component component-submit">\n  <button\n    data-manipulator-target\n    type="submit"\n    {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n  ></button>\n</div>\n'},{}],40:[function(t,e,n){e.exports='<div class="component component-text">\n  <p data-manipulator-target></p>\n</div>\n'},{}],41:[function(t,e,n){e.exports='<div class="component component-toggle">\n  <label class="tap-highlight">\n    <span class="label">{{{label}}}</span>\n    <span class="input">\n      <input\n        data-manipulator-target\n        type="checkbox"\n        {{each key: attributes}}{{key}}="{{this}}"{{/each}}\n      />\n      <span class="graphic">\n        <span class="slide"></span>\n        <span class="marker"></span>\n      </span>\n    </span>\n  </label>\n  {{if description}}\n    <div class="description">{{{description}}}</div>\n  {{/if}}\n</div>\n'},{}],42:[function(t,e,n){e.exports='<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><style>@font-face{font-family:PFDinDisplayProRegularWebfont;src:url(data:application/font-woff;charset=utf-8;base64,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) format("woff");font-weight:400;font-style:normal}a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,p,pre,q,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;outline:0;font-size:100%;font:inherit;vertical-align:baseline}button,input,textarea{outline:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote:after,blockquote:before,q:after,q:before{content:\'\';content:none}html{box-sizing:border-box}*,:after,:before{box-sizing:inherit}body,html{font-weight:400;font-family:PFDinDisplayPro-Regular,PFDinDisplayProRegularWebfont,sans-serif;-webkit-font-smoothing:antialiased;font-size:17px;line-height:1.4;height:100%;color:#fff}body.platform-ios,html.platform-ios{font-size:16px}body{background-color:#333;padding:0 .75rem .7rem}em{font-style:italic}strong{font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;color:#ff4700}.platform-android strong{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}a{color:#858585}a:hover{color:inherit}h1,h2,h3,h4{text-transform:uppercase;font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;text-transform:uppercase;position:relative;top:.05rem;line-height:.9}.platform-android h1,.platform-android h2,.platform-android h3,.platform-android h4{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}h1{font-size:2rem;line-height:2.8rem}h2{font-size:1.8rem;line-height:2.8rem}h3{font-size:1.5rem;line-height:2.8rem}h4{font-size:1.2rem;line-height:1.4rem}h5{font-size:1rem;line-height:1.4rem}h6{font-size:.8rem;line-height:1.4rem}input{font-family:inherit;font-size:inherit;line-height:inherit}label{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;-webkit-box-align:center;-webkit-align-items:center;align-items:center;padding:.7rem .75rem}label .input{white-space:nowrap;display:-webkit-box;display:-webkit-flex;display:flex;max-width:50%;margin-left:.75rem}label.invalid .input:after{content:"!";display:inline-block;color:#fff;background:#ff4700;border-radius:.55rem;width:1.1rem;text-align:center;height:1.1rem;font-size:.825rem;vertical-align:middle;line-height:1.1rem;box-shadow:0 .1rem .1rem #2f2f2f;font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;-webkit-box-flex:0;-webkit-flex:0 0 1.1rem;flex:0 0 1.1rem;margin-left:.3rem}.platform-android label.invalid .input:after{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}.hide{display:none!important}.tap-highlight{-webkit-tap-highlight-color:rgba(255,255,255,.1);border-radius:.25rem}.tap-highlight:active{background-color:rgba(255,255,255,.1)}.component{padding-top:.7rem}.component.disabled{pointer-events:none}.component.disabled>*{opacity:.25}.section{background:#484848;border-radius:.25rem;box-shadow:#2f2f2f 0 .15rem .25rem}.section>.component{padding-bottom:.7rem;padding-right:.75rem;padding-left:.75rem;position:relative;margin-top:1rem}.section>.component:not(.hide)~.component{margin-top:0}.section>.component:first-child:after{display:none}.section>.component:after{content:"";background:#666;display:block;position:absolute;top:0;left:.375rem;right:.375rem;height:1px;pointer-events:none}.section>.component:not(.hide):after{display:none}.section>.component:not(.hide)~.component:not(.hide):after{display:block}.section>.component-heading:first-child{background:#414141;border-radius:.25rem .25rem 0 0}.section>.component-heading:first-child:after,.section>.component-heading:first-child~.component:not(.hide):after{display:none}.section>.component-heading:first-child~.component:not(.hide)~.component:not(.hide):after{display:block}.description{padding:0 .75rem .7rem;font-size:.9rem;line-height:1.4rem;color:#a4a4a4;text-align:left}.inputs{display:block;width:100%;border-collapse:collapse}.button,button{font-weight:400;font-family:PFDinDisplayPro-Medium,PFDinDisplayProRegularWebfont,sans-serif;font-size:1rem;line-height:1.4rem;text-transform:uppercase;background-color:#767676;border-radius:.25rem;border:none;display:inline-block;color:#fff;min-width:12rem;text-align:center;margin:0 auto .7rem;padding:.6rem;-webkit-tap-highlight-color:#858585}.platform-android .button,.platform-android button{font-family:PFDinDisplayProRegularWebfont,sans-serif;font-weight:700;letter-spacing:.025em}.button:active,button:active{background-color:#858585}.platform-ios .button,.platform-ios button{padding:.5rem}.button.primary,.button[type=submit],button.primary,button[type=submit]{background-color:#ff4700;-webkit-tap-highlight-color:red}.button.primary:active,.button[type=submit]:active,button.primary:active,button[type=submit]:active{background-color:red}a.button{text-decoration:none;color:#fff}</style><meta name="viewport"content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><script>window.returnTo="$$RETURN_TO$$",window.clayConfig=$$CONFIG$$,window.claySettings=$$SETTINGS$$,window.customFn=$$CUSTOM_FN$$,window.clayComponents=$$COMPONENTS$$,window.clayMeta=$$META$$</script></head><body><form id="main-form"class="inputs"></form><script>!function t(e,n,r){function i(a,u){if(!n[a]){if(!e[a]){var s="function"==typeof require&&require;if(!u&&s)return s(a,!0);if(o)return o(a,!0);var c=new Error("Cannot find module \'"+a+"\'");throw c.code="MODULE_NOT_FOUND",c}var f=n[a]={exports:{}};e[a][0].call(f.exports,function(t){var n=e[a][1][t];return i(n?n:t)},f,f.exports,t,e,n,r)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<r.length;a++)i(r[a]);return i}({1:[function(t,e,n){"use strict";var r=t("./vendor/minified"),i=t("./lib/clay-config"),o=r.$,a=r._,u=a.extend([],window.clayConfig||[]),s=a.extend({},window.claySettings||{}),c=window.returnTo||"pebblejs://close#",f=window.customFn||function(){},l=window.clayComponents||{},h=window.clayMeta||{},m=window.navigator.userAgent.match(/android/i)?"android":"ios";document.documentElement.classList.add("platform-"+m),a.eachObj(l,function(t,e){i.registerComponent(e)});var p=o("#main-form"),d=new i(s,u,p,h);p.on("submit",function(){location.href=c+encodeURIComponent(JSON.stringify(d.serialize()))}),f.call(d,r),d.build()},{"./lib/clay-config":2,"./vendor/minified":8}],2:[function(t,e,n){"use strict";function r(t,e,n,c){function f(){m=[],p={},d={},g=!1}function l(t,e){if(Array.isArray(t))t.forEach(function(t){l(t,e)});else if(u.includesCapability(c.activeWatchInfo,t.capabilities))if("section"===t.type){var n=i(\'<div class="section">\');e.add(n),l(t.items,n)}else{var r=o.copyObj(t);r.clayId=m.length;var s=new a(r).initialize(v);r.id&&(p[r.id]=s),r.messageKey&&(d[r.messageKey]=s),m.push(s);var f="undefined"!=typeof y[r.messageKey]?y[r.messageKey]:r.defaultValue;s.set("undefined"!=typeof f?f:""),e.add(s.$element)}}function h(t){if(!g)throw new Error("ClayConfig not built. build() must be run before you can run "+t+"()");return!0}var m,p,d,g,v=this,y=o.copyObj(t);v.meta=c,v.$rootContainer=n,v.EVENTS={BEFORE_BUILD:"BEFORE_BUILD",AFTER_BUILD:"AFTER_BUILD",BEFORE_DESTROY:"BEFORE_DESTROY",AFTER_DESTROY:"AFTER_DESTROY"},u.updateProperties(v.EVENTS,{writable:!1}),v.getAllItems=function(){return h("getAllItems"),m},v.getItemByMessageKey=function(t){return h("getItemByMessageKey"),d[t]},v.getItemById=function(t){return h("getItemById"),p[t]},v.getItemsByType=function(t){return h("getItemsByType"),m.filter(function(e){return e.config.type===t})},v.getItemsByGroup=function(t){return h("getItemsByGroup"),m.filter(function(e){return e.config.group===t})},v.serialize=function(){return h("serialize"),y={},o.eachObj(d,function(t,e){y[t]={value:e.get()},e.precision&&(y[t].precision=e.precision)}),y},v.registerComponent=r.registerComponent,v.destroy=function(){var t=n[0];for(v.trigger(v.EVENTS.BEFORE_DESTROY);t.firstChild;)t.removeChild(t.firstChild);return f(),v.trigger(v.EVENTS.AFTER_DESTROY),v},v.build=function(){return g&&v.destroy(),v.trigger(v.EVENTS.BEFORE_BUILD),l(v.config,n),g=!0,v.trigger(v.EVENTS.AFTER_BUILD),v},f(),s.call(v,n),u.updateProperties(v,{writable:!1,configurable:!1}),v.config=e}var i=t("../vendor/minified").HTML,o=t("../vendor/minified")._,a=t("./clay-item"),u=t("../lib/utils"),s=t("./clay-events"),c=t("./component-registry"),f=t("./manipulators");r.registerComponent=function(t){var e=o.copyObj(t);if(c[e.name])return console.warn("Component: "+e.name+" is already registered. If you wish to override the existing functionality, you must provide a new name"),!1;if("string"==typeof e.manipulator&&(e.manipulator=f[t.manipulator],!e.manipulator))throw new Error("The manipulator: "+t.manipulator+" does not exist in the built-in manipulators.");if(!e.manipulator)throw new Error("The manipulator must be defined");if("function"!=typeof e.manipulator.set||"function"!=typeof e.manipulator.get)throw new Error("The manipulator must have both a `get` and `set` method");if(e.style){var n=document.createElement("style");n.type="text/css",n.appendChild(document.createTextNode(e.style)),document.head.appendChild(n)}return c[e.name]=e,!0},e.exports=r},{"../lib/utils":7,"../vendor/minified":8,"./clay-events":3,"./clay-item":4,"./component-registry":5,"./manipulators":6}],3:[function(t,e,n){"use strict";function r(t){function e(t){return t.split(" ").map(function(t){return"|"+t.replace(/^\\|/,"")}).join(" ")}function n(t,e){var n=o.find(u,function(e){return e.handler===t?e:null});return n||(n={handler:t,proxy:e},u.push(n)),n.proxy}function r(t){return o.find(u,function(e){return e.handler===t?e.proxy:null})}var a=this,u=[];a.on=function(r,i){var o=e(r),a=this,u=n(i,function(){i.apply(a,arguments)});return t.on(o,u),a},a.off=function(t){var e=r(t);return e&&i.off(e),a},a.trigger=function(e,n){return t.trigger(e,n),a}}var i=t("../vendor/minified").$,o=t("../vendor/minified")._;e.exports=r},{"../vendor/minified":8}],4:[function(t,e,n){"use strict";function r(t){var e=this,n=i[t.type];if(!n)throw new Error("The component: "+t.type+" is not registered. Make sure to register it with ClayConfig.registerComponent()");var r={i18n:{foo:"bar"}},f=s.extend({},n.defaults||{},t,r),l=s.formatHtml(n.template.trim(),f);e.id=t.id||null,e.messageKey=t.messageKey||null,e.config=t,e.$element=c(l,f),e.$manipulatorTarget=e.$element.select("[data-manipulator-target]"),e.$manipulatorTarget.length||(e.$manipulatorTarget=e.$element),e.initialize=function(t){return"function"==typeof n.initialize&&n.initialize.call(e,o,t),e},u.call(e,e.$manipulatorTarget),s.eachObj(n.manipulator,function(t,n){e[t]=n.bind(e)}),a.updateProperties(e,{writable:!1,configurable:!1})}var i=t("./component-registry"),o=t("../vendor/minified"),a=t("../lib/utils"),u=t("./clay-events"),s=o._,c=o.HTML;e.exports=r},{"../lib/utils":7,"../vendor/minified":8,"./clay-events":3,"./component-registry":5}],5:[function(t,e,n){"use strict";e.exports={}},{}],6:[function(t,e,n){"use strict";function r(){return this.$manipulatorTarget.get("disabled")?this:(this.$element.set("+disabled"),this.$manipulatorTarget.set("disabled",!0),this.trigger("disabled"))}function i(){return this.$manipulatorTarget.get("disabled")?(this.$element.set("-disabled"),this.$manipulatorTarget.set("disabled",!1),this.trigger("enabled")):this}function o(){return this.$element[0].classList.contains("hide")?this:(this.$element.set("+hide"),this.trigger("hide"))}function a(){return this.$element[0].classList.contains("hide")?(this.$element.set("-hide"),this.trigger("show")):this}var u=t("../vendor/minified")._;e.exports={html:{get:function(){return this.$manipulatorTarget.get("innerHTML")},set:function(t){return this.get()===t.toString(10)?this:(this.$manipulatorTarget.set("innerHTML",t),this.trigger("change"))},hide:o,show:a},button:{get:function(){return this.$manipulatorTarget.get("innerHTML")},set:function(t){return this.get()===t.toString(10)?this:(this.$manipulatorTarget.set("innerHTML",t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},val:{get:function(){return this.$manipulatorTarget.get("value")},set:function(t){return this.get()===t.toString(10)?this:(this.$manipulatorTarget.set("value",t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},slider:{get:function(){return parseFloat(this.$manipulatorTarget.get("value"))},set:function(t){var e=this.get();return this.$manipulatorTarget.set("value",t),this.get()===e?this:this.trigger("change")},disable:r,enable:i,hide:o,show:a},checked:{get:function(){return this.$manipulatorTarget.get("checked")},set:function(t){return!this.get()==!t?this:(this.$manipulatorTarget.set("checked",!!t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},radiogroup:{get:function(){return this.$element.select("input:checked").get("value")},set:function(t){return this.get()===t.toString(10)?this:(this.$element.select(\'input[value="\'+t.replace(\'"\',\'\\\\"\')+\'"]\').set("checked",!0),this.trigger("change"))},disable:r,enable:i,hide:o,show:a},checkboxgroup:{get:function(){var t=[];return this.$element.select("input").each(function(e){t.push(!!e.checked)}),t},set:function(t){var e=this;for(t=Array.isArray(t)?t:[];t.length<this.get().length;)t.push(!1);return u.equals(this.get(),t)?this:(e.$element.select("input").set("checked",!1).each(function(e,n){e.checked=!!t[n]}),e.trigger("change"))},disable:r,enable:i,hide:o,show:a},color:{get:function(){return parseInt(this.$manipulatorTarget.get("value"),10)||0},set:function(t){return t=this.roundColorToLayout(t||0),this.get()===t?this:(this.$manipulatorTarget.set("value",t),this.trigger("change"))},disable:r,enable:i,hide:o,show:a}}},{"../vendor/minified":8}],7:[function(t,e,n){"use strict";e.exports.updateProperties=function(t,e){Object.getOwnPropertyNames(t).forEach(function(n){Object.defineProperty(t,n,e)})},e.exports.capabilityMap={PLATFORM_APLITE:{platforms:["aplite"],minFwMajor:0,minFwMinor:0},PLATFORM_BASALT:{platforms:["basalt"],minFwMajor:0,minFwMinor:0},PLATFORM_CHALK:{platforms:["chalk"],minFwMajor:0,minFwMinor:0},PLATFORM_DIORITE:{platforms:["diorite"],minFwMajor:0,minFwMinor:0},PLATFORM_EMERY:{platforms:["emery"],minFwMajor:0,minFwMinor:0},BW:{platforms:["aplite","diorite"],minFwMajor:0,minFwMinor:0},COLOR:{platforms:["basalt","chalk","emery"],minFwMajor:0,minFwMinor:0},MICROPHONE:{platforms:["basalt","chalk","diorite","emery"],minFwMajor:0,minFwMinor:0},SMARTSTRAP:{platforms:["basalt","chalk","diorite","emery"],minFwMajor:3,minFwMinor:4},SMARTSTRAP_POWER:{platforms:["basalt","chalk","emery"],minFwMajor:3,minFwMinor:4},HEALTH:{platforms:["basalt","chalk","diorite","emery"],minFwMajor:3,minFwMinor:10},RECT:{platforms:["aplite","basalt","diorite","emery"],minFwMajor:0,minFwMinor:0},ROUND:{platforms:["chalk"],minFwMajor:0,minFwMinor:0},DISPLAY_144x168:{platforms:["aplite","basalt","diorite"],minFwMajor:0,minFwMinor:0},DISPLAY_180x180_ROUND:{platforms:["chalk"],minFwMajor:0,minFwMinor:0},DISPLAY_200x228:{platforms:["emery"],minFwMajor:0,minFwMinor:0}},e.exports.includesCapability=function(t,n){var r=/^NOT_/,i=[];if(!n||!n.length)return!0;for(var o=n.length-1;o>=0;o--){var a=n[o],u=e.exports.capabilityMap[a.replace(r,"")];!u||u.platforms.indexOf(t.platform)===-1||u.minFwMajor>t.firmware.major||u.minFwMajor===t.firmware.major&&u.minFwMinor>t.firmware.minor?i.push(!!a.match(r)):i.push(!a.match(r))}return i.indexOf(!1)===-1}},{}],8:[function(t,e,n){e.exports=function(){function t(t){return t.substr(0,3)}function e(t){return t!=lt?""+t:""}function n(t,e){return typeof t==e}function r(t){return n(t,"string")}function i(t){return!!t&&n(t,"object")}function o(t){return t&&t.nodeType}function a(t){return n(t,"number")}function u(t){return i(t)&&!!t.getDay}function s(t){return t===!0||t===!1}function c(t){var e=typeof t;return"object"==e?!(!t||!t.getDay):"string"==e||"number"==e||s(t)}function f(t){return t}function l(t,n,r){return e(t).replace(n,r!=lt?r:"")}function h(t){return l(t,/^\\s+|\\s+$/g)}function m(t,e,n){for(var r in t)t.hasOwnProperty(r)&&e.call(n||t,r,t[r]);return t}function p(t,e,n){if(t)for(var r=0;r<t.length;r++)e.call(n||t,t[r],r);return t}function d(t,e,n){var r=[],i=B(e)?e:function(t){return e!=t};return p(t,function(e,o){i.call(n||t,e,o)&&r.push(e)}),r}function g(t,e,n,r){var i=[];return t(e,function(t,o){P(t=n.call(r||e,t,o))?p(t,function(t){i.push(t)}):t!=lt&&i.push(t)}),i}function v(t){var e=0;return m(t,function(t){e++}),e}function y(t){var e=[];return m(t,function(t){e.push(t)}),e}function b(t,e,n){var r=[];return p(t,function(i,o){r.push(e.call(n||t,i,o))}),r}function w(t,e){var n={};return p(t,function(t,r){n[t]=e}),n}function $(t,e){var n=e||{};for(var r in t)n[r]=t[r];return n}function T(t,e){for(var n=e,r=0;r<t.length;r++)n=$(t[r],n);return n}function M(t){return B(t)?t:function(e,n){if(t===e)return n}}function E(t,e,n){return e==lt?n:e<0?Math.max(t.length+e,0):Math.min(t.length,e)}function F(t,e,n,r){for(var i,o=M(e),a=E(t,r,t.length),u=E(t,n,0);u<a;u++)if((i=o.call(t,t[u],u))!=lt)return i}function x(t,e,n){var r=[];if(t)for(var i=E(t,n,t.length),o=E(t,e,0);o<i;o++)r.push(t[o]);return r}function O(t){return b(t,f)}function j(t,e){var n,r=B(t)?t():t,i=B(e)?e():e;return r==i||r!=lt&&i!=lt&&(c(r)||c(i)?u(r)&&u(i)&&+r==+i:P(r)?r.length==i.length&&!F(r,function(t,e){if(!j(t,i[e]))return!0}):!P(i)&&(n=y(r)).length==v(i)&&!F(n,function(t){if(!j(r[t],i[t]))return!0}))}function A(t,e,n){if(B(t))return t.apply(n&&e,b(n||e,f))}function R(t,e,n){return b(t,function(t){return A(t,e,n)})}function L(t){return"\\\\u"+("0000"+t.charCodeAt(0).toString(16)).slice(-4)}function S(t){return l(t,/[\\x00-\\x1f\'"\\u2028\\u2029]/g,L)}function _(t,e){return t.split(e)}function C(t,e){if(dt[t])return dt[t];var n="with(_.isObject(obj)?obj:{}){"+b(_(t,/{{|}}}?/g),function(t,e){var n,r=h(t),i=l(r,/^{/),o=r==i?"esc(":"";return e%2?(n=/^each\\b(\\s+([\\w_]+(\\s*,\\s*[\\w_]+)?)\\s*:)?(.*)/.exec(i))?"each("+(h(n[4])?n[4]:"this")+", function("+n[2]+"){":(n=/^if\\b(.*)/.exec(i))?"if("+n[1]+"){":(n=/^else\\b\\s*(if\\b(.*))?/.exec(i))?"}else "+(n[1]?"if("+n[2]+")":"")+"{":(n=/^\\/(if)?/.exec(i))?n[1]?"}\\n":"});\\n":(n=/^(var\\s.*)/.exec(i))?n[1]+";":(n=/^#(.*)/.exec(i))?n[1]:(n=/(.*)::\\s*(.*)/.exec(i))?"print("+o+\'_.formatValue("\'+S(n[2])+\'",\'+(h(n[1])?n[1]:"this")+(o&&")")+"));\\n":"print("+o+(h(i)?i:"this")+(o&&")")+");\\n":t?\'print("\'+S(t)+\'");\\n\':void 0}).join("")+"}",r=new Function("obj","each","esc","print","_",n),i=function(t,n){var i=[];return r.call(n||t,t,function(t,e){P(t)?p(t,function(t,n){e.call(t,t,n)}):m(t,function(t,n){e.call(n,t,n)})},e||f,function(){A(i.push,i,arguments)},rt),i.join("")};return gt.push(i)>pt&&delete dt[gt.shift()],dt[t]=i}function I(t){return l(t,/[<>\'"&]/g,function(t){return"&#"+t.charCodeAt(0)+";"})}function N(t,e){return C(t,I)(e)}function D(t){return function(e,n,r){return t(this,e,n,r)}}function B(t){return"function"==typeof t&&!t.item}function P(t){return t&&t.length!=lt&&!r(t)&&!o(t)&&!B(t)&&t!==ot}function H(t){return parseFloat(l(t,/^[^\\d-]+/))}function k(t){return t[at]=t[at]||++ct}function q(t,e){var n,r=[],i={};return Q(t,function(t){Q(e(t),function(t){i[n=k(t)]||(r.push(t),i[n]=!0)})}),r}function U(t,e){var n={$position:"absolute",$visibility:"hidden",$display:"block",$height:lt},r=t.get(n),i=t.set(n).get("clientHeight");return t.set(r),i*e+"px"}function Y(t,n,i,o,a){return B(n)?this.on(lt,t,n,i,o):r(o)?this.on(t,n,i,lt,o):this.each(function(r,u){Q(t?G(t,r):r,function(t){Q(e(n).split(/\\s/),function(e){function n(e,n,r){var f=!a,l=a?r:t;if(a)for(var h=Z(a,t);l&&l!=t&&!(f=h(l));)l=l.parentNode;return!f||s!=e||i.apply(X(l),o||[n,u])&&"?"==c||"|"==c}function r(t){n(s,t,t.target)||(t.preventDefault(),t.stopPropagation())}var s=l(e,/[?|]/g),c=l(e,/[^?|]/g),h=("blur"==s||"focus"==s)&&!!a,m=ct++;t.addEventListener(s,r,h),t.M||(t.M={}),t.M[m]=n,i.M=g(Q,[i.M,function(){t.removeEventListener(s,r,h),delete t.M[m]}],f)})})})}function K(t){R(t.M),t.M=lt}function V(t){ft?ft.push(t):setTimeout(t,0)}function z(t,e,n){return G(t,e,n)[0]}function W(t,e,n){var r=X(document.createElement(t));return P(e)||e!=lt&&!i(e)?r.add(e):r.set(e).add(n)}function J(t){return g(Q,t,function(t){var e;return P(t)?J(t):o(t)?(e=t.cloneNode(!0),e.removeAttribute&&e.removeAttribute("id"),e):t})}function X(t,e,n){return B(t)?V(t):new nt(G(t,e,n))}function G(t,e,n){function i(t){return P(t)?g(Q,t,i):t}function a(t){return d(g(Q,t,i),function(t){for(var r=t;r=r.parentNode;)if(r==e[0]||n)return r==e[0]})}return e?1!=(e=G(e)).length?q(e,function(e){return G(t,e,n)}):r(t)?1!=o(e[0])?[]:n?a(e[0].querySelectorAll(t)):e[0].querySelectorAll(t):a(t):r(t)?document.querySelectorAll(t):g(Q,t,i)}function Z(t,e){function n(t,e){var n=RegExp("(^|\\\\s+)"+t+"(?=$|\\\\s)","i");return function(r){return!t||n.test(r[e])}}var i={},u=i;if(B(t))return t;if(a(t))return function(e,n){return n==t};if(!t||"*"==t||r(t)&&(u=/^([\\w-]*)\\.?([\\w-]*)$/.exec(t))){var s=n(u[1],"tagName"),c=n(u[2],"className");return function(t){return 1==o(t)&&s(t)&&c(t)}}return e?function(n){return X(t,e).find(n)!=lt}:(X(t).each(function(t){i[k(t)]=!0}),function(t){return i[k(t)]})}function Q(t,e){return P(t)?p(t,e):t!=lt&&e(t,0),t}function tt(){this.state=null,this.values=[],this.parent=null}function et(){var t=[],e=arguments,n=e.length,r=0,o=0,a=new tt;a.errHandled=function(){o++,a.parent&&a.parent.errHandled()};var u=a.fire=function(e,n){return null==a.state&&null!=e&&(a.state=!!e,a.values=P(n)?n:[n],setTimeout(function(){p(t,function(t){t()})},0)),a};p(e,function c(t,e){try{t.then?t.then(function(t){var o;(i(t)||B(t))&&B(o=t.then)?c(t,e):(a.values[e]=O(arguments),++r==n&&u(!0,n<2?a.values[e]:a.values))},function(t){a.values[e]=O(arguments),u(!1,n<2?a.values[e]:[a.values[e][0],a.values,e])}):t(function(){u(!0,O(arguments))},function(){u(!1,O(arguments))})}catch(o){u(!1,[o,a.values,e])}}),a.stop=function(){return p(e,function(t){t.stop&&t.stop()}),a.stop0&&A(a.stop0)};var s=a.then=function(e,n){var r=et(),u=function(){try{var t=a.state?e:n;B(t)?!function s(t){try{var e,n=0;if((i(t)||B(t))&&B(e=t.then)){if(t===r)throw new TypeError;e.call(t,function(t){n++||s(t)},function(t){n++||r.fire(!1,[t])}),r.stop0=t.stop}else r.fire(!0,[t])}catch(a){if(!n++&&(r.fire(!1,[a]),!o))throw a}}(A(t,it,a.values)):r.fire(a.state,a.values)}catch(u){if(r.fire(!1,[u]),!o)throw u}};return B(n)&&a.errHandled(),r.stop0=a.stop,r.parent=a,null!=a.state?setTimeout(u,0):t.push(u),r};return a.always=function(t){return s(t,t)},a.error=function(t){return s(0,t)},a}function nt(t,e){var n=this,r=0;if(t)for(var i=0,o=t.length;i<o;i++){var a=t[i];if(e&&P(a))for(var u=0,s=a.length;u<s;u++)n[r++]=a[u];else n[r++]=a}else n[r++]=e;n.length=r,n._=!0}function rt(){return new nt(arguments,(!0))}var it,ot=window,at="Nia",ut={},st={},ct=1,ft=/^[ic]/.test(document.readyState)?lt:[],lt=null,ht=_("January,February,March,April,May,June,July,August,September,October,November,December",/,/g),mt=(b(ht,t),_("Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday",/,/g)),pt=(b(mt,t),_("am,pm",/,/g),_("am,am,am,am,am,am,am,am,am,am,am,am,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm",/,/g),99),dt={},gt=[];return $({each:D(p),equals:D(j),find:D(F),dummySort:0,select:function(t,e){return X(t,this,e)},get:function(t,e){var n=this,i=n[0];if(i){if(r(t)){var o,a=/^(\\W*)(.*)/.exec(l(t,/^%/,"@data-")),u=a[1];return o=st[u]?st[u](this,a[2]):"$"==t?n.get("className"):"$$"==t?n.get("@style"):"$$slide"==t?n.get("$height"):"$$fade"==t||"$$show"==t?"hidden"==n.get("$visibility")||"none"==n.get("$display")?0:"$$fade"==t?isNaN(n.get("$opacity",!0))?1:n.get("$opacity",!0):1:"$"==u?ot.getComputedStyle(i,lt).getPropertyValue(l(a[2],/[A-Z]/g,function(t){return"-"+t.toLowerCase()})):"@"==u?i.getAttribute(a[2]):i[a[2]],e?H(o):o}var s={};return(P(t)?Q:m)(t,function(t){s[t]=n.get(t,e)}),s}},set:function(t,e){var n=this;if(e!==it){var i=/^(\\W*)(.*)/.exec(l(l(t,/^\\$float$/,"cssFloat"),/^%/,"@data-")),o=i[1];ut[o]?ut[o](this,i[2],e):"$$fade"==t?this.set({$visibility:e?"visible":"hidden",$opacity:e}):"$$slide"==t?n.set({$visibility:e?"visible":"hidden",$overflow:"hidden",$height:/px/.test(e)?e:function(t,n,r){return U(X(r),e)}}):"$$show"==t?e?n.set({$visibility:e?"visible":"hidden",$display:""}).set({$display:function(t){return"none"==t?"block":t}}):n.set({$display:"none"}):"$$"==t?n.set("@style",e):Q(this,function(n,r){var a=B(e)?e(X(n).get(t),r,n):e;"$"==o?i[2]?n.style[i[2]]=a:Q(a&&a.split(/\\s+/),function(t){var e=l(t,/^[+-]/);/^\\+/.test(t)?n.classList.add(e):/^-/.test(t)?n.classList.remove(e):n.classList.toggle(e)}):"$$scrollX"==t?n.scroll(a,X(n).get("$$scrollY")):"$$scrollY"==t?n.scroll(X(n).get("$$scrollX"),a):"@"==o?a==lt?n.removeAttribute(i[2]):n.setAttribute(i[2],a):n[i[2]]=a})}else r(t)||B(t)?n.set("$",t):m(t,function(t,e){n.set(t,e)});return n},add:function(t,e){return this.each(function(n,r){function i(t){if(P(t))Q(t,i);else if(B(t))i(t(n,r));else if(t!=lt){var u=o(t)?t:document.createTextNode(t);a?a.parentNode.insertBefore(u,a.nextSibling):e?e(u,n,n.parentNode):n.appendChild(u),a=u}}var a;i(r&&!B(t)?J(t):t)})},on:Y,trigger:function(t,e){return this.each(function(n,r){for(var i=!0,o=n;o&&i;)m(o.M,function(r,o){i=i&&o(t,e,n)}),o=o.parentNode})},ht:function(t,e){var n=arguments.length>2?T(x(arguments,1)):e;return this.set("innerHTML",B(t)?t(n):/{{/.test(t)?N(t,n):/^#\\S+$/.test(t)?N(z(t).text,n):t)}},nt.prototype),$({request:function(t,n,r,i){var o,a=i||{},u=0,s=et(),c=r&&r.constructor==a.constructor;try{s.xhr=o=new XMLHttpRequest,s.stop0=function(){o.abort()},c&&(r=g(m,r,function(t,e){return g(Q,e,function(e){return encodeURIComponent(t)+(e!=lt?"="+encodeURIComponent(e):"")})}).join("&")),r==lt||/post/i.test(t)||(n+="?"+r,r=lt),o.open(t,n,!0,a.user,a.pass),c&&/post/i.test(t)&&o.setRequestHeader("Content-Type","application/x-www-form-urlencoded"),m(a.headers,function(t,e){o.setRequestHeader(t,e)}),m(a.xhr,function(t,e){o[t]=e}),o.onreadystatechange=function(){4!=o.readyState||u++||(o.status>=200&&o.status<300?s.fire(!0,[o.responseText,o]):s.fire(!1,[o.status,o.responseText,o]))},o.send(r)}catch(f){u||s.fire(!1,[0,lt,e(f)])}return s},ready:V,off:K,wait:function(t,e){var n=et(),r=setTimeout(function(){n.fire(!0,e)},t);return n.stop0=function(){n.fire(!1),clearTimeout(r)},n}},X),$({each:p,toObject:w,find:F,equals:j,copyObj:$,extend:function(t){return T(x(arguments,1),t)},eachObj:m,isObject:i,format:function(t,e,n){return C(t,n)(e)},template:C,formatHtml:N,promise:et},rt),document.addEventListener("DOMContentLoaded",function(){R(ft),ft=lt},!1),{HTML:function(){var t=W("div");return rt(A(t.ht,t,arguments)[0].childNodes)},_:rt,$:X,$$:z,M:nt,getter:st,setter:ut}}()},{}]},{},[1])</script></body></html>';
15
+},{}],"pebble-clay":[function(t,e,n){"use strict";function r(t,e,n){function r(){i.meta={activeWatchInfo:Pebble.getActiveWatchInfo&&Pebble.getActiveWatchInfo(),accountToken:Pebble.getAccountToken(),watchToken:Pebble.getWatchToken(),userData:s(n.userData||{})}}function o(t,e,n){Array.isArray(t)?t.forEach(function(t){o(t,e,n)}):"section"===t.type?o(t.items,e,n):e(t)&&n(t)}var i=this;if(!Array.isArray(t))throw new Error("config must be an Array");if(e&&"function"!=typeof e)throw new Error('customFn must be a function or "null"');n=n||{},i.config=s(t),i.customFn=e||function(){},i.components={},i.meta={activeWatchInfo:null,accountToken:"",watchToken:"",userData:{}},i.version=c,n.autoHandleEvents!==!1&&"undefined"!=typeof Pebble?(Pebble.addEventListener("showConfiguration",function(){r(),Pebble.openURL(i.generateUrl())}),Pebble.addEventListener("webviewclosed",function(t){t&&t.response&&Pebble.sendAppMessage(i.getSettings(t.response),function(){console.log("Sent config data to Pebble")},function(t){console.log("Failed to send config data!"),console.log(JSON.stringify(t))})})):"undefined"!=typeof Pebble&&Pebble.addEventListener("ready",function(){r()}),o(i.config,function(t){return a[t.type]},function(t){i.registerComponent(a[t.type])}),o(i.config,function(t){return t.appKey},function(){throw new Error("appKeys are no longer supported. Please follow the migration guide to upgrade your project")})}var o=t("./tmp/config-page.html"),i=t("tosource"),a=t("./src/scripts/components"),s=t("deepcopy/build/deepcopy.min"),c=t("./package.json").version,l=t("message_keys");r.prototype.registerComponent=function(t){this.components[t.name]=t},r.prototype.generateUrl=function(){var t={},e=!Pebble||"pypkjs"===Pebble.platform,n=e?"$$$RETURN_TO$$$":"pebblejs://close#";try{t=JSON.parse(localStorage.getItem("clay-settings"))||{}}catch(a){console.error(a.toString())}var s=o.replace("$$RETURN_TO$$",n).replace("$$CUSTOM_FN$$",i(this.customFn)).replace("$$CONFIG$$",i(this.config)).replace("$$SETTINGS$$",i(t)).replace("$$COMPONENTS$$",i(this.components)).replace("$$META$$",i(this.meta));return e?r.encodeDataUri(s,"http://clay.pebble.com.s3-website-us-west-2.amazonaws.com/#"):r.encodeDataUri(s)},r.prototype.getSettings=function(t,e){var n={};t=t.match(/^\{/)?t:decodeURIComponent(t);try{n=JSON.parse(t)}catch(o){throw new Error("The provided response was not valid JSON")}var i={};return Object.keys(n).forEach(function(t){"object"==typeof n[t]&&n[t]?i[t]=n[t].value:i[t]=n[t]}),localStorage.setItem("clay-settings",JSON.stringify(i)),e===!1?n:r.prepareSettingsForAppMessage(n)},r.prototype.setSettings=function(t,e){var n={};try{n=JSON.parse(localStorage.getItem("clay-settings"))||{}}catch(r){console.error(r.toString())}if("object"==typeof t){var o=t;Object.keys(o).forEach(function(t){n[t]=o[t]})}else n[t]=e;localStorage.setItem("clay-settings",JSON.stringify(n))},r.encodeDataUri=function(t,e){return e="undefined"!=typeof e?e:"data:text/html;charset=utf-8,",e+encodeURIComponent(t)},r.prepareForAppMessage=function(t){function e(t,e){return Math.floor(t*Math.pow(10,e||0))}var n;return Array.isArray(t)?(n=[],t.forEach(function(t,e){n[e]=r.prepareForAppMessage(t)})):n="object"==typeof t&&t?"number"==typeof t.value?e(t.value,t.precision):Array.isArray(t.value)?t.value.map(function(n){return"number"==typeof n?e(n,t.precision):n}):r.prepareForAppMessage(t.value):"boolean"==typeof t?t?1:0:t,n},r.prepareSettingsForAppMessage=function(t){var e={};Object.keys(t).forEach(function(n){var r=t[n],o=n.match(/(.+?)(?:\[(\d*)\])?$/);if(!o[2])return void(e[n]=r);var i=parseInt(o[2],10);n=o[1],"undefined"==typeof e[n]&&(e[n]=[]),e[n][i]=r});var n={};return Object.keys(e).forEach(function(t){var o=l[t],i=r.prepareForAppMessage(e[t]);i=Array.isArray(i)?i:[i],i.forEach(function(t,e){n[o+e]=t})}),Object.keys(n).forEach(function(t){if(Array.isArray(n[t]))throw new Error('Clay does not support 2 dimensional arrays for item values. Make sure you are not attempting to use array syntax (eg: "myMessageKey[2]") in the messageKey for components that return an array, such as a checkboxgroup')}),n},e.exports=r},{"./package.json":7,"./src/scripts/components":13,"./tmp/config-page.html":42,"deepcopy/build/deepcopy.min":3,message_keys:void 0,tosource:6}]},{},["pebble-clay"])("pebble-clay")});
0 16
\ No newline at end of file
1 17
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'button',
5
+  template: require('../../templates/components/button.tpl'),
6
+  style: require('../../styles/clay/components/button.scss'),
7
+  manipulator: 'button',
8
+  defaults: {
9
+    primary: false,
10
+    attributes: {},
11
+    description: ''
12
+  }
13
+};
0 14
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'checkboxgroup',
5
+  template: require('../../templates/components/checkboxgroup.tpl'),
6
+  style: require('../../styles/clay/components/checkboxgroup.scss'),
7
+  manipulator: 'checkboxgroup',
8
+  defaults: {
9
+    label: '',
10
+    options: [],
11
+    description: ''
12
+  }
13
+};
0 14
new file mode 100644
... ...
@@ -0,0 +1,327 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'color',
5
+  template: require('../../templates/components/color.tpl'),
6
+  style: require('../../styles/clay/components/color.scss'),
7
+  manipulator: 'color',
8
+  defaults: {
9
+    label: '',
10
+    description: ''
11
+  },
12
+  initialize: function(minified, clay) {
13
+    var HTML = minified.HTML;
14
+    var self = this;
15
+
16
+    /**
17
+     * @param {string|boolean|number} color
18
+     * @returns {string}
19
+     */
20
+    function cssColor(color) {
21
+      if (typeof color === 'number') {
22
+        color = color.toString(16);
23
+      } else if (!color) {
24
+        return 'transparent';
25
+      }
26
+
27
+      color = padColorString(color);
28
+
29
+      return '#' + (useSunlight ? sunlightColorMap[color] : color);
30
+    }
31
+
32
+    /**
33
+     * @param {string} color
34
+     * @return {string}
35
+     */
36
+    function padColorString(color) {
37
+      color = color.toLowerCase();
38
+
39
+      while (color.length < 6) {
40
+        color = '0' + color;
41
+      }
42
+
43
+      return color;
44
+    }
45
+
46
+    /**
47
+     * @param {number|string} value
48
+     * @returns {string|*}
49
+     */
50
+    function normalizeColor(value) {
51
+      switch (typeof value) {
52
+        case 'number': return padColorString(value.toString(16));
53
+        case 'string': return value.replace(/^#|^0x/, '');
54
+        default: return value;
55
+      }
56
+    }
57
+
58
+    /**
59
+     * @param {Array.<Array>} layout
60
+     * @returns {Array}
61
+     */
62
+    function flattenLayout(layout) {
63
+      return layout.reduce(function(a, b) {
64
+        return a.concat(b);
65
+      }, []);
66
+    }
67
+
68
+    /**
69
+     * Convert HEX color to LAB.
70
+     * Adapted from: https://github.com/antimatter15/rgb-lab
71
+     * @param {string} hex
72
+     * @returns {Array} - [l, a, b]
73
+     */
74
+    function hex2lab(hex) {
75
+      hex = hex.replace(/^#|^0x/, '');
76
+
77
+      var r = parseInt(hex.slice(0, 2), 16) / 255;
78
+      var g = parseInt(hex.slice(2, 4), 16) / 255;
79
+      var b = parseInt(hex.slice(4), 16) / 255;
80
+
81
+      r = (r > 0.04045) ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
82
+      g = (g > 0.04045) ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
83
+      b = (b > 0.04045) ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
84
+
85
+      var x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
86
+      var y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.00000;
87
+      var z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
88
+
89
+      x = (x > 0.008856) ? Math.pow(x, 1 / 3) : (7.787 * x) + 16 / 116;
90
+      y = (y > 0.008856) ? Math.pow(y, 1 / 3) : (7.787 * y) + 16 / 116;
91
+      z = (z > 0.008856) ? Math.pow(z, 1 / 3) : (7.787 * z) + 16 / 116;
92
+
93
+      return [(116 * y) - 16, 500 * (x - y), 200 * (y - z)];
94
+    }
95
+
96
+    /**
97
+     * Find the perceptual color distance between two LAB colors
98
+     * @param {Array} labA
99
+     * @param {Array} labB
100
+     * @returns {number}
101
+     */
102
+    function deltaE(labA, labB) {
103
+      var deltaL = labA[0] - labB[0];
104
+      var deltaA = labA[1] - labB[1];
105
+      var deltaB = labA[2] - labB[2];
106
+
107
+      return Math.sqrt(Math.pow(deltaL, 2) +
108
+                       Math.pow(deltaA, 2) +
109
+                       Math.pow(deltaB, 2));
110
+    }
111
+
112
+    /**
113
+     * Returns the layout based on the connected watch
114
+     * @returns {Array}
115
+     */
116
+    function autoLayout() {
117
+      if (!clay.meta.activeWatchInfo ||
118
+          clay.meta.activeWatchInfo.firmware.major === 2 ||
119
+          ['aplite', 'diorite'].indexOf(clay.meta.activeWatchInfo.platform) > -1 &&
120
+          !self.config.allowGray) {
121
+        return standardLayouts.BLACK_WHITE;
122
+      }
123
+
124
+      if (['aplite', 'diorite'].indexOf(clay.meta.activeWatchInfo.platform) > -1 &&
125
+          self.config.allowGray) {
126
+        return standardLayouts.GRAY;
127
+      }
128
+
129
+      return standardLayouts.COLOR;
130
+    }
131
+
132
+    /**
133
+     * @param {number|string} color
134
+     * @return {number}
135
+     */
136
+    self.roundColorToLayout = function(color) {
137
+      var itemValue = normalizeColor(color);
138
+
139
+      // if the color is not in the layout we will need find the closest match
140
+      if (colorList.indexOf(itemValue) === -1) {
141
+        var itemValueLAB = hex2lab(itemValue);
142
+        var differenceArr = colorList.map(function(color) {
143
+          var colorLAB = hex2lab(normalizeColor(color));
144
+          return deltaE(itemValueLAB, colorLAB);
145
+        });
146
+
147
+        // Get the lowest number from the differenceArray
148
+        var lowest = Math.min.apply(Math, differenceArr);
149
+
150
+        // Get the index for that lowest number
151
+        var index = differenceArr.indexOf(lowest);
152
+        itemValue = colorList[index];
153
+      }
154
+
155
+      return parseInt(itemValue, 16);
156
+    };
157
+
158
+    var useSunlight = self.config.sunlight !== false;
159
+    var sunlightColorMap = {
160
+      '000000': '000000', '000055': '001e41', '0000aa': '004387', '0000ff': '0068ca',
161
+      '005500': '2b4a2c', '005555': '27514f', '0055aa': '16638d', '0055ff': '007dce',
162
+      '00aa00': '5e9860', '00aa55': '5c9b72', '00aaaa': '57a5a2', '00aaff': '4cb4db',
163
+      '00ff00': '8ee391', '00ff55': '8ee69e', '00ffaa': '8aebc0', '00ffff': '84f5f1',
164
+      '550000': '4a161b', '550055': '482748', '5500aa': '40488a', '5500ff': '2f6bcc',
165
+      '555500': '564e36', '555555': '545454', '5555aa': '4f6790', '5555ff': '4180d0',
166
+      '55aa00': '759a64', '55aa55': '759d76', '55aaaa': '71a6a4', '55aaff': '69b5dd',
167
+      '55ff00': '9ee594', '55ff55': '9de7a0', '55ffaa': '9becc2', '55ffff': '95f6f2',
168
+      'aa0000': '99353f', 'aa0055': '983e5a', 'aa00aa': '955694', 'aa00ff': '8f74d2',
169
+      'aa5500': '9d5b4d', 'aa5555': '9d6064', 'aa55aa': '9a7099', 'aa55ff': '9587d5',
170
+      'aaaa00': 'afa072', 'aaaa55': 'aea382', 'aaaaaa': 'ababab', 'ffffff': 'ffffff',
171
+      'aaaaff': 'a7bae2', 'aaff00': 'c9e89d', 'aaff55': 'c9eaa7', 'aaffaa': 'c7f0c8',
172
+      'aaffff': 'c3f9f7', 'ff0000': 'e35462', 'ff0055': 'e25874', 'ff00aa': 'e16aa3',
173
+      'ff00ff': 'de83dc', 'ff5500': 'e66e6b', 'ff5555': 'e6727c', 'ff55aa': 'e37fa7',
174
+      'ff55ff': 'e194df', 'ffaa00': 'f1aa86', 'ffaa55': 'f1ad93', 'ffaaaa': 'efb5b8',
175
+      'ffaaff': 'ecc3eb', 'ffff00': 'ffeeab', 'ffff55': 'fff1b5', 'ffffaa': 'fff6d3'
176
+    };
177
+
178
+    /* eslint-disable  comma-spacing, no-multi-spaces, max-len,
179
+     standard/array-bracket-even-spacing */
180
+    var standardLayouts = {
181
+      COLOR: [
182
+        [false   , false   , '55ff00', 'aaff55', false   , 'ffff55', 'ffffaa', false   , false   ],
183
+        [false   , 'aaffaa', '55ff55', '00ff00', 'aaff00', 'ffff00', 'ffaa55', 'ffaaaa', false   ],
184
+        ['55ffaa', '00ff55', '00aa00', '55aa00', 'aaaa55', 'aaaa00', 'ffaa00', 'ff5500', 'ff5555'],
185
+        ['aaffff', '00ffaa', '00aa55', '55aa55', '005500', '555500', 'aa5500', 'ff0000', 'ff0055'],
186
+        [false   , '55aaaa', '00aaaa', '005555', 'ffffff', '000000', 'aa5555', 'aa0000', false   ],
187
+        ['55ffff', '00ffff', '00aaff', '0055aa', 'aaaaaa', '555555', '550000', 'aa0055', 'ff55aa'],
188
+        ['55aaff', '0055ff', '0000ff', '0000aa', '000055', '550055', 'aa00aa', 'ff00aa', 'ffaaff'],
189
+        [false   , '5555aa', '5555ff', '5500ff', '5500aa', 'aa00ff', 'ff00ff', 'ff55ff', false   ],
190
+        [false   , false   , false   , 'aaaaff', 'aa55ff', 'aa55aa', false   , false   , false   ]
191
+      ],
192
+      GRAY: [
193
+        ['000000', 'aaaaaa', 'ffffff']
194
+      ],
195
+      BLACK_WHITE: [
196
+        ['000000', 'ffffff']
197
+      ]
198
+    };
199
+    /* eslint-enable */
200
+
201
+    var layout = self.config.layout || autoLayout();
202
+
203
+    if (typeof layout === 'string') {
204
+      layout = standardLayouts[layout];
205
+    }
206
+
207
+    // make sure layout is a 2D array
208
+    if (!Array.isArray(layout[0])) {
209
+      layout = [layout];
210
+    }
211
+
212
+    var colorList = flattenLayout(layout).map(function(item) {
213
+      return normalizeColor(item);
214
+    }).filter(function(item) {
215
+      return item;
216
+    });
217
+
218
+    var grid = '';
219
+    var rows = layout.length;
220
+    var cols = 0;
221
+    layout.forEach(function(row) {
222
+      cols = row.length > cols ? row.length : cols;
223
+    });
224
+    var itemWidth = 100 / cols;
225
+    var itemHeight = 100 / rows;
226
+    var $elem = self.$element;
227
+
228
+    for (var i = 0; i < rows; i++) {
229
+      for (var j = 0; j < cols; j++) {
230
+
231
+        var color = normalizeColor(layout[i][j]);
232
+        var selectable = (color ? ' selectable' : '');
233
+
234
+        var roundedTL = (i === 0 && j === 0) || i === 0 && !layout[i][j - 1] ||
235
+                        !layout[i][j - 1] && !layout[i - 1][j] ?
236
+          ' rounded-tl' :
237
+          '';
238
+
239
+        var roundedTR = i === 0 && !layout[i][j + 1] ||
240
+                        !layout[i][j + 1] && !layout[i - 1][j] ?
241
+          ' rounded-tr ' :
242
+          '';
243
+
244
+        var roundedBL = (i === layout.length - 1 && j === 0) ||
245
+                        i === layout.length - 1 && !layout[i][j - 1] ||
246
+                        !layout[i][j - 1] && !layout[i + 1][j] ?
247
+          ' rounded-bl' :
248
+          '';
249
+
250
+        var roundedBR = i === layout.length - 1 && !layout[i][j + 1] ||
251
+                        !layout[i][j + 1] && !layout[i + 1][j] ?
252
+          ' rounded-br' :
253
+          '';
254
+
255
+        grid += '<i ' +
256
+          'class="color-box ' + selectable + roundedTL + roundedTR + roundedBL +
257
+              roundedBR + '" ' +
258
+          (color ? 'data-value="' + parseInt(color, 16) + '" ' : '') +
259
+          'style="' +
260
+            'width:' + itemWidth + '%; ' +
261
+            'height:' + itemHeight + '%; ' +
262
+            'background:' + cssColor(color) + ';">' +
263
+        '</i>';
264
+      }
265
+    }
266
+
267
+    // on very small layouts the boxes end up huge. The following adds extra padding
268
+    // to prevent them from being so big.
269
+    var extraPadding = 0;
270
+    if (cols === 3) {
271
+      extraPadding = 5;
272
+    }
273
+    if (cols === 2) {
274
+      extraPadding = 8;
275
+    }
276
+    var vPadding = (extraPadding * itemWidth / itemHeight) + '%';
277
+    var hPadding = extraPadding + '%';
278
+    $elem.select('.color-box-container')
279
+      .add(HTML(grid))
280
+      .set('$paddingTop', vPadding)
281
+      .set('$paddingRight', hPadding)
282
+      .set('$paddingBottom', vPadding)
283
+      .set('$paddingLeft', hPadding);
284
+
285
+    $elem.select('.color-box-wrap').set(
286
+      '$paddingBottom',
287
+      (itemWidth / itemHeight * 100) + '%'
288
+    );
289
+
290
+    var $valueDisplay = $elem.select('.value');
291
+    var $picker = $elem.select('.picker-wrap');
292
+    var disabled = self.$manipulatorTarget.get('disabled');
293
+
294
+    $elem.select('label').on('click', function() {
295
+      if (!disabled) {
296
+        $picker.set('show'); // toggle visibility
297
+      }
298
+    });
299
+
300
+    self.on('change', function() {
301
+      var value = self.get();
302
+      $valueDisplay.set('$background-color', cssColor(value));
303
+      $elem.select('.color-box').set('-selected');
304
+      $elem.select('.color-box[data-value="' + value + '"]').set('+selected');
305
+    });
306
+
307
+    $elem.select('.color-box.selectable').on('click', function(ev) {
308
+      self.set(parseInt(ev.target.dataset.value, 10));
309
+      $picker.set('-show');
310
+    });
311
+
312
+    $picker.on('click', function() {
313
+      $picker.set('-show');
314
+    });
315
+
316
+    self.on('disabled', function() {
317
+      disabled = true;
318
+    });
319
+
320
+    self.on('enabled', function() {
321
+      disabled = false;
322
+    });
323
+
324
+    // expose layout for testing
325
+    self._layout = layout;
326
+  }
327
+};
0 328
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'footer',
5
+  template: require('../../templates/components/footer.tpl'),
6
+  manipulator: 'html'
7
+};
0 8
new file mode 100644
... ...
@@ -0,0 +1,10 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'heading',
5
+  template: require('../../templates/components/heading.tpl'),
6
+  manipulator: 'html',
7
+  defaults: {
8
+    size: 4
9
+  }
10
+};
0 11
new file mode 100644
... ...
@@ -0,0 +1,16 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  color: require('./color'),
5
+  footer: require('./footer'),
6
+  heading: require('./heading'),
7
+  input: require('./input'),
8
+  select: require('./select'),
9
+  submit: require('./submit'),
10
+  text: require('./text'),
11
+  toggle: require('./toggle'),
12
+  radiogroup: require('./radiogroup'),
13
+  checkboxgroup: require('./checkboxgroup'),
14
+  button: require('./button'),
15
+  slider: require('./slider')
16
+};
0 17
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'input',
5
+  template: require('../../templates/components/input.tpl'),
6
+  style: require('../../styles/clay/components/input.scss'),
7
+  manipulator: 'val',
8
+  defaults: {
9
+    label: '',
10
+    description: '',
11
+    attributes: {}
12
+  }
13
+};
0 14
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'radiogroup',
5
+  template: require('../../templates/components/radiogroup.tpl'),
6
+  style: require('../../styles/clay/components/radiogroup.scss'),
7
+  manipulator: 'radiogroup',
8
+  defaults: {
9
+    label: '',
10
+    options: [],
11
+    description: '',
12
+    attributes: {}
13
+  }
14
+};
0 15
new file mode 100644
... ...
@@ -0,0 +1,33 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'select',
5
+  template: require('../../templates/components/select.tpl'),
6
+  style: require('../../styles/clay/components/select.scss'),
7
+  manipulator: 'val',
8
+  defaults: {
9
+    label: '',
10
+    options: [],
11
+    description: '',
12
+    attributes: {}
13
+  },
14
+  initialize: function() {
15
+    var self = this;
16
+
17
+    var $value = self.$element.select('.value');
18
+
19
+    /**
20
+     * Updates the HTML value of the component to match the slected option's label
21
+     * @return {void}
22
+     */
23
+    function setValueDisplay() {
24
+      var selectedIndex = self.$manipulatorTarget.get('selectedIndex');
25
+      var $options = self.$manipulatorTarget.select('option');
26
+      var value = $options[selectedIndex] && $options[selectedIndex].innerHTML;
27
+      $value.set('innerHTML', value);
28
+    }
29
+
30
+    setValueDisplay();
31
+    self.on('change', setValueDisplay);
32
+  }
33
+};
0 34
new file mode 100644
... ...
@@ -0,0 +1,50 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'slider',
5
+  template: require('../../templates/components/slider.tpl'),
6
+  style: require('../../styles/clay/components/slider.scss'),
7
+  manipulator: 'slider',
8
+  defaults: {
9
+    label: '',
10
+    description: '',
11
+    min: 0,
12
+    max: 100,
13
+    step: 1,
14
+    attributes: {}
15
+  },
16
+  initialize: function() {
17
+    var self = this;
18
+
19
+    var $value = self.$element.select('.value');
20
+    var $valuePad = self.$element.select('.value-pad');
21
+    var $slider = self.$manipulatorTarget;
22
+
23
+    /**
24
+     * Sets the value display
25
+     * @return {void}
26
+     */
27
+    function setValueDisplay() {
28
+      var value = self.get().toFixed(self.precision);
29
+      $value.set('value', value);
30
+      $valuePad.set('innerHTML', value);
31
+    }
32
+
33
+    var step = $slider.get('step');
34
+    step = step.toString(10).split('.')[1];
35
+    self.precision = step ? step.length : 0;
36
+
37
+    self.on('change', setValueDisplay);
38
+    $slider.on('|input', setValueDisplay);
39
+    setValueDisplay();
40
+
41
+    $value.on('|input', function() {
42
+      $valuePad.set('innerHTML', this.get('value'));
43
+    });
44
+
45
+    $value.on('|change', function() {
46
+      self.set(this.get('value'));
47
+      setValueDisplay();
48
+    });
49
+  }
50
+};
0 51
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'submit',
5
+  template: require('../../templates/components/submit.tpl'),
6
+  style: require('../../styles/clay/components/submit.scss'),
7
+  manipulator: 'button',
8
+  defaults: {
9
+    attributes: {}
10
+  }
11
+};
0 12
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'text',
5
+  template: require('../../templates/components/text.tpl'),
6
+  manipulator: 'html'
7
+};
0 8
new file mode 100644
... ...
@@ -0,0 +1,13 @@
1
+'use strict';
2
+
3
+module.exports = {
4
+  name: 'toggle',
5
+  template: require('../../templates/components/toggle.tpl'),
6
+  style: require('../../styles/clay/components/toggle.scss'),
7
+  manipulator: 'checked',
8
+  defaults: {
9
+    label: '',
10
+    description: '',
11
+    attributes: {}
12
+  }
13
+};
0 14
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+'use strict';
2
+
3
+var minified = require('./vendor/minified');
4
+var ClayConfig = require('./lib/clay-config');
5
+
6
+var $ = minified.$;
7
+var _ = minified._;
8
+
9
+var config = _.extend([], window.clayConfig || []);
10
+var settings = _.extend({}, window.claySettings || {});
11
+var returnTo = window.returnTo || 'pebblejs://close#';
12
+var customFn = window.customFn || function() {};
13
+var clayComponents = window.clayComponents || {};
14
+var clayMeta = window.clayMeta || {};
15
+
16
+var platform = window.navigator.userAgent.match(/android/i) ? 'android' : 'ios';
17
+document.documentElement.classList.add('platform-' + platform);
18
+
19
+// Register the passed components
20
+_.eachObj(clayComponents, function(key, component) {
21
+  ClayConfig.registerComponent(component);
22
+});
23
+
24
+var $mainForm = $('#main-form');
25
+var clayConfig = new ClayConfig(settings, config, $mainForm, clayMeta);
26
+
27
+// add listeners here
28
+$mainForm.on('submit', function() {
29
+  // Set the return URL depending on the runtime environment
30
+  location.href = returnTo +
31
+                  encodeURIComponent(JSON.stringify(clayConfig.serialize()));
32
+});
33
+
34
+// Run the custom function in the context of the ClayConfig
35
+customFn.call(clayConfig, minified);
36
+
37
+// Now that we have given the dev's custom code to run and attach listeners,
38
+// we build the config
39
+clayConfig.build();
0 40
new file mode 100644
... ...
@@ -0,0 +1,314 @@
1
+'use strict';
2
+
3
+/**
4
+ * A Clay config Item
5
+ * @typedef {Object} Clay~ConfigItem
6
+ * @property {string} type
7
+ * @property {string|boolean|number} defaultValue
8
+ * @property {string} [messageKey]
9
+ * @property {string} [id]
10
+ * @property {string} [label]
11
+ * @property {Object} [attributes]
12
+ * @property {Array} [options]
13
+ * @property {Array} [items]
14
+ * @property {Array} [capabilities]
15
+ */
16
+
17
+var HTML = require('../vendor/minified').HTML;
18
+var _ = require('../vendor/minified')._;
19
+var ClayItem = require('./clay-item');
20
+var utils = require('../lib/utils');
21
+var ClayEvents = require('./clay-events');
22
+var componentStore = require('./component-registry');
23
+var manipulators = require('./manipulators');
24
+
25
+/**
26
+ * @extends ClayEvents
27
+ * @param {Object} settings - setting that were set from a previous session
28
+ * @param {Array|Object} config
29
+ * @param {M} $rootContainer
30
+ * @param {Object} meta
31
+ * @constructor
32
+ */
33
+function ClayConfig(settings, config, $rootContainer, meta) {
34
+  var self = this;
35
+
36
+  var _settings = _.copyObj(settings);
37
+  var _items;
38
+  var _itemsById;
39
+  var _itemsByMessageKey;
40
+  var _isBuilt;
41
+
42
+  /**
43
+   * Initialize the item arrays and objects
44
+   * @private
45
+   * @return {void}
46
+   */
47
+  function _initializeItems() {
48
+    _items = [];
49
+    _itemsById = {};
50
+    _itemsByMessageKey = {};
51
+    _isBuilt = false;
52
+  }
53
+
54
+  /**
55
+   * Add item(s) to the config
56
+   * @param {Clay~ConfigItem|Array} item
57
+   * @param {M} $container
58
+   * @return {void}
59
+   */
60
+  function _addItems(item, $container) {
61
+    if (Array.isArray(item)) {
62
+      item.forEach(function(item) {
63
+        _addItems(item, $container);
64
+      });
65
+    } else if (utils.includesCapability(meta.activeWatchInfo, item.capabilities)) {
66
+      if (item.type === 'section') {
67
+        var $wrapper = HTML('<div class="section">');
68
+        $container.add($wrapper);
69
+        _addItems(item.items, $wrapper);
70
+      } else {
71
+        var _item = _.copyObj(item);
72
+        _item.clayId = _items.length;
73
+
74
+        var clayItem = new ClayItem(_item).initialize(self);
75
+
76
+        if (_item.id) {
77
+          _itemsById[_item.id] = clayItem;
78
+        }
79
+
80
+        if (_item.messageKey) {
81
+          _itemsByMessageKey[_item.messageKey] = clayItem;
82
+        }
83
+
84
+        _items.push(clayItem);
85
+
86
+        // set the value of the item via the manipulator to ensure consistency
87
+        var value = typeof _settings[_item.messageKey] !== 'undefined' ?
88
+          _settings[_item.messageKey] :
89
+          _item.defaultValue;
90
+
91
+        clayItem.set(typeof value !== 'undefined' ? value : '');
92
+
93
+        $container.add(clayItem.$element);
94
+      }
95
+    }
96
+  }
97
+
98
+  /**
99
+   * Throws if the config has not been built yet.
100
+   * @param {string} fnName
101
+   * @returns {boolean}
102
+   * @private
103
+   */
104
+  function _checkBuilt(fnName) {
105
+    if (!_isBuilt) {
106
+      throw new Error(
107
+        'ClayConfig not built. build() must be run before ' +
108
+        'you can run ' + fnName + '()'
109
+      );
110
+    }
111
+    return true;
112
+  }
113
+
114
+  self.meta = meta;
115
+  self.$rootContainer = $rootContainer;
116
+
117
+  self.EVENTS = {
118
+    /**
119
+     * Called before framework has initialized. This is when you would attach your
120
+     * custom components.
121
+     * @const
122
+     */
123
+    BEFORE_BUILD: 'BEFORE_BUILD',
124
+
125
+    /**
126
+     * Called after the config has been parsed and all components have their initial
127
+     * value set
128
+     * @const
129
+     */
130
+    AFTER_BUILD: 'AFTER_BUILD',
131
+
132
+    /**
133
+     * Called if .build() is executed after the page has already been built and
134
+     * before the existing content is destroyed
135
+     * @const
136
+     */
137
+    BEFORE_DESTROY: 'BEFORE_DESTROY',
138
+
139
+    /**
140
+     * Called if .build() is executed after the page has already been built and after
141
+     * the existing content is destroyed
142
+     * @const
143
+     */
144
+    AFTER_DESTROY: 'AFTER_DESTROY'
145
+  };
146
+  utils.updateProperties(self.EVENTS, {writable: false});
147
+
148
+  /**
149
+   * @returns {Array.<ClayItem>}
150
+   */
151
+  self.getAllItems = function() {
152
+    _checkBuilt('getAllItems');
153
+    return _items;
154
+  };
155
+
156
+  /**
157
+   * @param {string} messageKey
158
+   * @returns {ClayItem}
159
+   */
160
+  self.getItemByMessageKey = function(messageKey) {
161
+    _checkBuilt('getItemByMessageKey');
162
+    return _itemsByMessageKey[messageKey];
163
+  };
164
+
165
+  /**
166
+   * @param {string} id
167
+   * @returns {ClayItem}
168
+   */
169
+  self.getItemById = function(id) {
170
+    _checkBuilt('getItemById');
171
+    return _itemsById[id];
172
+  };
173
+
174
+  /**
175
+   * @param {string} type
176
+   * @returns {Array.<ClayItem>}
177
+   */
178
+  self.getItemsByType = function(type) {
179
+    _checkBuilt('getItemsByType');
180
+    return _items.filter(function(item) {
181
+      return item.config.type === type;
182
+    });
183
+  };
184
+
185
+  /**
186
+   * @param {string} group
187
+   * @returns {Array.<ClayItem>}
188
+   */
189
+  self.getItemsByGroup = function(group) {
190
+    _checkBuilt('getItemsByGroup');
191
+    return _items.filter(function(item) {
192
+      return item.config.group === group;
193
+    });
194
+  };
195
+
196
+  /**
197
+   * @returns {Object}
198
+   */
199
+  self.serialize = function() {
200
+    _checkBuilt('serialize');
201
+
202
+    _settings = {};
203
+
204
+    _.eachObj(_itemsByMessageKey, function(messageKey, item) {
205
+      _settings[messageKey] = {
206
+        value: item.get()
207
+      };
208
+
209
+      if (item.precision) {
210
+        _settings[messageKey].precision = item.precision;
211
+      }
212
+    });
213
+    return _settings;
214
+  };
215
+
216
+  // @todo maybe don't do this and force the static method
217
+  self.registerComponent = ClayConfig.registerComponent;
218
+
219
+  /**
220
+   * Empties the root container
221
+   * @returns {ClayConfig}
222
+   */
223
+  self.destroy = function() {
224
+    var el = $rootContainer[0];
225
+    self.trigger(self.EVENTS.BEFORE_DESTROY);
226
+    while (el.firstChild) {
227
+      el.removeChild(el.firstChild);
228
+    }
229
+    _initializeItems();
230
+    self.trigger(self.EVENTS.AFTER_DESTROY);
231
+    return self;
232
+  };
233
+
234
+  /**
235
+   * Build the config page. This must be run before any of the get methods can be run
236
+   * If you call this method after the page has already been built, teh page will be
237
+   * destroyed and built again.
238
+   * @returns {ClayConfig}
239
+   */
240
+  self.build = function() {
241
+    if (_isBuilt) {
242
+      self.destroy();
243
+    }
244
+    self.trigger(self.EVENTS.BEFORE_BUILD);
245
+    _addItems(self.config, $rootContainer);
246
+    _isBuilt = true;
247
+    self.trigger(self.EVENTS.AFTER_BUILD);
248
+    return self;
249
+  };
250
+
251
+  _initializeItems();
252
+
253
+  // attach event methods
254
+  ClayEvents.call(self, $rootContainer);
255
+
256
+  // prevent external modifications of properties
257
+  utils.updateProperties(self, { writable: false, configurable: false });
258
+
259
+  // expose the config to allow developers to update it before the build is run
260
+  self.config = config;
261
+}
262
+
263
+/**
264
+ * Register a component to Clay. This must be called prior to .build();
265
+ * @param {Object} component - the clay component to register
266
+ * @param {string} component.name - the name of the component
267
+ * @param {string} component.template - HTML template to use for the component
268
+ * @param {string|Object} component.manipulator - methods to attach to the component
269
+ * @param {function} component.manipulator.set - set manipulator method
270
+ * @param {function} component.manipulator.get - get manipulator method
271
+ * @param {Object} [component.defaults] - template defaults
272
+ * @param {function} [component.initialize] - method to scaffold the component
273
+ * @return {boolean} - Returns true if component was registered correctly
274
+ */
275
+ClayConfig.registerComponent = function(component) {
276
+  var _component = _.copyObj(component);
277
+
278
+  if (componentStore[_component.name]) {
279
+    console.warn('Component: ' + _component.name +
280
+                 ' is already registered. If you wish to override the existing' +
281
+                 ' functionality, you must provide a new name');
282
+    return false;
283
+  }
284
+
285
+  if (typeof _component.manipulator === 'string') {
286
+    _component.manipulator = manipulators[component.manipulator];
287
+
288
+    if (!_component.manipulator) {
289
+      throw new Error('The manipulator: ' + component.manipulator +
290
+                      ' does not exist in the built-in manipulators.');
291
+    }
292
+  }
293
+
294
+  if (!_component.manipulator) {
295
+    throw new Error('The manipulator must be defined');
296
+  }
297
+
298
+  if (typeof _component.manipulator.set !== 'function' ||
299
+      typeof _component.manipulator.get !== 'function') {
300
+    throw new Error('The manipulator must have both a `get` and `set` method');
301
+  }
302
+
303
+  if (_component.style) {
304
+    var style = document.createElement('style');
305
+    style.type = 'text/css';
306
+    style.appendChild(document.createTextNode(_component.style));
307
+    document.head.appendChild(style);
308
+  }
309
+
310
+  componentStore[_component.name] = _component;
311
+  return true;
312
+};
313
+
314
+module.exports = ClayConfig;
0 315
new file mode 100644
... ...
@@ -0,0 +1,101 @@
1
+'use strict';
2
+
3
+var $ = require('../vendor/minified').$;
4
+var _ = require('../vendor/minified')._;
5
+
6
+/**
7
+ * Attaches event methods to the context.
8
+ * Call with ClayEvents.call(yourObject, $eventTarget)
9
+ * @param {EventEmitter|M} $eventTarget - An object that will be used as the event
10
+ * target. Must implement EventEmitter
11
+ * @constructor
12
+ */
13
+function ClayEvents($eventTarget) {
14
+  var self = this;
15
+  var _eventProxies = [];
16
+
17
+  /**
18
+   * prefixes events with "|"
19
+   * @param {string} events
20
+   * @returns {string}
21
+   * @private
22
+   */
23
+  function _transformEventNames(events) {
24
+    return events.split(' ').map(function(event) {
25
+      return '|' + event.replace(/^\|/, '');
26
+    }).join(' ');
27
+  }
28
+
29
+  /**
30
+   * @param {function} handler
31
+   * @param {function} proxy
32
+   * @returns {function}
33
+   * @private
34
+   */
35
+  function _registerEventProxy(handler, proxy) {
36
+    var eventProxy = _.find(_eventProxies, function(item) {
37
+      return item.handler === handler ? item : null;
38
+    });
39
+
40
+    if (!eventProxy) {
41
+      eventProxy = { handler: handler, proxy: proxy };
42
+      _eventProxies.push(eventProxy);
43
+    }
44
+    return eventProxy.proxy;
45
+  }
46
+
47
+  /**
48
+   * @param {function} handler
49
+   * @returns {function}
50
+   * @private
51
+   */
52
+  function _getEventProxy(handler) {
53
+    return _.find(_eventProxies, function(item) {
54
+      return item.handler === handler ? item.proxy : null;
55
+    });
56
+  }
57
+
58
+  /**
59
+   * Attach an event listener to the item.
60
+   * @param {string} events - a space separated list of events
61
+   * @param {function} handler
62
+   * @returns {ClayEvents}
63
+   */
64
+  self.on = function(events, handler) {
65
+    var _events = _transformEventNames(events);
66
+    var self = this;
67
+    var _proxy = _registerEventProxy(handler, function() {
68
+      handler.apply(self, arguments);
69
+    });
70
+    $eventTarget.on(_events, _proxy);
71
+    return self;
72
+  };
73
+
74
+  /**
75
+   * Remove the given event handler. NOTE: This will remove the handler from all
76
+   * registered events
77
+   * @param {function} handler
78
+   * @returns {ClayEvents}
79
+   */
80
+  self.off = function(handler) {
81
+    var _proxy = _getEventProxy(handler);
82
+    if (_proxy) {
83
+      $.off(_proxy);
84
+    }
85
+    return self;
86
+  };
87
+
88
+  /**
89
+   * Trigger an event.
90
+   * @param {string} name - a single event name to trigger
91
+   * @param {Object} [eventObj] - an object to pass to the event handler,
92
+   * provided the handler does not have custom arguments.
93
+   * @returns {ClayEvents}
94
+   */
95
+  self.trigger = function(name, eventObj) {
96
+    $eventTarget.trigger(name, eventObj);
97
+    return self;
98
+  };
99
+}
100
+
101
+module.exports = ClayEvents;
0 102
new file mode 100644
... ...
@@ -0,0 +1,78 @@
1
+'use strict';
2
+
3
+var componentRegistry = require('./component-registry');
4
+var minified = require('../vendor/minified');
5
+var utils = require('../lib/utils');
6
+var ClayEvents = require('./clay-events');
7
+
8
+var _ = minified._;
9
+var HTML = minified.HTML;
10
+
11
+/**
12
+ * @extends ClayEvents
13
+ * @param {Clay~ConfigItem} config
14
+ * @constructor
15
+ */
16
+function ClayItem(config) {
17
+  var self = this;
18
+
19
+  var _component = componentRegistry[config.type];
20
+
21
+  if (!_component) {
22
+    throw new Error('The component: ' + config.type + ' is not registered. ' +
23
+                    'Make sure to register it with ClayConfig.registerComponent()');
24
+  }
25
+
26
+  var extra = {
27
+    i18n: {
28
+      foo: 'bar'
29
+    }
30
+  };
31
+  var _templateData = _.extend({}, _component.defaults || {}, config, extra);
32
+  var _html = _.formatHtml(_component.template.trim(), _templateData);
33
+
34
+  /** @type {string|null} */
35
+  self.id = config.id || null;
36
+
37
+  /** @type {string|null} */
38
+  self.messageKey = config.messageKey || null;
39
+
40
+  /** @type {Object} */
41
+  self.config = config;
42
+  /** @type {M} */
43
+  self.$element = HTML(_html, _templateData);
44
+
45
+  /** @type {M} */
46
+  self.$manipulatorTarget = self.$element.select('[data-manipulator-target]');
47
+
48
+  // this caters for situations where the manipulator target is the root element
49
+  if (!self.$manipulatorTarget.length) {
50
+    self.$manipulatorTarget = self.$element;
51
+  }
52
+
53
+  /**
54
+   * Run the initializer if it exists and attaches the css to the head.
55
+   * Passes minified as the first param
56
+   * @param {ClayConfig} clay
57
+   * @returns {ClayItem}
58
+   */
59
+  self.initialize = function(clay) {
60
+    if (typeof _component.initialize === 'function') {
61
+      _component.initialize.call(self, minified, clay);
62
+    }
63
+    return self;
64
+  };
65
+
66
+  // attach event methods
67
+  ClayEvents.call(self, self.$manipulatorTarget);
68
+
69
+  // attach the manipulator methods to the clayItem
70
+  _.eachObj(_component.manipulator, function(methodName, method) {
71
+    self[methodName] = method.bind(self);
72
+  });
73
+
74
+  // prevent external modifications of properties
75
+  utils.updateProperties(self, { writable: false, configurable: false });
76
+}
77
+
78
+module.exports = ClayItem;
0 79
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+'use strict';
2
+
3
+// module is blank because we dynamically add components
4
+module.exports = {};
0 5
new file mode 100644
... ...
@@ -0,0 +1,180 @@
1
+'use strict';
2
+
3
+var _ = require('../vendor/minified')._;
4
+
5
+/**
6
+ * @returns {ClayItem|ClayEvents}
7
+ * @extends {ClayItem}
8
+ */
9
+function disable() {
10
+  if (this.$manipulatorTarget.get('disabled')) { return this; }
11
+  this.$element.set('+disabled');
12
+  this.$manipulatorTarget.set('disabled', true);
13
+  return this.trigger('disabled');
14
+}
15
+
16
+/**
17
+ * @returns {ClayItem|ClayEvents}
18
+ * @extends {ClayItem}
19
+ */
20
+function enable() {
21
+  if (!this.$manipulatorTarget.get('disabled')) { return this; }
22
+  this.$element.set('-disabled');
23
+  this.$manipulatorTarget.set('disabled', false);
24
+  return this.trigger('enabled');
25
+}
26
+
27
+/**
28
+ * @returns {ClayItem|ClayEvents}
29
+ * @extends {ClayItem}
30
+ */
31
+function hide() {
32
+  if (this.$element[0].classList.contains('hide')) { return this; }
33
+  this.$element.set('+hide');
34
+  return this.trigger('hide');
35
+}
36
+
37
+/**
38
+ * @returns {ClayItem|ClayEvents}
39
+ * @extends {ClayItem}
40
+ */
41
+function show() {
42
+  if (!this.$element[0].classList.contains('hide')) { return this; }
43
+  this.$element.set('-hide');
44
+  return this.trigger('show');
45
+}
46
+
47
+module.exports = {
48
+  html: {
49
+    get: function() {
50
+      return this.$manipulatorTarget.get('innerHTML');
51
+    },
52
+    set: function(value) {
53
+      if (this.get() === value.toString(10)) { return this; }
54
+      this.$manipulatorTarget.set('innerHTML', value);
55
+      return this.trigger('change');
56
+    },
57
+    hide: hide,
58
+    show: show
59
+  },
60
+  button: {
61
+    get: function() {
62
+      return this.$manipulatorTarget.get('innerHTML');
63
+    },
64
+    set: function(value) {
65
+      if (this.get() === value.toString(10)) { return this; }
66
+      this.$manipulatorTarget.set('innerHTML', value);
67
+      return this.trigger('change');
68
+    },
69
+    disable: disable,
70
+    enable: enable,
71
+    hide: hide,
72
+    show: show
73
+  },
74
+  val: {
75
+    get: function() {
76
+      return this.$manipulatorTarget.get('value');
77
+    },
78
+    set: function(value) {
79
+      if (this.get() === value.toString(10)) { return this; }
80
+      this.$manipulatorTarget.set('value', value);
81
+      return this.trigger('change');
82
+    },
83
+    disable: disable,
84
+    enable: enable,
85
+    hide: hide,
86
+    show: show
87
+  },
88
+  slider: {
89
+    get: function() {
90
+      return parseFloat(this.$manipulatorTarget.get('value'));
91
+    },
92
+    set: function(value) {
93
+      var initVal = this.get();
94
+      this.$manipulatorTarget.set('value', value);
95
+      if (this.get() === initVal) { return this; }
96
+      return this.trigger('change');
97
+    },
98
+    disable: disable,
99
+    enable: enable,
100
+    hide: hide,
101
+    show: show
102
+  },
103
+  checked: {
104
+    get: function() {
105
+      return this.$manipulatorTarget.get('checked');
106
+    },
107
+    set: function(value) {
108
+      if (!this.get() === !value) { return this; }
109
+      this.$manipulatorTarget.set('checked', !!value);
110
+      return this.trigger('change');
111
+    },
112
+    disable: disable,
113
+    enable: enable,
114
+    hide: hide,
115
+    show: show
116
+  },
117
+  radiogroup: {
118
+    get: function() {
119
+      return this.$element.select('input:checked').get('value');
120
+    },
121
+    set: function(value) {
122
+      if (this.get() === value.toString(10)) { return this; }
123
+      this.$element
124
+        .select('input[value="' + value.replace('"', '\\"') + '"]')
125
+        .set('checked', true);
126
+      return this.trigger('change');
127
+    },
128
+    disable: disable,
129
+    enable: enable,
130
+    hide: hide,
131
+    show: show
132
+  },
133
+  checkboxgroup: {
134
+    get: function() {
135
+      var result = [];
136
+      this.$element.select('input').each(function(item) {
137
+        result.push(!!item.checked);
138
+      });
139
+      return result;
140
+    },
141
+    set: function(values) {
142
+      var self = this;
143
+      values = Array.isArray(values) ? values : [];
144
+
145
+      while (values.length < this.get().length) {
146
+        values.push(false);
147
+      }
148
+
149
+      if (_.equals(this.get(), values)) { return this; }
150
+
151
+      self.$element.select('input')
152
+        .set('checked', false)
153
+        .each(function(item, index) {
154
+          item.checked = !!values[index];
155
+        });
156
+
157
+      return self.trigger('change');
158
+    },
159
+    disable: disable,
160
+    enable: enable,
161
+    hide: hide,
162
+    show: show
163
+  },
164
+  color: {
165
+    get: function() {
166
+      return parseInt(this.$manipulatorTarget.get('value'), 10) || 0;
167
+    },
168
+    set: function(value) {
169
+      value = this.roundColorToLayout(value || 0);
170
+
171
+      if (this.get() === value) { return this; }
172
+      this.$manipulatorTarget.set('value', value);
173
+      return this.trigger('change');
174
+    },
175
+    disable: disable,
176
+    enable: enable,
177
+    hide: hide,
178
+    show: show
179
+  }
180
+};
0 181
new file mode 100644
... ...
@@ -0,0 +1,135 @@
1
+'use strict';
2
+
3
+/**
4
+ * Batch update all the properties of an object.
5
+ * @param {Object} obj
6
+ * @param {Object} descriptor
7
+ * @param {boolean} [descriptor.configurable]
8
+ * @param {boolean} [descriptor.enumerable]
9
+ * @param {*} [descriptor.value]
10
+ * @param {boolean} [descriptor.writable]
11
+ * @param {function} [descriptor.get]
12
+ * @param {function} [descriptor.set]
13
+ * @return {void}
14
+ */
15
+module.exports.updateProperties = function(obj, descriptor) {
16
+  Object.getOwnPropertyNames(obj).forEach(function(prop) {
17
+    Object.defineProperty(obj, prop, descriptor);
18
+  });
19
+};
20
+
21
+module.exports.capabilityMap = {
22
+  PLATFORM_APLITE: {
23
+    platforms: ['aplite'],
24
+    minFwMajor: 0,
25
+    minFwMinor: 0
26
+  },
27
+  PLATFORM_BASALT: {
28
+    platforms: ['basalt'],
29
+    minFwMajor: 0,
30
+    minFwMinor: 0
31
+  },
32
+  PLATFORM_CHALK: {
33
+    platforms: ['chalk'],
34
+    minFwMajor: 0,
35
+    minFwMinor: 0
36
+  },
37
+  PLATFORM_DIORITE: {
38
+    platforms: ['diorite'],
39
+    minFwMajor: 0,
40
+    minFwMinor: 0
41
+  },
42
+  PLATFORM_EMERY: {
43
+    platforms: ['emery'],
44
+    minFwMajor: 0,
45
+    minFwMinor: 0
46
+  },
47
+  BW: {
48
+    platforms: ['aplite', 'diorite'],
49
+    minFwMajor: 0,
50
+    minFwMinor: 0
51
+  },
52
+  COLOR: {
53
+    platforms: ['basalt', 'chalk', 'emery'],
54
+    minFwMajor: 0,
55
+    minFwMinor: 0
56
+  },
57
+  MICROPHONE: {
58
+    platforms: ['basalt', 'chalk', 'diorite', 'emery'],
59
+    minFwMajor: 0,
60
+    minFwMinor: 0
61
+  },
62
+  SMARTSTRAP: {
63
+    platforms: ['basalt', 'chalk', 'diorite', 'emery'],
64
+    minFwMajor: 3,
65
+    minFwMinor: 4
66
+  },
67
+  SMARTSTRAP_POWER: {
68
+    platforms: ['basalt', 'chalk', 'emery'],
69
+    minFwMajor: 3,
70
+    minFwMinor: 4
71
+  },
72
+  HEALTH: {
73
+    platforms: ['basalt', 'chalk', 'diorite', 'emery'],
74
+    minFwMajor: 3,
75
+    minFwMinor: 10
76
+  },
77
+  RECT: {
78
+    platforms: ['aplite', 'basalt', 'diorite', 'emery'],
79
+    minFwMajor: 0,
80
+    minFwMinor: 0
81
+  },
82
+  ROUND: {
83
+    platforms: ['chalk'],
84
+    minFwMajor: 0,
85
+    minFwMinor: 0
86
+  },
87
+  DISPLAY_144x168: {
88
+    platforms: ['aplite', 'basalt', 'diorite'],
89
+    minFwMajor: 0,
90
+    minFwMinor: 0
91
+  },
92
+  DISPLAY_180x180_ROUND: {
93
+    platforms: ['chalk'],
94
+    minFwMajor: 0,
95
+    minFwMinor: 0
96
+  },
97
+  DISPLAY_200x228: {
98
+    platforms: ['emery'],
99
+    minFwMajor: 0,
100
+    minFwMinor: 0
101
+  }
102
+};
103
+
104
+/**
105
+ * Checks if all of the provided capabilities are compatible with the watch
106
+ * @param {Object} activeWatchInfo
107
+ * @param {Array<string>} [capabilities]
108
+ * @return {boolean}
109
+ */
110
+module.exports.includesCapability = function(activeWatchInfo, capabilities) {
111
+  var notRegex = /^NOT_/;
112
+  var result = [];
113
+
114
+  if (!capabilities || !capabilities.length) {
115
+    return true;
116
+  }
117
+
118
+  for (var i = capabilities.length - 1; i >= 0; i--) {
119
+    var capability = capabilities[i];
120
+    var mapping = module.exports.capabilityMap[capability.replace(notRegex, '')];
121
+
122
+    if (!mapping ||
123
+        mapping.platforms.indexOf(activeWatchInfo.platform) === -1 ||
124
+        mapping.minFwMajor > activeWatchInfo.firmware.major ||
125
+        mapping.minFwMajor === activeWatchInfo.firmware.major &&
126
+        mapping.minFwMinor > activeWatchInfo.firmware.minor
127
+    ) {
128
+      result.push(!!capability.match(notRegex));
129
+    } else {
130
+      result.push(!capability.match(notRegex));
131
+    }
132
+  }
133
+
134
+  return result.indexOf(false) === -1;
135
+};
0 136
new file mode 100644
... ...
@@ -0,0 +1,51 @@
1
+var path = require('path');
2
+var through = require('through');
3
+var postcss = require('postcss');
4
+var autoprefixer = require('autoprefixer');
5
+var requireFromString = require('require-from-string');
6
+
7
+/**
8
+ * Stringifies the content
9
+ * @param   {string}    content
10
+ * @returns {string}
11
+ */
12
+function stringify (content) {
13
+  return 'module.exports = ' + JSON.stringify(content) + ';\n';
14
+}
15
+
16
+module.exports = function (file, options) {
17
+
18
+  /**
19
+   * The function Browserify will use to transform the input.
20
+   * @param   {string} file
21
+   * @returns {stream}
22
+   */
23
+  function browserifyTransform (file) {
24
+    var extensions = ['.css', '.sass', '.scss', '.less'];
25
+    var chunks = [];
26
+
27
+    if (extensions.indexOf(path.extname(file)) === -1) {
28
+      return through();
29
+    }
30
+
31
+    var write = function (buffer) {
32
+      chunks.push(buffer);
33
+    };
34
+
35
+    var end = function () {
36
+      var contents = requireFromString(Buffer.concat(chunks).toString('utf8'));
37
+      contents = postcss([autoprefixer(options)]).process(contents).css;
38
+      this.queue(stringify(contents));
39
+      this.queue(null);
40
+    };
41
+
42
+    return through(write, end);
43
+  }
44
+
45
+  if (typeof file !== 'string') {
46
+    options = file;
47
+    return browserifyTransform;
48
+  } else {
49
+    return browserifyTransform(file);
50
+  }
51
+};
0 52
new file mode 100644
... ...
@@ -0,0 +1,3602 @@
1
+// minified.js config start -- use this comment to re-create a configuration in the Builder
2
+// - Only sections add, always, amdsupport, copyobj, dollardollar,
3
+// - each, eachobj, equals, error, extend, find, format, formathtml, get, ht,
4
+// - html, isobject, off, on, ready, request, select, set, template, trigger,
5
+// - underscore, wait.
6
+
7
+
8
+// WARNING! This file is autogenerated from minified-master.js and others.
9
+
10
+/*
11
+ * Minified.js - Lightweight Client-Side JavaScript Library (full package)
12
+ * Version: Version 2014 beta 5 b2
13
+ *
14
+ * Public Domain. Use, modify and distribute it any way you like. No attribution required.
15
+ * To the extent possible under law, Tim Jansen has waived all copyright and related or neighboring rights to Minified.
16
+ * Please see http://creativecommons.org/publicdomain/zero/1.0/.
17
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
18
+ *
19
+ * Contains code based on https://github.com/douglascrockford/JSON-js (also Public Domain).
20
+ *
21
+ * https://github.com/timjansen/minified.js
22
+ */
23
+// ==ClosureCompiler==
24
+// @output_file_name minified.js
25
+// @compilation_level ADVANCED_OPTIMIZATIONS
26
+// ==/ClosureCompiler==
27
+
28
+/*$
29
+ * @id ALL
30
+ * @doc no
31
+ * @required
32
+ * This id allows identifying whether both Web and Util are available.
33
+ */
34
+
35
+///#snippet commonAmdStart
36
+
37
+/*$
38
+ * @id require
39
+ * @name require()
40
+ * @syntax require(name)
41
+ * @group OPTIONS
42
+ * @module WEB, UTIL
43
+ * Returns a reference to a module. If you do not use an AMD loader to load Minified, just call <var>require()</var> with the
44
+ * argument 'minified' to get a reference to Minified. You can also access all modules defined using ##define().
45
+ *
46
+ * If you do use an AMD loader, Minified will not define this function and you can use the AMD loader to obtain the
47
+ * reference to Minified.
48
+ * Minified's version of <var>require</var> is very simple and will only support Minified and other libraries designed
49
+ * for Minfied, but <strong>no real AMD libraries</strong>. If you need to work with libraries requiring AMD, you need a real AMD loader.
50
+ *
51
+ * @param name the name of the module to request. Minified is available as 'minified'.
52
+ * @return the reference to the module. Use the name 'minified' to get Minified. You can also access any modules defined using
53
+ * ##define(). If the name is unknown, it returns <var>undefined</var>.
54
+ *
55
+ * @see ##define() allows you to define modules that can be obtained using <var>require()</var>.
56
+ */
57
+
58
+/*$
59
+ * @id define
60
+ * @name define()
61
+ * @syntax define(name, factoryFunction)
62
+ * @group OPTIONS
63
+ * @module WEB, UTIL
64
+ * Defines a module that can be returned by ##require(), in case you don't have a AMD loader. If you have a AMD loader before you include Minified,
65
+ * <var>define()</var> will not be set and you can use the AMD loader's (more powerful) variant.
66
+ *
67
+ * Minified's versions of <var>require()</var> and <var>define()</var> are very simple and can not resolve things like circular references.
68
+ * Also, they are not AMD-compatible and only useful for simple modules. If you need to work with real AMD libraries that are not written
69
+ * for Minified, you need a real AMD loader.
70
+ *
71
+ * @example Creates a simple module and uses it:
72
+ * <pre>
73
+ * define('makeGreen', function(require) {
74
+ *     var MINI = require('minified'), $ = MINI.$; // obtain own ref to Minified
75
+ *     return function(list) {
76
+ *         $(list).set({$color: '#0f0', $backgroundColor: '#050'});
77
+ *     });
78
+ * });
79
+ *
80
+ * var makeGreen = require('makeGreen');
81
+ * makeGreen('.notGreenEnough');
82
+ * </pre>
83
+ *
84
+ * @param name the name of the module to request. In Minified's implementation, only 'minified' is supported.
85
+ * @param factoryFunction is a <code>function(require)</code> will be called the first time the name is defined to obtain the module
86
+ * 						  reference. It received a reference to ##require() (which is required for AMD backward-compatibility) and
87
+ * 						  must return the value that is returned by ##require(). The function will only be called once, its result will
88
+ *                        be cached.
89
+ *                        <dl><dt>require</dt><dd>A reference to ##require(). While you could use <var>require()</var> from the global
90
+ *                        context, this would prevent backward compatibility with AMD.</dd>
91
+ *                        <dt class="returnValue">(callback return value)</dt><dd>The reference to be returned by ##require().</dd></dl>
92
+ *
93
+ * @see ##require() can be used to obtain references defined with ##define().
94
+ */
95
+
96
+/*$
97
+ * @id amdsupport
98
+ * @name AMD stubs
99
+ * @configurable default
100
+ * @group OPTIONS
101
+ * @doc no
102
+ * @module WEB, UTIL
103
+ * If enabled, Minified will create stubs so you can use it without an AMD framework.
104
+ * It requires AMD's <code>define()</code> function.
105
+ */
106
+if (/^u/.test(typeof define)) { // no AMD support available ? define a minimal version
107
+  (function(def){
108
+    var require = this['require'] = function(name) { return def[name]; };
109
+    this['define'] = function(name, f) { def[name] = def[name] || f(require); };
110
+  })({});
111
+}
112
+/*$
113
+ * @stop
114
+ */
115
+
116
+define('minified', function() {
117
+
118
+  ///#/snippet commonAmdStart
119
+  ///#snippet webVars
120
+  /*$
121
+   * @id WEB
122
+   * @doc no
123
+   * @required
124
+   * This id allows identifying whether the Web module is available.
125
+   */
126
+
127
+  /**
128
+   * @const
129
+   */
130
+  var _window = window;
131
+
132
+  /**
133
+   * @const
134
+   * @type {!string}
135
+   */
136
+  var MINIFIED_MAGIC_NODEID = 'Nia';
137
+
138
+  /**
139
+   * @const
140
+   * @type {!string}
141
+   */
142
+  var MINIFIED_MAGIC_PREV = 'NiaP';
143
+
144
+  var setter = {}, getter = {};
145
+
146
+  var idSequence = 1;  // used as node id to identify nodes, and as general id for other maps
147
+
148
+
149
+  /*$
150
+   * @id ready_vars
151
+   * @dependency
152
+   */
153
+  /** @type {!Array.<function()>} */
154
+  var DOMREADY_HANDLER = /^[ic]/.test(document['readyState']) ? _null : []; // check for 'interactive' and 'complete'
155
+  /*$
156
+   * @stop
157
+   */
158
+
159
+  ///#/snippet webVars
160
+  ///#snippet utilVars
161
+  /*$
162
+   * @id UTIL
163
+   * @doc no
164
+   * @required
165
+   * This id allows identifying whether the Util module is available.
166
+   */
167
+
168
+  var _null = null;
169
+
170
+  /** @const */
171
+  var undef;
172
+
173
+  /*$
174
+   * @id date_constants
175
+   * @dependency
176
+   */
177
+  function val3(v) {return v.substr(0,3);}
178
+  var MONTH_LONG_NAMES = split('January,February,March,April,May,June,July,August,September,October,November,December', /,/g);
179
+  var MONTH_SHORT_NAMES = map(MONTH_LONG_NAMES, val3); // ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
180
+  var WEEK_LONG_NAMES = split('Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday', /,/g);
181
+  var WEEK_SHORT_NAMES = map(WEEK_LONG_NAMES, val3);
182
+  var MERIDIAN_NAMES = split('am,pm', /,/g);
183
+  var MERIDIAN_NAMES_FULL = split('am,am,am,am,am,am,am,am,am,am,am,am,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm,pm', /,/g);
184
+
185
+  var FORMAT_DATE_MAP = {
186
+    'y': ['FullYear', nonOp],
187
+    'Y': ['FullYear', function(d) { return d % 100; }],
188
+    'M': ['Month', plusOne],
189
+    'n': ['Month', MONTH_SHORT_NAMES],
190
+    'N': ['Month', MONTH_LONG_NAMES],
191
+    'd': ['Date', nonOp],
192
+    'm': ['Minutes', nonOp],
193
+    'H': ['Hours', nonOp],
194
+    'h': ['Hours', function(d) { return (d % 12) || 12; }],
195
+    'k': ['Hours', plusOne],
196
+    'K': ['Hours', function(d) { return d % 12; }],
197
+    's': ['Seconds', nonOp],
198
+    'S': ['Milliseconds', nonOp],
199
+    'a': ['Hours', MERIDIAN_NAMES_FULL],
200
+    'w': ['Day', WEEK_SHORT_NAMES],
201
+    'W': ['Day', WEEK_LONG_NAMES],
202
+    'z': ['TimezoneOffset', function(d, dummy, timezone) {
203
+      if (timezone)
204
+        return timezone;
205
+
206
+      var sign = d > 0 ? '-' : '+';
207
+      var off = d < 0 ? -d : d;
208
+      return sign + pad(2, Math.floor(off/60)) + pad(2, off%60);
209
+    }]
210
+  };
211
+
212
+  var PARSE_DATE_MAP = {
213
+    'y': 0,      // placeholder -> ctorIndex
214
+    'Y': [0, -2000],
215
+    'M': [1,1], // placeholder -> [ctorIndex, offset|value array]
216
+    'n': [1, MONTH_SHORT_NAMES],
217
+    'N': [1, MONTH_LONG_NAMES],
218
+    'd': 2,
219
+    'm': 4,
220
+    'H': 3,
221
+    'h': 3,
222
+    'K': [3,1],
223
+    'k': [3,1],
224
+    's':  5,
225
+    'S':  6,
226
+    'a': [3, MERIDIAN_NAMES]
227
+  };
228
+
229
+  /*$
230
+   * @stop
231
+   */
232
+
233
+  /** @const */
234
+  var MAX_CACHED_TEMPLATES = 99;
235
+  var templateCache={}; // template -> function
236
+  var templates = [];   // list of MAX_CACHED_TEMPLATES templates
237
+
238
+  ///#/snippet utilVars
239
+  ///#snippet commonFunctions
240
+
241
+  /** @param s {?} */
242
+  function toString(s) {
243
+    return s!=_null ? ''+s : '';
244
+  }
245
+  /**
246
+   * @param s {?}
247
+   * @param o {string}
248
+   */
249
+  function isType(s,o) {
250
+    return typeof s == o;
251
+  }
252
+  /** @param s {?} */
253
+  function isString(s) {
254
+    return isType(s, 'string');
255
+  }
256
+  function isObject(f) {
257
+    return !!f && isType(f, 'object');
258
+  }
259
+  function isNode(n) {
260
+    return n && n['nodeType'];
261
+  }
262
+  function isNumber(n) {
263
+    return isType(n, 'number');
264
+  }
265
+  function isDate(n) {
266
+    return isObject(n) && !!n['getDay'];
267
+  }
268
+  function isBool(n) {
269
+    return n === true || n === false;
270
+  }
271
+  function isValue(n) {
272
+    var type = typeof n;
273
+    return type == 'object' ? !!(n && n['getDay']) : (type == 'string' || type == 'number' || isBool(n));
274
+  }
275
+  function nonOp(v) {
276
+    return v;
277
+  }
278
+  function plusOne(d) {
279
+    return d+1;
280
+  }
281
+  function replace(s, regexp, sub) {
282
+    return toString(s).replace(regexp, sub != _null ? sub : '');
283
+  }
284
+  function escapeRegExp(s) {
285
+    return replace(s, /[\\\[\]\/{}()*+?.$|^-]/g, "\\$&");
286
+  }
287
+  function trim(s) {
288
+    return replace(s, /^\s+|\s+$/g);
289
+  }
290
+  function eachObj(obj, cb, ctx) {
291
+    for (var n in obj)
292
+      if (obj.hasOwnProperty(n))
293
+        cb.call(ctx || obj, n, obj[n]);
294
+    return obj;
295
+  }
296
+  function each(list, cb, ctx) {
297
+    if (list)
298
+      for (var i = 0; i < list.length; i++)
299
+        cb.call(ctx || list, list[i], i);
300
+    return list;
301
+  }
302
+  function filter(list, filterFuncOrObject, ctx) {
303
+    var r = [];
304
+    var f = isFunction(filterFuncOrObject) ? filterFuncOrObject : function(value) { return filterFuncOrObject != value; };
305
+    each(list, function(value, index) {
306
+      if (f.call(ctx || list, value, index))
307
+        r.push(value);
308
+    });
309
+    return r;
310
+  }
311
+  function collector(iterator, obj, collectFunc, ctx) {
312
+    var result = [];
313
+    iterator(obj, function (a, b) {
314
+      if (isList(a = collectFunc.call(ctx || obj, a, b))) // extreme variable reusing: a is now the callback result
315
+        each(a, function(rr) { result.push(rr); });
316
+      else if (a != _null)
317
+        result.push(a);
318
+    });
319
+    return result;
320
+  }
321
+  function collectObj(obj, collectFunc, ctx) {
322
+    return collector(eachObj, obj, collectFunc, ctx);
323
+  }
324
+  function collect(list, collectFunc, ctx) {
325
+    return collector(each, list, collectFunc, ctx);
326
+  }
327
+  function keyCount(obj) {
328
+    var c = 0;
329
+    eachObj(obj, function(key) { c++; });
330
+    return c;
331
+  }
332
+  function keys(obj) { // use Object.keys? in IE>=9
333
+    var list = [];
334
+    eachObj(obj, function(key) { list.push(key); });
335
+    return list;
336
+  }
337
+  function map(list, mapFunc, ctx) {
338
+    var result = [];
339
+    each(list, function(item, index) {
340
+      result.push(mapFunc.call(ctx || list, item, index));
341
+    });
342
+    return result;
343
+  }
344
+  function startsWith(base, start) {
345
+    if (isList(base)) {
346
+      var s2 = _(start); // convert start as we don't know whether it is a list yet
347
+      return equals(sub(base, 0, s2.length), s2);
348
+    }
349
+    else
350
+      return start != _null && base.substr(0, start.length) == start;
351
+  }
352
+  function endsWith(base, end) {
353
+    if (isList(base)) {
354
+      var e2 = _(end);
355
+      return equals(sub(base, -e2.length), e2) || !e2.length;
356
+    }
357
+    else
358
+      return end != _null && base.substr(base.length - end.length) == end;
359
+  }
360
+  function reverse(list) {
361
+    var len = list.length;
362
+    if (isList(list))
363
+      return new M(map(list, function() { return list[--len]; }));
364
+    else
365
+      return replace(list, /[\s\S]/g, function() { return list.charAt(--len); });
366
+  }
367
+  function toObject(list, value) {
368
+    var obj = {};
369
+    each(list, function(item, index) {
370
+      obj[item] = value;
371
+    });
372
+    return obj;
373
+  }
374
+  function copyObj(from, to) {
375
+    var dest = to || {};
376
+    for (var name in from)
377
+      dest[name] = from[name];
378
+    return dest;
379
+  }
380
+  function merge(list, target) {
381
+    var o = target;
382
+    for (var i = 0; i < list.length; i++)
383
+      o = copyObj(list[i], o);
384
+    return o;
385
+  }
386
+  function getFindFunc(findFunc) {
387
+    return isFunction(findFunc) ? findFunc : function(obj, index) { if (findFunc === obj) return index; };
388
+  }
389
+  function getFindIndex(list, index, defaultIndex) {
390
+    return index == _null ? defaultIndex : index < 0 ? Math.max(list.length+index, 0) : Math.min(list.length, index);
391
+  }
392
+  function find(list, findFunc, startIndex, endIndex) {
393
+    var f = getFindFunc(findFunc);
394
+    var e = getFindIndex(list, endIndex, list.length);
395
+    var r;
396
+    for (var i = getFindIndex(list, startIndex, 0); i < e; i++)
397
+      if ((r = f.call(list, list[i], i)) != _null)
398
+        return r;
399
+  }
400
+  function findLast(list, findFunc, startIndex, endIndex) {
401
+    var f = getFindFunc(findFunc);
402
+    var e = getFindIndex(list, endIndex, -1);
403
+    var r;
404
+    for (var i = getFindIndex(list, startIndex, list.length-1); i > e; i--)
405
+      if ((r = f.call(list, list[i], i)) != _null)
406
+        return r;
407
+  }
408
+  function sub(list, startIndex, endIndex) {
409
+    var r = [];
410
+    if (list) {
411
+      var e = getFindIndex(list, endIndex, list.length);
412
+      for (var i = getFindIndex(list, startIndex, 0); i < e; i++)
413
+        r.push(list[i]);
414
+    }
415
+    return r;
416
+  }
417
+  function array(list) {
418
+    return map(list, nonOp);
419
+  }
420
+  function unite(list) {
421
+    return function() {
422
+      return new M(callList(list, arguments));
423
+    };
424
+  }
425
+  function uniq(list) {
426
+    var found = {};
427
+    return filter(list, function(item) {
428
+      if (found[item])
429
+        return false;
430
+      else
431
+        return found[item] = 1;
432
+    });
433
+  }
434
+  function intersection(list, otherList) {
435
+    var keys = toObject(otherList, 1);
436
+    return filter(list, function(item) {
437
+      var r = keys[item];
438
+      keys[item] = 0;
439
+      return r;
440
+    });
441
+  }
442
+  function contains(list, value) { // TODO: can Array.indexOf be used in >IE8?
443
+    for (var i = 0; i < list.length; i++)
444
+      if (list[i] == value)
445
+        return true;
446
+    return false;
447
+  }
448
+  // equals if a and b have the same elements and all are equal. Supports getters.
449
+  function equals(x, y) {
450
+    var a = isFunction(x) ? x() : x;
451
+    var b = isFunction(y) ? y() : y;
452
+    var aKeys;
453
+    if (a == b)
454
+      return true;
455
+    else if (a == _null || b == _null)
456
+      return false;
457
+    else if (isValue(a) || isValue(b))
458
+      return isDate(a) && isDate(b) && +a==+b;
459
+    else if (isList(a)) {
460
+      return (a.length == b.length) &&
461
+             !find(a, function(val, index) {
462
+               if (!equals(val, b[index]))
463
+                 return true;
464
+             });
465
+    }
466
+    else {
467
+      return !isList(b) &&
468
+             ((aKeys = keys(a)).length == keyCount(b)) &&
469
+             !find(aKeys, function(key) {
470
+               if (!equals(a[key],b[key]))
471
+                 return true;
472
+             });
473
+    }
474
+  }
475
+
476
+  function call(f, fThisOrArgs, args) {
477
+    if (isFunction(f))
478
+      return f.apply(args && fThisOrArgs, map(args || fThisOrArgs, nonOp));
479
+  }
480
+  function callList(list, fThisOrArgs, args) {
481
+    return map(list, function(f) { return call(f, fThisOrArgs, args);});
482
+  }
483
+  function bind(f, fThis, beforeArgs, afterArgs) {
484
+    return function() {
485
+      return call(f, fThis, collect([beforeArgs, arguments, afterArgs], nonOp));
486
+    };
487
+  }
488
+  function partial(f, beforeArgs, afterArgs) {
489
+    return bind(f, this, beforeArgs, afterArgs);
490
+  }
491
+  function pad(digits, number) {
492
+    var signed = number < 0 ? '-' : '';
493
+    var preDecimal = (signed?-number:number).toFixed(0);
494
+    while (preDecimal.length < digits)
495
+      preDecimal = '0' + preDecimal;
496
+    return signed + preDecimal;
497
+  }
498
+
499
+  function processNumCharTemplate(tpl, input, fwd) {
500
+    var inHash;
501
+    var inputPos = 0;
502
+    var rInput = fwd ? input : reverse(input);
503
+    var s = (fwd ? tpl : reverse(tpl)).replace(/./g, function(tplChar) {
504
+      if (tplChar == '0') {
505
+        inHash = false;
506
+        return rInput.charAt(inputPos++) || '0';
507
+      }
508
+      else if (tplChar == '#') {
509
+        inHash = true;
510
+        return rInput.charAt(inputPos++) || '';
511
+      }
512
+      else
513
+        return inHash && !rInput.charAt(inputPos) ? '' : tplChar;
514
+    });
515
+    return fwd ? s : (input.substr(0, input.length - inputPos) + reverse(s));
516
+  }
517
+
518
+  function getTimezone(match, idx, refDate) { // internal helper, see below
519
+    if (idx == _null || !match)
520
+      return 0;
521
+    return parseFloat(match[idx]+match[idx+1])*60 + parseFloat(match[idx]+match[idx+2]) + refDate.getTimezoneOffset();
522
+  }
523
+
524
+  // formats number with format string (e.g. "#.000", "#,#", "00000", "000.00", "000.000.000,00", "000,000,000.##")
525
+  // choice syntax: <cmp><value>:<format>|<cmp><value>:<format>|...
526
+  // e.g. 0:no item|1:one item|>=2:# items
527
+  // <value>="null" used to compare with nulls.
528
+  // choice also works with strings or bools, e.g. ERR:error|WAR:warning|FAT:fatal|ok
529
+  function formatValue(fmt, value) {
530
+    var format = replace(fmt, /^\?/);
531
+    if (isDate(value)) {
532
+      var timezone, match;
533
+
534
+      if (match = /^\[(([+-])(\d\d)(\d\d))\]\s*(.*)/.exec(format)) {
535
+        timezone = match[1];
536
+        value = dateAdd(value, 'minutes', getTimezone(match, 2, value));
537
+        format = match[5];
538
+      }
539
+
540
+      return replace(format, /(\w)(\1*)(?:\[([^\]]+)\])?/g, function(s, placeholderChar, placeholderDigits, params) {
541
+        var val = FORMAT_DATE_MAP[placeholderChar];
542
+        if (val) {
543
+          var d = value['get' + val[0]]();
544
+          var optionArray = (params && params.split(','));
545
+
546
+          if (isList(val[1]))
547
+            d = (optionArray || val[1])[d];
548
+          else
549
+            d = val[1](d, optionArray, timezone);
550
+          if (d != _null && !isString(d))
551
+            d = pad(placeholderDigits.length+1, d);
552
+          return d;
553
+        }
554
+        else
555
+          return s;
556
+      });
557
+
558
+    }
559
+    else
560
+      return find(format.split(/\s*\|\s*/), function(fmtPart) {
561
+        var match, numFmtOrResult;
562
+        if (match = /^([<>]?)(=?)([^:]*?)\s*:\s*(.*)$/.exec(fmtPart)) {
563
+          var cmpVal1 = value, cmpVal2 = +(match[3]);
564
+          if (isNaN(cmpVal2) || !isNumber(cmpVal1)) {
565
+            cmpVal1 = (cmpVal1==_null) ? "null" : toString(cmpVal1); // not ""+value, because undefined is treated as null here
566
+            cmpVal2 = match[3];
567
+          }
568
+          if (match[1]) {
569
+            if ((!match[2] && cmpVal1 == cmpVal2 ) ||
570
+                (match[1] == '<'  && cmpVal1 > cmpVal2)  ||
571
+                (match[1] == '>'  && cmpVal1 < cmpVal2))
572
+              return _null;
573
+          }
574
+          else if (cmpVal1 != cmpVal2)
575
+            return _null;
576
+          numFmtOrResult = match[4];
577
+        }
578
+        else
579
+          numFmtOrResult = fmtPart;
580
+
581
+        if (isNumber(value))
582
+          return numFmtOrResult.replace(/[0#](.*[0#])?/, function(numFmt) {
583
+            var decimalFmt = /^([^.]+)(\.)([^.]+)$/.exec(numFmt) || /^([^,]+)(,)([^,]+)$/.exec(numFmt);
584
+            var signed = value < 0 ? '-' : '';
585
+            var numData = /(\d+)(\.(\d+))?/.exec((signed?-value:value).toFixed(decimalFmt ? decimalFmt[3].length:0));
586
+            var preDecimalFmt = decimalFmt ? decimalFmt[1] : numFmt;
587
+            var postDecimal = decimalFmt ? processNumCharTemplate(decimalFmt[3], replace(numData[3], /0+$/), true) : '';
588
+
589
+            return 	(signed ? '-' : '') +
590
+                    (preDecimalFmt == '#' ? numData[1] : processNumCharTemplate(preDecimalFmt, numData[1])) +
591
+                    (postDecimal.length ? decimalFmt[2] : '') +
592
+                    postDecimal;
593
+          });
594
+        else
595
+          return numFmtOrResult;
596
+      });
597
+  }
598
+  // returns date; null if optional and not set; undefined if parsing failed
599
+  function parseDate(fmt, date) {
600
+    var indexMap = {}; // contains reGroupPosition -> typeLetter or [typeLetter, value array]
601
+    var reIndex = 1;
602
+    var timezoneOffsetMatch;
603
+    var timezoneIndex;
604
+    var match;
605
+
606
+    var format = replace(fmt, /^\?/);
607
+    if (format!=fmt && !trim(date))
608
+      return _null;
609
+
610
+    if (match = /^\[([+-])(\d\d)(\d\d)\]\s*(.*)/.exec(format)) {
611
+      timezoneOffsetMatch = match;
612
+      format = match[4];
613
+    }
614
+
615
+    var parser = new RegExp(format.replace(/(.)(\1*)(?:\[([^\]]*)\])?/g, function(wholeMatch, placeholderChar, placeholderDigits, param) {
616
+      if (/[dmhkyhs]/i.test(placeholderChar)) {
617
+        indexMap[reIndex++] = placeholderChar;
618
+        var plen = placeholderDigits.length+1;
619
+        return "(\\d"+(plen<2?"+":("{1,"+plen+"}"))+")";
620
+      }
621
+      else if (placeholderChar == 'z') {
622
+        timezoneIndex = reIndex;
623
+        reIndex += 3;
624
+        return "([+-])(\\d\\d)(\\d\\d)";
625
+      }
626
+      else if (/[Nna]/.test(placeholderChar)) {
627
+        indexMap[reIndex++] = [placeholderChar, param && param.split(',')];
628
+        return "([a-zA-Z\\u0080-\\u1fff]+)";
629
+      }
630
+      else if (/w/i.test(placeholderChar))
631
+        return "[a-zA-Z\\u0080-\\u1fff]+";
632
+      else if (/\s/.test(placeholderChar))
633
+        return "\\s+";
634
+      else
635
+        return escapeRegExp(wholeMatch);
636
+    }));
637
+
638
+    if (!(match = parser.exec(date)))
639
+      return undef;
640
+
641
+    var ctorArgs = [0, 0, 0, 0, 0, 0,  0];
642
+    for (var i = 1; i < reIndex; i++) {
643
+      var matchVal = match[i];
644
+      var indexEntry = indexMap[i];
645
+      if (isList(indexEntry)) { // for a, n or N
646
+        var placeholderChar = indexEntry[0];
647
+        var mapEntry  = PARSE_DATE_MAP[placeholderChar];
648
+        var ctorIndex = mapEntry[0];
649
+        var valList = indexEntry[1] || mapEntry[1];
650
+        var listValue = find(valList, function(v, index) { if (startsWith(matchVal.toLowerCase(), v.toLowerCase())) return index; });
651
+        if (listValue == _null)
652
+          return undef;
653
+        if (placeholderChar == 'a')
654
+          ctorArgs[ctorIndex] += listValue * 12;
655
+        else
656
+          ctorArgs[ctorIndex] = listValue;
657
+      }
658
+      else if (indexEntry) { // for numeric values (yHmMs)
659
+        var value = parseFloat(matchVal);
660
+        var mapEntry  = PARSE_DATE_MAP[indexEntry];
661
+        if (isList(mapEntry))
662
+          ctorArgs[mapEntry[0]] += value - mapEntry[1];
663
+        else
664
+          ctorArgs[mapEntry] += value;
665
+      }
666
+    }
667
+    var d = new Date(ctorArgs[0], ctorArgs[1], ctorArgs[2], ctorArgs[3], ctorArgs[4], ctorArgs[5], ctorArgs[6]);
668
+    return dateAdd(d, 'minutes', -getTimezone(timezoneOffsetMatch, 1, d) - getTimezone(match, timezoneIndex, d));
669
+  }
670
+  // format ?##00,00##
671
+  // returns number; null if optional and not set; undefined if parsing failed
672
+  function parseNumber(fmt, value) {
673
+    var format = replace(fmt, /^\?/);
674
+    if (format!=fmt && !trim(value))
675
+      return _null;
676
+    var decSep = (/(^|[^0#.,])(,|[0#.]*,[0#]+|[0#]+\.[0#]+\.[0#.,]*)($|[^0#.,])/.test(format)) ? ',' : '.';
677
+    var r = parseFloat(replace(replace(replace(value, decSep == ',' ? /\./g : /,/g), decSep, '.'), /^[^\d-]*(-?\d)/, '$1'));
678
+    return isNaN(r) ? undef : r;
679
+  }
680
+  function now() {
681
+    return new Date();
682
+  }
683
+  function dateClone(date) {
684
+    return new Date(+date);
685
+  }
686
+  function capWord(w) {
687
+    return w.charAt(0).toUpperCase() + w.substr(1);
688
+  }
689
+  function dateAddInline(d, cProp, value) {
690
+    d['set'+cProp](d['get'+cProp]() + value);
691
+    return d;
692
+  }
693
+  function dateAdd(date, property, value) {
694
+    if (value == _null)
695
+      return dateAdd(now(), date, property);
696
+    return dateAddInline(dateClone(date), capWord(property), value);
697
+  }
698
+  function dateMidnight(date) {
699
+    var od = date || now();
700
+    return new Date(od.getFullYear(), od.getMonth(), od.getDate());
701
+  }
702
+  function dateDiff(property, date1, date2) {
703
+    var d1t = +date1;
704
+    var d2t = +date2;
705
+    var dt = d2t - d1t;
706
+    if (dt < 0)
707
+      return -dateDiff(property, date2, date1);
708
+
709
+    var propValues = {'milliseconds': 1, 'seconds': 1000, 'minutes': 60000, 'hours': 3600000};
710
+    var ft = propValues[property];
711
+    if (ft)
712
+      return dt / ft;
713
+
714
+    var cProp = capWord(property);
715
+    var calApproxValues = {'fullYear': 8.64e7*365, 'month': 8.64e7*365/12, 'date': 8.64e7}; // minimum values, a little bit below avg values
716
+    var minimumResult = Math.floor((dt / calApproxValues[property])-2); // -2 to remove the imperfections caused by the values above
717
+
718
+    var d = dateAddInline(new Date(d1t), cProp, minimumResult);
719
+    for (var i = minimumResult; i < minimumResult*1.2+4; i++) { // try out 20% more than needed, just to be sure
720
+      if (+dateAddInline(d, cProp, 1) > d2t)
721
+        return i;
722
+    }
723
+    // should never ever be reached
724
+  }
725
+
726
+  function ucode(a) {
727
+    return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
728
+  }
729
+
730
+  function escapeJavaScriptString(s) {
731
+    return replace(s, /[\x00-\x1f'"\u2028\u2029]/g, ucode);
732
+  }
733
+
734
+  // reimplemented split for IE8
735
+  function split(str, regexp) {
736
+
737
+    return str.split(regexp);
738
+  }
739
+
740
+  function template(template, escapeFunction) {
741
+    if (templateCache[template])
742
+      return templateCache[template];
743
+    else {
744
+      var funcBody = 'with(_.isObject(obj)?obj:{}){'+
745
+                     map(split(template, /{{|}}}?/g), function(chunk, index) {
746
+                       var match, c1 = trim(chunk), c2 = replace(c1, /^{/), escapeSnippet  = (c1==c2) ? 'esc(' : '';
747
+                       if (index%2) { // odd means JS code
748
+                         if (match = /^each\b(\s+([\w_]+(\s*,\s*[\w_]+)?)\s*:)?(.*)/.exec(c2))
749
+                           return 'each('+(trim(match[4])?match[4]:'this')+', function('+match[2]+'){';
750
+                         else if (match = /^if\b(.*)/.exec(c2))
751
+                           return 'if('+match[1]+'){';
752
+                         else if (match = /^else\b\s*(if\b(.*))?/.exec(c2))
753
+                           return '}else ' + (match[1]  ? 'if('+match[2] +')' : '')+'{';
754
+                         else if (match = /^\/(if)?/.exec(c2))
755
+                           return match[1] ? '}\n' : '});\n';
756
+                         else if (match = /^(var\s.*)/.exec(c2))
757
+                           return match[1]+';';
758
+                         else if (match = /^#(.*)/.exec(c2))
759
+                           return match[1];
760
+                         else if (match = /(.*)::\s*(.*)/.exec(c2))
761
+                           return 'print('+escapeSnippet+'_.formatValue("'+escapeJavaScriptString(match[2])+'",'+(trim(match[1])?match[1]:'this')+(escapeSnippet&&')')+'));\n';
762
+                         else
763
+                           return 'print('+escapeSnippet+(trim(c2)?c2:'this')+(escapeSnippet&&')')+');\n';
764
+                       }
765
+                       else if (chunk){
766
+                         return 'print("'+escapeJavaScriptString(chunk)+'");\n';
767
+                       }
768
+                     }).join('')+'}';
769
+      var f = (new Function('obj', 'each', 'esc', 'print', '_', funcBody));
770
+      var t = function(obj, thisContext) {
771
+        var result = [];
772
+        f.call(thisContext || obj, obj, function(obj, func) {
773
+          if (isList(obj))
774
+            each(obj, function(value, index) { func.call(value, value, index); });
775
+          else
776
+            eachObj(obj, function(key, value) { func.call(value, key, value); });
777
+        }, escapeFunction || nonOp, function() {call(result['push'], result, arguments);}, _);
778
+        return result.join('');
779
+      };
780
+      if (templates.push(t) > MAX_CACHED_TEMPLATES)
781
+        delete templateCache[templates.shift()];
782
+      return templateCache[template] = t;
783
+    }
784
+  }
785
+
786
+  function escapeHtml(s) {
787
+    return replace(s, /[<>'"&]/g, function(s) {
788
+      return '&#'+s.charCodeAt(0)+';';
789
+    });
790
+  }
791
+
792
+  function formatHtml(tpl, obj) {
793
+    return template(tpl, escapeHtml)(obj);
794
+  }
795
+
796
+  function listBindArray(func) {
797
+    return function(arg1, arg2) {
798
+      return new M(func(this, arg1, arg2));
799
+    };
800
+  }
801
+  function listBind(func) {
802
+    return function(arg1, arg2, arg3) {
803
+      return func(this, arg1, arg2, arg3);
804
+    };
805
+  }
806
+  function funcArrayBind(func) {
807
+    return function(arg1, arg2, arg3) {
808
+      return new M(func(arg1, arg2, arg3));
809
+    };
810
+  }
811
+
812
+  ///#/snippet commonFunctions
813
+  ///#snippet webFunctions
814
+
815
+  // note: only the web version has the f.item check
816
+  function isFunction(f) {
817
+    return typeof f == 'function' && !f['item']; // item check as work-around for webkit bug 14547
818
+  }
819
+
820
+  function isList(v) {
821
+    return v && v.length != _null && !isString(v) && !isNode(v) && !isFunction(v) && v !== _window;
822
+  }
823
+
824
+  // used by IE impl of on() only
825
+  function push(obj, prop, value) {
826
+    (obj[prop] = (obj[prop] || [])).push(value);
827
+  }
828
+  // used by IE impl of on()/off() only
829
+  function removeFromArray(array, value) {
830
+    for (var i = 0; array && i < array.length; i++)
831
+      if (array[i] === value)
832
+        array['splice'](i--, 1);
833
+  }
834
+
835
+  function extractNumber(v) {
836
+    return parseFloat(replace(v, /^[^\d-]+/));
837
+  }
838
+
839
+  // retrieves the node id of the element, create one if needed.
840
+  function getNodeId(el) {
841
+    return (el[MINIFIED_MAGIC_NODEID] = (el[MINIFIED_MAGIC_NODEID] || ++idSequence));
842
+  }
843
+
844
+  // collect variant that filters out duplicate nodes from the given list, returns a new array
845
+  function collectUniqNodes(list, func) {
846
+    var result = [];
847
+    var nodeIds = {};
848
+    var currentNodeId;
849
+
850
+    flexiEach(list, function(value) {
851
+      flexiEach(func(value), function(node) {
852
+        if (!nodeIds[currentNodeId = getNodeId(node)]) {
853
+          result.push(node);
854
+          nodeIds[currentNodeId] = true;
855
+        }
856
+      });
857
+    });
858
+    return result;
859
+  }
860
+
861
+  // finds out the 'natural' height of the first element, the one if $$slide=1
862
+  function getNaturalHeight(elementList, factor) {
863
+    var q = {'$position': 'absolute', '$visibility': 'hidden', '$display': 'block', '$height': _null};
864
+    var oldStyles = elementList['get'](q);
865
+    var h = elementList['set'](q)['get']('clientHeight');
866
+    elementList['set'](oldStyles);
867
+    return h*factor + 'px';
868
+  }
869
+
870
+
871
+
872
+
873
+  // @condblock !ie8compatibility
874
+  function on(subSelector, eventSpec, handler, args, bubbleSelector) {
875
+    if (isFunction(eventSpec))
876
+      return this['on'](_null, subSelector, eventSpec, handler, args);
877
+    else if (isString(args))
878
+      return this['on'](subSelector, eventSpec, handler, _null, args);
879
+    else
880
+      return this['each'](function(baseElement, index) {
881
+        flexiEach(subSelector ? dollarRaw(subSelector, baseElement) : baseElement, function(registeredOn) {
882
+          flexiEach(toString(eventSpec).split(/\s/), function(namePrefixed) {
883
+            var name = replace(namePrefixed, /[?|]/g);
884
+            var prefix = replace(namePrefixed, /[^?|]/g);
885
+            var capture = (name == 'blur' || name == 'focus') && !!bubbleSelector; // bubble selectors for 'blur' and 'focus' registered as capuring!
886
+            var triggerId = idSequence++;
887
+
888
+            // returns true if processing should be continued
889
+            function triggerHandler(eventName, event, target) {
890
+              var match = !bubbleSelector;
891
+              var el = bubbleSelector ? target : registeredOn;
892
+              if (bubbleSelector) {
893
+                var selectorFilter = getFilterFunc(bubbleSelector, registeredOn);
894
+                while (el && el != registeredOn && !(match = selectorFilter(el)))
895
+                  el = el['parentNode'];
896
+              }
897
+              return (!match) || (name != eventName) || ((handler.apply($(el), args || [event, index]) && prefix=='?') || prefix == '|');
898
+            };
899
+
900
+            function eventHandler(event) {
901
+              if (!triggerHandler(name, event, event['target'])) {
902
+                event['preventDefault']();
903
+                event['stopPropagation']();
904
+              }
905
+            };
906
+
907
+            registeredOn.addEventListener(name, eventHandler, capture);
908
+
909
+            if (!registeredOn['M'])
910
+              registeredOn['M'] = {};
911
+            registeredOn['M'][triggerId] = triggerHandler;                  // to be called by trigger()
912
+
913
+            handler['M'] = collector(flexiEach, [handler['M'], function () { // this function will be called by off()
914
+              registeredOn.removeEventListener(name, eventHandler, capture);
915
+              delete registeredOn['M'][triggerId];
916
+            }], nonOp);
917
+
918
+          });
919
+        });
920
+      });
921
+  }
922
+  // @condend !ie8compatibility
923
+
924
+
925
+  // @condblock !ie8compatibility
926
+  function off(handler) {
927
+    callList(handler['M']);
928
+    handler['M'] = _null;
929
+  }
930
+  // @condend !ie8compatibility
931
+
932
+  // for remove & window.unload, IE only
933
+  function detachHandlerList(dummy, handlerList) {
934
+    flexiEach(handlerList, function(h) {
935
+      h.element.detachEvent('on'+h.eventType, h.handlerFunc);
936
+    });
937
+  }
938
+
939
+  function ready(handler) {
940
+    if (DOMREADY_HANDLER)
941
+      DOMREADY_HANDLER.push(handler);
942
+    else
943
+      setTimeout(handler, 0);
944
+  }
945
+
946
+  function $$(selector, context, childrenOnly) {
947
+    return dollarRaw(selector, context, childrenOnly)[0];
948
+  }
949
+
950
+  function EE(elementName, attributes, children) {
951
+    var e = $(document.createElement(elementName));
952
+    // @condblock UTIL
953
+    // this attributes != null check is only required with Util's isObject() implementation. Web's isObject() is simpler.
954
+    return (isList(attributes) || (attributes != _null && !isObject(attributes)) ) ? e['add'](attributes) : e['set'](attributes)['add'](children);
955
+    // @condend UTIL
956
+    // @cond !UTIL return (isList(attributes) || (!isObject(attributes)) ) ? e['add'](attributes) : e['set'](attributes)['add'](children);
957
+  }
958
+
959
+  function clone(listOrNode) {
960
+    return collector(flexiEach, listOrNode, function(e) {
961
+      var c;
962
+      if (isList(e))
963
+        return clone(e);
964
+      else if (isNode(e)) {
965
+        c = e['cloneNode'](true);
966
+        c['removeAttribute'] && c['removeAttribute']('id');
967
+        return c;
968
+      }
969
+      else
970
+        return e;
971
+    });
972
+  }
973
+
974
+  /*$
975
+   * @stop
976
+   */
977
+
978
+  function $(selector, context, childOnly) {
979
+    // @condblock ready
980
+    return isFunction(selector) ? ready(selector) : new M(dollarRaw(selector, context, childOnly));
981
+    // @condend
982
+    // @cond !ready return new M(dollarRaw(selector, context));
983
+  }
984
+
985
+  // implementation of $ that does not produce a Minified list, but just an array
986
+
987
+
988
+
989
+
990
+
991
+
992
+
993
+
994
+
995
+
996
+  // @condblock !ie7compatibility
997
+  function dollarRaw(selector, context, childOnly) {
998
+    function flatten(a) { // flatten list, keep non-lists, remove nulls
999
+      return isList(a) ? collector(flexiEach, a, flatten) : a;
1000
+    }
1001
+    function filterElements(list) { // converts into array, makes sure context is respected
1002
+      return filter(collector(flexiEach, list, flatten), function(node) {
1003
+        var a = node;
1004
+        while (a = a['parentNode'])
1005
+          if (a == context[0] || childOnly)
1006
+            return a == context[0];
1007
+        // fall through to return undef
1008
+      });
1009
+    }
1010
+
1011
+    if (context) {
1012
+      if ((context = dollarRaw(context)).length != 1)
1013
+        return collectUniqNodes(context, function(ci) { return dollarRaw(selector, ci, childOnly);});
1014
+      else if (isString(selector)) {
1015
+        if (isNode(context[0]) != 1)
1016
+          return [];
1017
+        else
1018
+          return childOnly ? filterElements(context[0].querySelectorAll(selector)) : context[0].querySelectorAll(selector);
1019
+      }
1020
+      else
1021
+        return filterElements(selector);
1022
+
1023
+    }
1024
+    else if (isString(selector))
1025
+      return document.querySelectorAll(selector);
1026
+    else
1027
+      return collector(flexiEach, selector, flatten);
1028
+  };
1029
+  // @condend !ie7compatibility
1030
+
1031
+  // If context is set, live updates will be possible.
1032
+  // Please note that the context is not evaluated for the '*' and 'tagname.classname' patterns, because context is used only
1033
+  // by on(), and in on() only nodes in the right context will be checked
1034
+  function getFilterFunc(selector, context) {
1035
+    function wordRegExpTester(name, prop) {
1036
+      var re = RegExp('(^|\\s+)' + name + '(?=$|\\s)', 'i');
1037
+      return function(obj) {return  name ? re.test(obj[prop]) : true;};
1038
+    }
1039
+
1040
+    var nodeSet = {};
1041
+    var dotPos = nodeSet;
1042
+    if (isFunction(selector))
1043
+      return selector;
1044
+    else if (isNumber(selector))
1045
+      return function(v, index) { return index == selector; };
1046
+    else if (!selector || selector == '*' ||
1047
+             (isString(selector) && (dotPos = /^([\w-]*)\.?([\w-]*)$/.exec(selector)))) {
1048
+      var nodeNameFilter = wordRegExpTester(dotPos[1], 'tagName');
1049
+      var classNameFilter = wordRegExpTester(dotPos[2], 'className');
1050
+      return function(v) {
1051
+        return isNode(v) == 1 && nodeNameFilter(v) && classNameFilter(v);
1052
+      };
1053
+    }
1054
+    else if (context)
1055
+      return function(v) {
1056
+        return $(selector, context)['find'](v)!=_null; // live search instead of node set, for on()
1057
+      };
1058
+    else {
1059
+      $(selector)['each'](function(node) {
1060
+        nodeSet[getNodeId(node)] = true;
1061
+      });
1062
+      return function(v) {
1063
+        return nodeSet[getNodeId(v)];
1064
+      };
1065
+    }
1066
+  }
1067
+
1068
+  function getInverseFilterFunc(selector) {
1069
+    var f = getFilterFunc(selector);
1070
+    return function(v) {return f(v) ? _null : true;};
1071
+  }
1072
+  ///#/snippet webFunctions
1073
+
1074
+  ///#snippet extrasFunctions
1075
+  function flexiEach(list, cb) {
1076
+    if (isList(list))
1077
+      each(list, cb);
1078
+    else if (list != _null)
1079
+      cb(list, 0);
1080
+    return list;
1081
+  }
1082
+
1083
+  function Promise() {
1084
+    this['state'] = null;
1085
+    this['values'] = [];
1086
+    this['parent'] = null;
1087
+  }
1088
+
1089
+  /*$
1090
+   * @id promise
1091
+   * @name _.promise()
1092
+   * @syntax _.promise()
1093
+   * @syntax _.promise(otherPromises...)
1094
+   * @module WEB+UTIL
1095
+   *
1096
+   * Creates a new ##promiseClass#Promise##, optionally assimilating other promises. If no other promise is given,
1097
+   * a fresh new promise is returned.
1098
+   *
1099
+   * The returned promise provides the methods ##fulfill() and ##reject() that can be called directly to change the promise's state,
1100
+   * as well as the more powerful ##fire().
1101
+   *
1102
+   * If one promise is given as parameter, the new promise assimilates the given promise as-is, and just forwards
1103
+   * fulfillment and rejection with the original values.
1104
+   *
1105
+   * If more than one promise are given, it will assimilate all of them with slightly different rules:
1106
+   * <ul><li>the new promise is fulfilled if all assimilated promises have been fulfilled. The fulfillment values
1107
+   *         of all assimilated promises are given to the handler as arguments. Note that the fulfillment values themselves are always
1108
+   *         arrays, as a promise can have several fulfillment values in Minified's implementation.</li>
1109
+   * <li>when one of the promises is rejected, the new promise is rejected immediately. The rejection handler gets the
1110
+   *     promises rejection value (first argument if it got several) as first argument, an array of the result values
1111
+   *     of all promises as a second (that means one array of arguments for each promise), and the index of the failed
1112
+   *     promise as third.
1113
+   * </li></ul>
1114
+   *
1115
+   * @example A simple promise that is fulfilled after 1 second, using Minified's invocation syntax:
1116
+   * <pre>var p = _.promise();
1117
+   * setTimeout(function() {
1118
+   *     p.fire(true);
1119
+   * }, 1000);
1120
+   * </pre>
1121
+   *
1122
+   * @example Request three files in parallel. When all three have been downloaded, concatenate them into a single string.
1123
+   * <pre>
1124
+   * var files = _('fileA.txt', 'fileA.txt', 'fileC.txt');
1125
+   * var content;
1126
+   * _.promise(files.map(function(file) {
1127
+   *      return $.request('get', '/txts/' + file);
1128
+   * })).then(function(fileRslt1, fileRslt2, fileRslt3) {
1129
+   *      content = _(fileRslt1, fileRslt2, fileRslt3).map( function(result) { return result[0]; }).join('');
1130
+   * }).error(function(status, response, xhr, url) {
1131
+   *    alert('failed to load file '+url);
1132
+   * });
1133
+   * </pre>
1134
+   *
1135
+   * @param otherPromises one or more promises to assimilate (varargs). You can also pass lists of promises.
1136
+   * @return the new promise.
1137
+   */
1138
+  function promise() {
1139
+    var deferred = [];   // this function calls the functions supplied by then()
1140
+
1141
+    var assimilatedPromises = arguments;
1142
+    var assimilatedNum = assimilatedPromises.length;
1143
+    var numCompleted = 0; // number of completed, assimilated promises
1144
+    var rejectionHandlerNum = 0;
1145
+
1146
+    var obj = new Promise();
1147
+
1148
+    obj['errHandled'] = function() {
1149
+      rejectionHandlerNum++;
1150
+      if (obj['parent'])
1151
+        obj['parent']['errHandled']();
1152
+    };
1153
+
1154
+    /*$
1155
+     * @id fire
1156
+     * @name promise.fire()
1157
+     * @syntax _.fire(newState)
1158
+     * @syntax _.fire(newState, values)
1159
+     * @module WEB+UTIL
1160
+     *
1161
+     * Changes the state of the promise into either fulfilled or rejected. This will also notify all ##then() handlers. If the promise
1162
+     * already has a state, the call will be ignored.
1163
+     *
1164
+     * <var>fire()</var> can be invoked as a function without context ('this'). Every promise has its own instance.
1165
+     *
1166
+     * @example A simple promise that is fulfilled after 1 second, using Minified's invocation syntax:
1167
+     * <pre>var p = _.promise();
1168
+     * setTimeout(function() {
1169
+     *     p.fire(true, []);
1170
+     * }, 1000);
1171
+     * </pre>
1172
+     *
1173
+     * @example Call <var>fire()</var> without a context:
1174
+     * <pre>var p = _.promise(function(resolve, reject) {
1175
+     *     setTimeout(resolve.fire, 1000);
1176
+     * });
1177
+     * </pre>
1178
+     *
1179
+     * @param newState <var>true</var> to set the Promise to fulfilled, <var>false</var> to set the state as rejected. If you pass <var>null</var> or
1180
+     * <var>undefined</var>, the promise's state does not change.
1181
+     * @param values optional an array of values to pass to ##then() handlers as arguments. You can also pass a non-list argument, which will then
1182
+     *               be passed as only argument.
1183
+     * @return the promise
1184
+     */
1185
+    var fire = obj['fire'] = function(newState, newValues) {
1186
+      if (obj['state'] == null && newState != null) {
1187
+        obj['state'] = !!newState;
1188
+        obj['values'] = isList(newValues) ? newValues : [newValues];
1189
+        setTimeout(function() {
1190
+          each(deferred, function(f) {f();});
1191
+        }, 0);
1192
+      }
1193
+      return obj;
1194
+    };
1195
+
1196
+    // use promise varargs
1197
+    each(assimilatedPromises, function assimilate(promise, index) {
1198
+      try {
1199
+        if (promise['then'])
1200
+          promise['then'](function(v) {
1201
+              var then;
1202
+              if ((isObject(v) || isFunction(v)) && isFunction(then = v['then']))
1203
+                assimilate(v, index);
1204
+              else {
1205
+                obj['values'][index] = array(arguments);
1206
+                if (++numCompleted == assimilatedNum)
1207
+                  fire(true, assimilatedNum < 2 ? obj['values'][index] : obj['values']);
1208
+              }
1209
+            },
1210
+            function(e) {
1211
+              obj['values'][index] = array(arguments);
1212
+              fire(false, assimilatedNum < 2 ? obj['values'][index] : [obj['values'][index][0], obj['values'], index]);
1213
+            });
1214
+        else
1215
+          promise(function() {fire(true, array(arguments));}, function() {fire(false, array(arguments)); });
1216
+      }
1217
+      catch (e) {
1218
+        fire(false, [e, obj['values'], index]);
1219
+      }
1220
+    });
1221
+
1222
+    /*$
1223
+     * @id stop
1224
+     * @name promise.stop()
1225
+     * @syntax promise.stop()
1226
+     * @module WEB+UTIL
1227
+     * Stops an ongoing operation, if supported. Currently the only promises supporting this are those returned by ##request(), ##animate(), ##wait() and
1228
+     * ##asyncEach().
1229
+     * stop() invocation will be propagated over promises returned by ##then() and promises assimilated by ##promise(). You only need to invoke stop
1230
+     * with the last promise, and all dependent promises will automatically stop as well.
1231
+     *
1232
+     *  <var>stop()</var> can be invoked as a function without context ('this'). Every promise has its own instance.
1233
+     *
1234
+     * @return In some cases, the <var>stop()</var> can return a value. This is currently only done by ##animate() and ##wait(), which will return the actual duration.
1235
+     *         ##asyncEach()'s promise will also return any value it got from the promise that it stopped.
1236
+     *
1237
+     * @example Animation chain that can be stopped.
1238
+     * <pre>
1239
+     * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
1240
+     * var prom = div.animate({$left: '200px', $top: '0px'}, 600, 0)
1241
+     *    .then(function() {
1242
+     *           return _.promise(div.animate({$left: '200px', $top: '200px'}, 800, 0),
1243
+     *                            div.animate({$backgroundColor: '#f00'}, 200));
1244
+     *    }).then(function() {
1245
+     *           return div.animate({$left: '100px', $top: '100px'}, 400);
1246
+     *    });
1247
+     *
1248
+     * $('#stopButton').on('click', prom.stop);
1249
+     * </pre>
1250
+     */
1251
+    obj['stop'] = function() {
1252
+      each(assimilatedPromises, function(promise) {
1253
+        if (promise['stop'])
1254
+          promise['stop']();
1255
+      });
1256
+
1257
+      return obj['stop0'] && call(obj['stop0']);
1258
+    };
1259
+
1260
+    /*$
1261
+     * @id then
1262
+     * @name promise.then()
1263
+     * @syntax promise.then()
1264
+     * @syntax promise.then(onSuccess)
1265
+     * @syntax promise.then(onSuccess, onError)
1266
+     *
1267
+     * @module WEB
1268
+     * Registers two callbacks that will be invoked when the ##promise#Promise##'s asynchronous operation finished
1269
+     * successfully (<var>onSuccess</var>) or an error occurred (<var>onError</var>). The callbacks will be called after
1270
+     * <var>then()</var> returned, from the browser's event loop.
1271
+     * You can chain <var>then()</var> invocations, as <var>then()</var> returns another Promise object that you can attach to.
1272
+     *
1273
+     * The full distribution of Minified implements the Promises/A+ specification, allowing interoperability with other Promises frameworks.
1274
+     *
1275
+     * <strong>Note:</strong> If you use the Web module, you will get a simplified Promises implementation that cuts some corners. The most notable
1276
+     * difference is that when a <code>then()</code> handler throws an exception, this will not be caught and the promise returned by
1277
+     * <code>then</code> will not be automatically rejected.
1278
+     *
1279
+     * @example Simple handler for an HTTP request. Handles only success and ignores errors.
1280
+     * <pre>
1281
+     * $.request('get', '/weather.html')
1282
+     *     .then(function(txt) {
1283
+     *        alert('Got response!');
1284
+     *     });
1285
+     * </pre>
1286
+     *
1287
+     * @example Including an error handler.
1288
+     * <pre>
1289
+     * $.request('get', '/weather.html')
1290
+     *     .then(function(txt) {
1291
+     *        alert('Got response!');
1292
+     *     }, function(err) {
1293
+     *        alert('Error!');
1294
+     *     }));
1295
+     * </pre>
1296
+     *
1297
+     * @example Chained handler.
1298
+     * <pre>
1299
+     * $.request('get', '/weather.do')
1300
+     *     .then(function(txt) {
1301
+     *        showWeather(txt);
1302
+     *     }
1303
+     *     .then(function() {
1304
+     *        return $.request('get', '/traffic.do');
1305
+     *     }
1306
+     *     .then(function(txt) {
1307
+     *        showTraffic(txt);
1308
+     *     }
1309
+     *     .then(function() {
1310
+     *        alert('All result displayed');
1311
+     *     }, function() {
1312
+     *        alert('An error occurred');
1313
+     *     });
1314
+     * </pre>
1315
+     *
1316
+     * @param onSuccess optional a callback function to be called when the operation has been completed successfully. The exact arguments it receives depend on the operation.
1317
+     *                           If the function returns a ##promise#Promise##, that Promise will be evaluated to determine the state of the promise returned by <var>then()</var>. If it returns any other value, the
1318
+     *                           returned Promise will also succeed. If the function throws an error, the returned Promise will be in error state.
1319
+     *                           Pass <var>null</var> or <var>undefined</var> if you do not need the success handler.
1320
+     * @param onError optional a callback function to be called when the operation failed. The exact arguments it receives depend on the operation. If the function returns a ##promise#Promise##, that promise will
1321
+     *                           be evaluated to determine the state of the Promise returned by <var>then()</var>. If it returns anything else, the returned Promise will
1322
+     *                           have success status. If the function throws an error, the returned Promise will be in the error state.
1323
+     *                           You can pass <var>null</var> or <var>undefined</var> if you do not need the error handler.
1324
+     * @return a new ##promise#Promise## object. If you specified a callback for success or error, the new Promises's state will be determined by that callback if it is called.
1325
+     *         If no callback has been provided and the original Promise changes to that state, the new Promise will change to that state as well.
1326
+     */
1327
+    var then = obj['then'] = function (onFulfilled, onRejected) {
1328
+      var promise2 = promise();
1329
+      var callCallbacks = function() {
1330
+        try {
1331
+          var f = (obj['state'] ? onFulfilled : onRejected);
1332
+          if (isFunction(f)) {
1333
+            (function resolve(x) {
1334
+              try {
1335
+                var then, cbCalled = 0;
1336
+                if ((isObject(x) || isFunction(x)) && isFunction(then = x['then'])) {
1337
+                  if (x === promise2)
1338
+                    throw new TypeError();
1339
+                  then.call(x, function(x) { if (!cbCalled++) resolve(x); }, function(value) { if (!cbCalled++) promise2['fire'](false, [value]);});
1340
+                  promise2['stop0'] = x['stop'];
1341
+                }
1342
+                else
1343
+                  promise2['fire'](true, [x]);
1344
+              }
1345
+              catch(e) {
1346
+                if (!(cbCalled++)) {
1347
+                  promise2['fire'](false, [e]);
1348
+                  if (!rejectionHandlerNum)
1349
+                    throw e;
1350
+                }
1351
+              }
1352
+            })(call(f, undef, obj['values']));
1353
+          }
1354
+          else
1355
+            promise2['fire'](obj['state'], obj['values']);
1356
+        }
1357
+        catch (e) {
1358
+          promise2['fire'](false, [e]);
1359
+          if (!rejectionHandlerNum)
1360
+            throw e;
1361
+        }
1362
+      };
1363
+      if (isFunction(onRejected))
1364
+        obj['errHandled']();
1365
+      promise2['stop0'] = obj['stop'];
1366
+      promise2['parent'] = obj;
1367
+      if (obj['state'] != null)
1368
+        setTimeout(callCallbacks, 0);
1369
+      else
1370
+        deferred.push(callCallbacks);
1371
+      return promise2;
1372
+    };
1373
+
1374
+    /*$
1375
+     * @id always
1376
+     * @group REQUEST
1377
+     * @name promise.always()
1378
+     * @syntax promise.always(callback)
1379
+     * @configurable default
1380
+     * @module WEB+UTIL
1381
+     * Registers a callback that will always be called when the ##promise#Promise##'s operation ended, no matter whether the operation succeeded or not.
1382
+     * This is a convenience function that will call ##then() with the same function for both arguments. It shares all of its semantics.
1383
+     *
1384
+     * @example Simple handler for a HTTP request.
1385
+     * <pre>
1386
+     * $.request('get', '/weather.html')
1387
+     *     .always(function() {
1388
+     *        alert('Got response or error!');
1389
+     *     });
1390
+     * </pre>
1391
+     *
1392
+     * @param callback a function to be called when the operation has been finished, no matter what its result was. The exact arguments depend on the operation and may
1393
+     *                 vary depending on whether it succeeded or not. If the function returns a ##promise#Promise##, that Promise will
1394
+     *                 be evaluated to determine the state of the returned Promise. If provided and it returns regularly, the returned promise will
1395
+     *                 have success status. If it throws an error, the returned Promise will be in the error state.
1396
+     * @return a new ##promise#Promise## object. Its state is determined by the callback.
1397
+     */
1398
+    obj['always'] = function(func) { return then(func, func); };
1399
+
1400
+    /*$
1401
+     * @id error
1402
+     * @group REQUEST
1403
+     * @name promise.error()
1404
+     * @syntax promise.error(callback)
1405
+     * @configurable default
1406
+     * @module WEB, UTIL
1407
+     * Registers a callback that will be called when the operation failed.
1408
+     * This is a convenience function that will invoke ##then() with only the second argument set.  It shares all of its semantics.
1409
+     *
1410
+     * @example Simple handler for a HTTP request.
1411
+     * <pre>
1412
+     * $.request('get', '/weather.html')
1413
+     *     .error(function() {
1414
+     *        alert('Got error!');
1415
+     *     });
1416
+     * </pre>
1417
+     *
1418
+     * @param callback a function to be called when the operation has failed. The exact arguments depend on the operation. If the function returns a ##promise#Promise##, that Promise will
1419
+     *                           be evaluated to determine the state of the returned Promise. If it returns regularly, the returned Promise will
1420
+     *                           have success status. If it throws an error, the returned Promise will be in error state.
1421
+     * @return a new ##promise#Promise## object. Its state is determined by the callback.
1422
+     */
1423
+    obj['error'] = function(func) { return then(0, func); };
1424
+
1425
+    return obj;
1426
+  }
1427
+
1428
+  ///#/snippet extrasFunctions
1429
+  ///#snippet extrasDocs
1430
+  /*$
1431
+   * @id length
1432
+   * @group SELECTORS
1433
+   * @requires dollar
1434
+   * @name list.length
1435
+   * @syntax length
1436
+   * @module WEB, UTIL
1437
+   *
1438
+   * Contains the number of elements in the ##list#Minified list##.
1439
+   *
1440
+   * @example With Web module:
1441
+   * <pre>
1442
+   * var list = $('input');
1443
+   * var myValues = {};
1444
+   * for (var i = 0; i &lt; list.length; i++)
1445
+   *    myValues[list[i].name] = list[i].value;
1446
+   * </pre>
1447
+   *
1448
+   * @example With Util module:
1449
+   * <pre>
1450
+   * var list = _(1, 2, 3);
1451
+   * var sum = 0;
1452
+   * for (var i = 0; i &lt; list.length; i++)
1453
+   *    sum += list[i];
1454
+   * </pre>
1455
+   */
1456
+  /*$
1457
+   * @stop
1458
+   */
1459
+  ///#/snippet extrasDocs
1460
+
1461
+  ///#snippet utilM
1462
+
1463
+  /*
1464
+   * syntax: M(list, assimilateSublists)
1465
+   *         M(null, singleElement)
1466
+   *
1467
+   *
1468
+   */
1469
+  /** @constructor */
1470
+  function M(list, assimilateSublists) {
1471
+    var self = this, idx = 0;
1472
+    if (list)
1473
+      for (var i = 0, len = list.length; i < len; i++) {
1474
+        var item = list[i];
1475
+        if (assimilateSublists && isList(item))
1476
+          for (var j = 0, len2 = item.length; j < len2; j++)
1477
+            self[idx++] = item[j];
1478
+        else
1479
+          self[idx++] = item;
1480
+      }
1481
+    else
1482
+      self[idx++] = assimilateSublists;
1483
+
1484
+    self['length'] = idx;
1485
+    self['_'] = true;
1486
+  }
1487
+
1488
+  function _() {
1489
+    return new M(arguments, true);
1490
+  }
1491
+
1492
+  ///#/snippet utilM
1493
+
1494
+  //// LIST FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
1495
+
1496
+  copyObj({
1497
+    ///#snippet utilListFuncs
1498
+    /*$
1499
+     * @id each
1500
+     * @group LIST
1501
+     * @requires
1502
+     * @configurable default
1503
+     * @name .each()
1504
+     * @altname _.each()
1505
+     * @syntax list.each(callback)
1506
+     * @syntax list.each(callback, ctx)
1507
+     * @syntax _.each(list, callback)
1508
+     * @syntax _.each(list, callback, ctx)
1509
+     * @module UTIL, WEB
1510
+     * Invokes the given function once for each item in the list. The function will be called with the item as first parameter and
1511
+     * the zero-based index as second. Unlike JavaScript's built-in <var>forEach()</var> it will be invoked for each item in the list,
1512
+     * even if it is <var>undefined</var>.
1513
+     *
1514
+     * @example Creates the sum of all list entries.
1515
+     * <pre>
1516
+     * var sum = 0;
1517
+     * _(17, 4, 22).each(function(item, index) {
1518
+     *     sum += item;
1519
+     * });
1520
+     * </pre>
1521
+     *
1522
+     * @example The previous example with a native array:
1523
+     * <pre>
1524
+     * var sum = 0;
1525
+     * _.each([17, 4, 22], function(item, index) {
1526
+     *     sum += item;
1527
+     * });
1528
+     * </pre>
1529
+     *
1530
+     * @example This goes through all h2 elements of the class 'section' on a web page and changes their content:
1531
+     * <pre>
1532
+     * $('h2.section').each(function(item, index) {
1533
+     *     item.innerHTML = 'Section ' + index + ': ' + item.innerHTML;
1534
+     * });
1535
+     * </pre>
1536
+     *
1537
+     * @param list a list to iterate. Can be an array, a ##list#Minified list## or any other array-like structure with
1538
+     *             <var>length</var> property.
1539
+     * @param callback The callback <code>function(item, index)</code> to invoke for each list element.
1540
+     *                 <dl><dt>item</dt><dd>The current list element.</dd>
1541
+     *                 <dt>index</dt><dd>The second the zero-based index of the current element.</dd>
1542
+     * 			       <dt class="this">this</dt><dd>The given context if not null. Otherwise the list.</dd>
1543
+     *                 The callback's return value will be ignored.
1544
+     * @param ctx optional a context to pass to the callback as 'this'. Only supported in UTIL module.
1545
+     * @return the list
1546
+     *
1547
+     * @see ##per() works like <var>each()</var>, but wraps the list elements in a list.
1548
+     * @see ##find() can be used instead of <var>each()</var> if you need to abort the loop.
1549
+     * @see ##eachObj() iterates through the properties of an object.
1550
+     */
1551
+    'each': listBind(each),
1552
+
1553
+    /*$
1554
+     * @id equals
1555
+     * @group LIST
1556
+     * @requires
1557
+     * @configurable default
1558
+     * @name .equals()
1559
+     * @altname _.equals()
1560
+     * @syntax list.equals(otherObject)
1561
+     * @syntax _.equals(thisObject, otherObject)
1562
+     * @module UTIL
1563
+     * Checks whether two values, lists or objects are equal in a deep comparison.
1564
+     *
1565
+     * First <var>equals()</var> checks whether it got a function as parameter.
1566
+     * If yes, it will be invoked without arguments and <var>equals()</var> calls itself recursively with the function's result.
1567
+     *
1568
+     * Once both values are no functions anymore, the values will be evaluated, If the first value is...
1569
+     * <ul><li>...<var>null</var> or <var>undefined</var>, they are only equal if the other one is also either <var>null</var> or <var>undefined</var>.</li>
1570
+     * <li>...a value as defined by ##_.isValue(), but not a Date, they are equal if the other value is the same type and is equal according to the '==' operator.</li>
1571
+     * <li>...a Date, they are equal if the other value is a Date representing the same time.</li>
1572
+     * <li>...a list or array, they are equal if the other value is also either a list or an array, has the same number of items and all items equal the items of the other
1573
+     *         list at the same position. The equality of list items is determined recursively using the same rules, so you can also nest lists.</li>
1574
+     * <li>...a function, it will be invoked without arguments and its return value is evaluated using these rules as if the value has been passed. </li>
1575
+     * <li>...any other object, they are equal if they contain exactly the same keys (as defined by ##_.eachObj()) and all values are equal as determined using these rules
1576
+     *      recursively.</li>
1577
+     * </ul>
1578
+     *
1579
+     * Please note that, according to the rules, a ##list#Minified list## is equal to an array, as long as their content is equal. <var>equals</var> does not
1580
+     * differentiate between <var>null</var> and <var>undefined</var>.
1581
+     *
1582
+     * <var>equals</var> is commutative. If you swap the parameters, the result is the same as long as no functions are involved.
1583
+     *
1584
+     * @example Compare a list and an array:
1585
+     *  <pre>
1586
+     *  _.equals([1, 2, 3], _(1, 2, 3));  // returns true
1587
+     * </pre>
1588
+     *
1589
+     * @example Same result, but with a list method:
1590
+     *  <pre>
1591
+     *  _(1, 2, 3).equals([1, 2, 3]);  // returns true
1592
+     * </pre>
1593
+     *
1594
+     * @param thisObject The first reference to evaluate.
1595
+     * @param otherObject The second reference to evaluate.
1596
+     * @return true if both references are equal. False otherwise.
1597
+     */
1598
+    'equals': listBind(equals),
1599
+
1600
+    /*$
1601
+     * @id find
1602
+     * @group LIST
1603
+     * @requires
1604
+     * @configurable default
1605
+     * @name .find()
1606
+     * @altname _.find()
1607
+     * @syntax list.find(findFunc)
1608
+     * @syntax list.find(element)
1609
+     * @syntax list.find(findFunc, startIndex)
1610
+     * @syntax list.find(element, startIndex)
1611
+     * @syntax _.find(list, findFunc)
1612
+     * @syntax _.find(list, element)
1613
+     * @syntax _.find(list, findFunc, startIndex)
1614
+     * @syntax _.find(list, element, startIndex)
1615
+     * @module WEB, UTIL
1616
+     * Finds a specific value in the list. There are two ways of calling <var>find()</var>:
1617
+     * <ol>
1618
+     * <li>With a value as argument. Then <var>find()</var> will search for the first occurrence of an identical value in the list,
1619
+     *     using the '===' operator for comparisons, and return the index. If it is not found,
1620
+     *     <var>find()</var> returns <var>undefined</var>.</li>
1621
+     * <li>With a callback function. <var>find()</var> will then call the given function for each list element until the function
1622
+     *     returns a value that is not <var>null</var> or <var>undefined</var>. This value will be returned.</li>
1623
+     * </ol>
1624
+     *
1625
+     * <var>find()</var> can also be used as an alternative to ##each() if you need to abort the loop.
1626
+     *
1627
+     * @example Finds the first negative number in the list:
1628
+     * <pre>
1629
+     * var i = _(1, 2, -4, 5, 2, -1).find(function(value, index) { if (value &lt; 0) return index; }); // returns 2
1630
+     * </pre>
1631
+
1632
+     * @example Finds the index of the first 5 in the array:
1633
+     * <pre>
1634
+     * var i = _.find([3, 6, 7, 6, 5, 4, 5], 5); // returns 4 (index of first 5)
1635
+     * </pre>
1636
+     *
1637
+     * @example Determines the position of the element with the id '#wanted' among all li elements:
1638
+     * <pre>
1639
+     * var elementIndex = $('li').find($$('#wanted'));
1640
+     * </pre>
1641
+     *
1642
+     * @example Goes through the elements to find the first div that has the class 'myClass', and returns this element:
1643
+     * <pre>
1644
+     * var myClassElement = $('div').find(function(e) { if ($(e).is('.myClass')) return e; });
1645
+     * </pre>
1646
+     *
1647
+     * @param list A list to use as input. Can be an array, a ##list#Minified list## or any other array-like structure with
1648
+     *             <var>length</var> property.
1649
+     * @param findFunc The callback <code>function(item, index)</code> that will be invoked for every list item until it returns a non-null value:
1650
+     * <dl><dt>item</dt><dd>The current list element.</dd><dt>index</dt><dd>The second the zero-based index of the current element.</dd>
1651
+     *        <dt class="this">this</dt><dd>This list.</dd>
1652
+     *        <dt class="returnValue">(callback return value)</dt><dd>If the callback returns something other than <var>null</var> or
1653
+     *        <var>undefined</var>, <var>find()</var> will return it directly. Otherwise it will continue. </dd></dl>
1654
+     * @param element the element to search for
1655
+     * @param startIndex optional the 0-based index of the first element to search.
1656
+     * @return if called with an element, either the element's index in the list or <var>undefined</var> if not found. If called with a callback function,
1657
+     *         it returns either the value returned by the callback or <var>undefined</var>.
1658
+     *
1659
+     * @see ##findLast() is the equivalent to <var>find()</var> for the list's end.
1660
+     */
1661
+    'find': listBind(find),
1662
+
1663
+    /*$
1664
+     * @stop
1665
+     */
1666
+    dummySort:0
1667
+    ,
1668
+    ///#/snippet utilListFuncs
1669
+    ///#snippet webListFuncs
1670
+
1671
+    /*$
1672
+     * @id select
1673
+     * @group SELECTORS
1674
+     * @requires dollar
1675
+     * @configurable default
1676
+     * @name .select()
1677
+     * @syntax list.select(selector)
1678
+     * @syntax list.select(selector, childrenOnly)
1679
+     * @module WEB
1680
+     * Executes a selector with the list as context. <code>list.select(selector, childrenOnly)</code> is equivalent
1681
+     * to <code>$(selector, list, childrenOnly)</code>.
1682
+     *
1683
+     * @example Returns a list of all list elements:
1684
+     * <pre>
1685
+     * var parents = $('ol.myList').select('li', true);
1686
+     * </pre>
1687
+     *
1688
+     * @example Returns a list of all child elements:
1689
+     * <pre>
1690
+     * var children = $('.myElements').select('*', true);
1691
+     * </pre>
1692
+     *
1693
+     * @param selector a selector or any other valid first argument for #dollar#$().
1694
+     * @param childrenOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not
1695
+     *             true, all descendants of the context will be included.
1696
+     * @return the new list containing the selected descendants.
1697
+     *
1698
+     * @see ##only() executes a selector on the list elements, instead of their descendants.
1699
+     */
1700
+    'select': function(selector, childOnly) {
1701
+      return $(selector, this, childOnly);
1702
+    },
1703
+
1704
+    /*$
1705
+     * @id get
1706
+     * @group SELECTORS
1707
+     * @requires dollar
1708
+     * @configurable default
1709
+     * @name .get()
1710
+     * @syntax list.get(name)
1711
+     * @syntax list.get(name, toNumber)
1712
+     * @syntax list.get(list)
1713
+     * @syntax list.get(list, toNumber)
1714
+     * @syntax list.get(map)
1715
+     * @syntax list.get(map, toNumber)
1716
+     * @module WEB
1717
+     * Retrieves properties, attributes and styles from the list's first element. The syntax to request those values is mostly identical with ##set(). You can either
1718
+     * get a single value if you specify only one name, or get an object map when you specify several names using an array or an object map.
1719
+     *
1720
+     * The <var>name</var> parameter defines what kind of data you are reading. The following name schemes are supported:
1721
+     * <table>
1722
+     * <tr><th>Name Schema</th><th>Example</th><th>Sets what?</th><th>Description</th></tr>
1723
+     * <tr><td>name</td><td>innerHTML</td><td>Property</td><td>A name without prefix of '$' or '@' gets a property of the object.</td></tr>
1724
+     * <tr><td>@name</td><td>@href</td><td>Attribute</td><td>Gets the HTML attribute using getAttribute().</td></tr>
1725
+     * <tr><td>%name</td><td>%phone</td><td>Data-Attribute</td><td>Gets a data attribute using getAttribute(). Data attributes are
1726
+     *         attributes whose names start with 'data-'. '%myattr' and '@data-myattr' are equivalent.</td></tr>
1727
+     * <tr><td>$name</td><td>$fontSize</td><td>CSS Property</td><td>Gets a style using the element's <var>style</var> object.
1728
+     *             The syntax for the CSS styles is camel-case (e.g. "$backgroundColor", not "$background-color"). Shorthand properties like "border" or "margin" are
1729
+     *             not supported. You must use the full name, e.g. "$marginTop". Minified will try to determine the effective style
1730
+     *             and thus will return the value set in style sheets if not overwritten using a regular style.</td></tr>
1731
+     * <tr><td>$</td><td>$</td><td>CSS Classes</td><td>A simple <var>$</var> returns the CSS classes of the element and is identical with "className".</td></tr>
1732
+     * <tr><td>$$</td><td>$$</td><td>Style</td><td>Reads the element's style attribute in a browser-independent way. On legacy IEs it uses
1733
+     *             <var>style.cssText</var>, and on everything else just the "style" attribute.</td></tr>
1734
+     * <tr><td>$$show</td><td>$$show</td><td>Show/Hide</td><td>Returns 1 if the element is visible and 0 if it is not visible. An element counts as
1735
+     * visible if '$visibility' is not 'hidden' and '$display' is not 'none'. Other properties will be ignored, even if they can also be used to hide the element.</td></tr>
1736
+     * <tr><td>$$fade</td><td>$$fade</td><td>Fade Effect</td><td>The name '$$fade' returns the opacity of the element as a value between 0 and 1.
1737
+     * 			   '$$fade' will also automatically evaluate the element's 'visibility' and 'display' styles to find out whether the element is actually visible.</td></tr>
1738
+     * <tr><td>$$slide</td><td>$$slide</td><td>Slide Effect</td><td>'$$slide' returns the height of the element in pixels with a 'px' suffix and is equivalent to '$height'.
1739
+     * Please note that you can pass that 'px' value to '$$slide' in ##set(), which will then set the according '$height'.</td></tr>
1740
+     * <tr><td>$$scrollX, $$scrollY</td><td>$$scrollY</td><td>Scroll Coordinates</td><td>The names '$$scrollX' and
1741
+     *             '$$scrollY' can be used on <code>$(window)</code> to retrieve the scroll coordinates of the document.
1742
+     *             The coordinates are specified in pixels without a 'px' unit postfix.</td></tr>
1743
+     * </table>
1744
+     *
1745
+     * @example Retrieves the id, title attribute and the background color of the element '#myElement':
1746
+     * <pre>
1747
+     * var id = $('#myElement).get('id');
1748
+     * var title = $('#myElement).get('@title');
1749
+     * var bgColor = $('#myElement).get('$backgroundColor');
1750
+     * </pre>
1751
+     *
1752
+     * @example Retrieves the id, title attribute and the background color of the element '#myElement' as a map:
1753
+     * <pre>
1754
+     * var m = $('#myElement).get(['id', '@title', '$backgroundColor']);
1755
+     * var id = m.id;
1756
+     * var title = m['@title'];
1757
+     * var bgColor = m.$backgroundColor;
1758
+     * </pre>
1759
+     *
1760
+     * @example Uses ##get() and ##set() to reposition an element:
1761
+     * <pre>
1762
+     * var coords = $('#myElement').get({$top: 0, $left: 0}, true);
1763
+     * coords.$top = coords.$top + 10 + 'px';
1764
+     * coords.$left = coords.$left + 20 + 'px';
1765
+     * $('#myElement').set(coords);
1766
+     * </pre>
1767
+     * Please note that the values of $top and $left in the <var>get()</var> invocation do not matter and will be ignored!
1768
+     *
1769
+     * @param name the name of a single property or attribute to modify. Unprefixed names set properties, a '$' prefix sets CSS styles and
1770
+     *        '@' sets attributes. Please see the table above for special properties and other options.
1771
+     * @param list in order to retrieve more than one value, you can specify several names in an array or list. <var>get()</var> will then return an object map
1772
+     *        containing the values.
1773
+     * @param map if you specify an object that is neither list nor string, <var>get()</var> will use it as a map of property names. Each property name will be requested.
1774
+     * The values of the properties in the map will be ignored. <var>get()</var> will then return a new object map containing of results.
1775
+     * @param toNumber if 'true', <var>get()</var> converts all returned values into numbers. If they are strings,
1776
+     *                 <var>get()</var> removes any non-numeric characters before the conversion. This is useful when you request
1777
+     *                 a CSS property such as '$marginTop'  that returns a value with a unit suffix, like "21px". <var>get()</var> will convert it
1778
+     *                 into a number and return 21. If the returned value is not parsable as a number, <var>NaN</var> will be returned.
1779
+     * @return if <var>get()</var> was called with a single name, it returns the corresponding value.
1780
+     *         If a list or map was given, <var>get()</var> returns a new object map with the names as keys and the values as values.
1781
+     *         It returns <var>undefined</var> if the list is empty.
1782
+     *
1783
+     * @see ##set() sets values using the same property syntax.
1784
+     */
1785
+    'get': function(spec, toNumber) {
1786
+      var self = this;
1787
+      var element = self[0];
1788
+
1789
+      if (element) {
1790
+        if (isString(spec)) {
1791
+          var match = /^(\W*)(.*)/.exec(replace(spec, /^%/,'@data-'));
1792
+          var prefix = match[1];
1793
+          var s;
1794
+
1795
+          if (getter[prefix])
1796
+            s = getter[prefix](this, match[2]);
1797
+          else if (spec == '$')
1798
+            s = self['get']('className');
1799
+          else if (spec == '$$') {
1800
+            s = self['get']('@style');
1801
+          }
1802
+          else if (spec == '$$slide')
1803
+            s = self['get']('$height');
1804
+          else if (spec == '$$fade' || spec == '$$show') {
1805
+            if  (self['get']('$visibility') == 'hidden' || self['get']('$display') == 'none')
1806
+              s = 0;
1807
+            else if (spec == '$$fade') {
1808
+              s =
1809
+                isNaN(self['get']('$opacity', true)) ? 1 : self['get']('$opacity', true);
1810
+            }
1811
+            else // $$show
1812
+              s = 1;
1813
+          }
1814
+          else if (prefix == '$') {
1815
+            s = _window['getComputedStyle'](element, _null)['getPropertyValue'](replace(match[2], /[A-Z]/g, function (match2) {  return '-' + match2.toLowerCase(); }));
1816
+          }
1817
+          else if (prefix == '@')
1818
+            s = element.getAttribute(match[2]);
1819
+          else
1820
+            s = element[match[2]];
1821
+          return toNumber ? extractNumber(s) : s;
1822
+        }
1823
+        else {
1824
+          var r = {};
1825
+          (isList(spec) ? flexiEach : eachObj)(spec, function(name) {
1826
+            r[name] = self['get'](name, toNumber);
1827
+          });
1828
+          return r;
1829
+        }
1830
+      }
1831
+    },
1832
+
1833
+    /*$
1834
+     * @id set
1835
+     * @group SELECTORS
1836
+     * @requires dollar get
1837
+     * @configurable default
1838
+     * @name .set()
1839
+     * @syntax list.set(name, value)
1840
+     * @syntax list.set(properties)
1841
+     * @syntax list.set(cssClasses)
1842
+     * @module WEB
1843
+     *
1844
+     * Modifies the list's elements by setting their properties, attributes, CSS styles and/or CSS classes. You can either supply a
1845
+     * single name and value to set only one property, or you can provide an object that contains name/value pairs to describe more than one property.
1846
+     * More complex operations can be accomplished by supplying functions as values. They will then be called for each element that will
1847
+     * be set.
1848
+     *
1849
+     * The <var>name</var> parameter defines what kind of data you are setting. The following name schemes are supported:
1850
+     *
1851
+     * <table>
1852
+     * <tr><th>Name Schema</th><th>Example</th><th>Sets what?</th><th>Description</th></tr>
1853
+     * <tr><td>name</td><td>innerHTML</td><td>Property</td><td>A name without prefix of '$' or '@' sets a property of the object.</td></tr>
1854
+     * <tr><td>@name</td><td>@href</td><td>Attribute</td><td>Sets the HTML attribute using setAttribute(). In order to stay compatible with Internet Explorer 7 and earlier,
1855
+     *             you should not set the attributes '@class' and '@style'. Instead use '$' and '$$' as shown below.</td></tr>
1856
+     * <tr><td>%name</td><td>%phone</td><td>Data-Attribute</td><td>Sets a data attribute using setAttribute(). Data attributes are
1857
+     *         attributes whose names start with 'data-'. '%myattr' and '@data-myattr' are equivalent.</td></tr>
1858
+     * <tr><td>$name</td><td>$fontSize</td><td>CSS Property</td><td>Sets a style using the element's <var>style</var> object.
1859
+     *         The syntax for the CSS styles is camel-case (e.g. "$backgroundColor", not "$background-color"). </td></tr>
1860
+     * <tr><td>$</td><td>$</td><td>CSS Classes</td><td>A simple <var>$</var> modifies the element's CSS classes using the object's <var>className</var> property. The value is a
1861
+     *             space-separated list of class names. If prefixed with '-' the class is removed, a '+' prefix adds the class and a class name without prefix toggles the class.
1862
+     *             The name '$' can also be omitted if <var>set</var> is called with class names as only argument.</td></tr>
1863
+     * <tr><td>$$</td><td>$$</td><td>Style</td><td>Sets the element's style attribute in a browser-independent way.</td></tr>
1864
+     * <tr><td>$$show</td><td>$$show</td><td>Show/Hide</td><td>If <var>true</var> or a number not 0, it will make sure the element is visible by
1865
+     *         making sure '$display' is not 'none' and by setting '$visibility' to 'visible'. Please see ##show() for details. If the value is <var>false</var> or 0, it
1866
+     *         will be hidden by setting '$display' to 'none'.</td></tr>
1867
+     * <tr><td>$$fade</td><td>$$fade</td><td>Fade Effect</td><td>The name '$$fade' sets the opacity of the element in a browser-independent way. The value must be a number
1868
+     *              between 0 and 1. '$$fade' will also automatically control the element's 'visibility' style. If the value is 0,
1869
+     *             the element's visibility will automatically be set to 'hidden'. If the value is larger, the visibility will be set to
1870
+     *             'visible'. '$$fade' only works with block elements.</td></tr>
1871
+     * <tr><td>$$slide</td><td>$$slide</td><td>Slide Effect</td><td>The name '$$slide' allows a vertical slide-out or slide-in effect. The value must be a number
1872
+     *              between 0 and 1 and will be used to set the element's '$height'. '$$slide' will also automatically control the element's 'visibility'
1873
+     *              style. If the value is 0, the element's visibility will automatically be set to 'hidden'. If the value is larger,
1874
+     *              the visibility will be set to 'visible'. '$$slide' only works with block elements and will not set the
1875
+     *              element's margin or padding. If you need a margin or padding, you should wrap the elements in a simple &lt;div>.</td></tr>
1876
+     * <tr><td>$$scrollX, $$scrollY</td><td>$$scrollY</td><td>Scroll Coordinates</td><td>The names '$$scrollX' and
1877
+     *             '$$scrollY' can be used on <code>$(window)</code> to set the scroll coordinates of the document.
1878
+     *             The coordinates are specified in pixels, but must not use a 'px' unit postfix.</td></tr>
1879
+     * </table>
1880
+     *
1881
+     * @example Unchecking checkboxes:
1882
+     * <pre>
1883
+     * $('input.checkbox').set('checked', false);
1884
+     * </pre>
1885
+     *
1886
+     * @example Changing the <var>innerHTML</var> property of an element:
1887
+     * <pre>
1888
+     * $('#toc').set('innerHTML', 'Content');
1889
+     * </pre>
1890
+     *
1891
+     * @example Changing attributes:
1892
+     * <pre>
1893
+     * $('a.someLinks').set('@href', 'http://www.example.com/');
1894
+     * </pre>
1895
+     *
1896
+     * @example Removing attributes:
1897
+     * <pre>
1898
+     * $('a.someLinks').set('@title', null);
1899
+     * </pre>
1900
+     *
1901
+     * @example Changing styles:
1902
+     * <pre>
1903
+     * $('.bigText').set('$fontSize', 'x-large');
1904
+     * </pre>
1905
+     *
1906
+     * @example Adding and removing CSS classes:
1907
+     * <pre>
1908
+     * $('.myElem').set('$', '+myClass -otherClass');
1909
+     * </pre>
1910
+     *
1911
+     * @example Toggling a CSS class:
1912
+     * <pre>
1913
+     * $('.myElem').set('$', 'on');
1914
+     * </pre>
1915
+     *
1916
+     * @example Shortcut for CSS manipulation:
1917
+     * <pre>
1918
+     * $('.myElem').set('+myClass -otherClass on');
1919
+     * </pre>
1920
+     *
1921
+     * @example Making an element transparent:
1922
+     * <pre>
1923
+     * $('.seeThrough').set('$$fade', 0.5);
1924
+     * </pre>
1925
+     *
1926
+     * @example Making an element visible. Note that $$fade will set the element's display style to 'block' and visibility style to 'visible'.
1927
+     * <pre>
1928
+     * $('.myElem').set('$$fade', 1);
1929
+     * </pre>
1930
+     *
1931
+     * @example Using a map to change several properties:
1932
+     * <pre>
1933
+     * $('input.checkbox').set({checked: false,
1934
+     *                          '@title': 'Check this'});
1935
+     * </pre>
1936
+     *
1937
+     * @example Changing CSS with a map:
1938
+     * <pre>
1939
+     * $('.importantText').set({$fontSize: 'x-large',
1940
+     *                          $color: 'black',
1941
+     *                          $backgroundColor: 'red',
1942
+     *                          $: '+selected -default'});
1943
+     * </pre>
1944
+     *
1945
+     * @example You can specify a function as value to modify a value instead of just setting it:
1946
+     * <pre>
1947
+     * $('h2').set('innerHTML', function(oldValue, index) {
1948
+     *     return 'Chapter ' + index + ': ' + oldValue.toUpperCase();
1949
+     * });
1950
+     * </pre>
1951
+     *
1952
+     * @param name the name of a single property or attribute to modify. Unprefixed names set properties, a '$' prefix sets CSS styles and
1953
+     *        '@' sets attributes. Please see the table above for special properties and other options.
1954
+     * @param value the value to set. If value is <var>null</var> and name specified an attribute, the attribute will be removed.
1955
+     * If dollar ('$') has been passed as name, the value can contain space-separated CSS class names. If prefixed with a '+' the class will be added,
1956
+     * with a '-' prefix the class will be removed. Without prefix, the class will be toggled.
1957
+     * If <var>value</var> is a function, the <code>function(oldValue, index, obj)</code> will be invoked for each list element
1958
+     * to evaluate the new value:
1959
+     * <dl><dt>oldValue</dt><dd>The old value of the property to be changed, as returned by ##get().
1960
+     * For the CSS style names, this is the computed style of the property </dd>
1961
+     * <dt>index</dt><dd>The list index of the object owning the property</dd>
1962
+     * <dt>obj</dt><dd>The list element owning the property.</dd>
1963
+     * <dt class="returnValue">(callback return value)</dt><dd>The value to be set.</dd></dl>
1964
+     * Functions are not supported by '$'.
1965
+     * @param properties a Object as map containing names as keys and the values to set as map values. See above for the name and value syntax.
1966
+     * @param cssClasses if <var>set()</var> is invoked with a string as single argument, the name "$" (CSS classes) is assumed and the argument is the
1967
+     *                   value. See above for CSS syntax.
1968
+     *                   Instead of a string, you can also specify a <code>function(oldValue, index, obj)</code> to modify the existing classes.
1969
+     * @return the list
1970
+     *
1971
+     * @see ##get() retrieves values using the same property syntax.
1972
+     * @see ##animate() animates values using the same property syntax.
1973
+     * @see ##toggle() can toggle between two sets of values.
1974
+     * @see ##dial() allows smooth transitions between two sets of values.
1975
+     */
1976
+    'set': function (name, value) {
1977
+      var self = this;
1978
+      if (value !== undef) {
1979
+        var match = /^(\W*)(.*)/.exec(replace(replace(name, /^\$float$/, 'cssFloat'), /^%/,'@data-'));
1980
+        var prefix = match[1];
1981
+
1982
+        if (setter[prefix])
1983
+          setter[prefix](this, match[2], value);
1984
+        else if (name == '$$fade') {
1985
+          this['set']({'$visibility': value ? 'visible' : 'hidden', '$opacity': value});
1986
+        }
1987
+        else if (name == '$$slide') {
1988
+          self['set']({'$visibility': value ? 'visible' : 'hidden', '$overflow': 'hidden',
1989
+            '$height': /px/.test(value) ? value : function(oldValue, idx, element) { return getNaturalHeight($(element), value);}
1990
+          });
1991
+        }
1992
+        else if (name == '$$show') {
1993
+          if (value)
1994
+            self['set']({'$visibility': value ? 'visible' : 'hidden', '$display': ''}) // that value? part is only for gzip
1995
+              ['set']({'$display': function(oldVal) {                                // set for 2nd time: now we get the stylesheet's $display
1996
+              return oldVal == 'none' ? 'block' : oldVal;
1997
+            }});
1998
+          else
1999
+            self['set']({'$display': 'none'});
2000
+        }
2001
+        else if (name == '$$') {
2002
+          self['set']('@style', value);
2003
+        }
2004
+        else
2005
+          flexiEach(this, function(obj, c) {
2006
+            var newValue = isFunction(value) ? value($(obj)['get'](name), c, obj) : value;
2007
+            if (prefix == '$') {
2008
+              if (match[2])
2009
+                obj['style'][match[2]] = newValue;
2010
+              else {
2011
+                flexiEach(newValue && newValue.split(/\s+/), function(clzz) {
2012
+                  var cName = replace(clzz, /^[+-]/);
2013
+
2014
+                  if (/^\+/.test(clzz))
2015
+                    obj['classList'].add(cName);
2016
+                  else if (/^-/.test(clzz))
2017
+                    obj['classList'].remove(cName);
2018
+                  else
2019
+                    obj['classList'].toggle(cName);
2020
+                });
2021
+              }
2022
+            }
2023
+            else if (name == '$$scrollX')
2024
+              obj['scroll'](newValue, $(obj)['get']('$$scrollY'));
2025
+            else if (name == '$$scrollY')
2026
+              obj['scroll']($(obj)['get']('$$scrollX'), newValue);
2027
+            else if (prefix == '@') {
2028
+              if (newValue == _null)
2029
+                obj.removeAttribute(match[2]);
2030
+              else
2031
+                obj.setAttribute(match[2], newValue);
2032
+            }
2033
+            else
2034
+              obj[match[2]] = newValue;
2035
+          });
2036
+      }
2037
+      else if (isString(name) || isFunction(name))
2038
+        self['set']('$', name);
2039
+      else
2040
+        eachObj(name, function(n,v) { self['set'](n, v); });
2041
+      return self;
2042
+    },
2043
+
2044
+    /*$
2045
+     * @id add
2046
+     * @group ELEMENT
2047
+     * @requires dollar each
2048
+     * @configurable default
2049
+     * @name .add()
2050
+     * @syntax list.add(text)
2051
+     * @syntax list.add(node)
2052
+     * @syntax list.add(list)
2053
+     * @syntax list.add(factoryFunction)
2054
+     * @module WEB
2055
+     * Adds the given node(s) as children to the list's HTML elements. If a string has been given, it will be added as text node.
2056
+     * DOM nodes will be added directly. If you pass a list, all its elements will be added using the rules above.
2057
+     *
2058
+     * When you pass a DOM node and the target list has more than one element, the original node will be added to the first list element,
2059
+     * and ##clone#clones## to all following list elements.
2060
+     *
2061
+     * ##EE(), ##HTML() and ##clone() are compatible with <var>add()</var> and can help you create new HTML nodes.
2062
+     *
2063
+     * @example Using the following HTML:
2064
+     * <pre>
2065
+     * &lt;div id="comments">Here is some text.&lt;br/>&lt;/div>
2066
+     * </pre>
2067
+     * The next line appends a text node to the div:
2068
+     * <pre>
2069
+     * $('#comments').add('Some additional text.');
2070
+     * </pre>
2071
+     * This results in:
2072
+     * <pre>
2073
+     * &lt;div id="comments">Here is some text.&lt;br/>Some additional text.&lt;/div>
2074
+     * </pre>
2075
+     *
2076
+     * @example Using the following HTML:
2077
+     * <pre>
2078
+     * &lt;ul id="myList">
2079
+     *   &lt;li>First list entry&lt;/li>
2080
+     *   &lt;li>Second list entry&lt;/li>
2081
+     * &lt;/ul>
2082
+     * </pre>
2083
+     * The following Javascript adds an element to the list:
2084
+     * <pre>
2085
+     * $('#myList').add(EE('li', 'My extra point');
2086
+     * </pre>
2087
+     * This results in
2088
+     * <pre>
2089
+     * &lt;ul id="myList">
2090
+     *   &lt;li>First list entry&lt;/li>
2091
+     *   &lt;li>Second list entry&lt;/li>
2092
+     *   &lt;li>My extra point&lt;/li>
2093
+     * &lt;/ul>
2094
+     * </pre>
2095
+     *
2096
+     * @example Use a list to add several elements at once:
2097
+     * <pre>
2098
+     * $('#comments').add([
2099
+     *      EE('br'),
2100
+     *     'Some text',
2101
+     *     EE('span', {'className': 'highlight'}, 'Some highlighted text')
2102
+     * ]);
2103
+     * </pre>
2104
+     *
2105
+     * @example If you need to customize the content, you can write a factory function:
2106
+     * <pre>
2107
+     * $('.chapter').add(function(parent, index) { return EE('h2', 'Chapter number ' + index); });
2108
+     * </pre>
2109
+     *
2110
+     * @param text a string or number to add as text node
2111
+     * @param node a DOM node to add to the list. If the list has more than one element, the given node will be added to the first element.
2112
+     *             For all additional elements, the node will be cloned using ##clone().
2113
+     * @param list a list containing text and/or nodes. May also contain nested lists with nodes or text..
2114
+     * @param factoryFunction a <code>function(listItem, listIndex)</code> that will be invoked for each list element to create the nodes:
2115
+     * <dl><dt>listItem</dt><dd>The list element that will receive the new children.</dd>
2116
+     * <dt>listIndex</dt><dd>The index of the list element that will receive the new children.</dd>
2117
+     * <dt class="returnValue">(callback return value)<dt><dd>The node(s) to be added to the list element.
2118
+     * Can be either a string for a text node, an HTML element or a list containing strings and/or DOM nodes.
2119
+     * If a function is returned, it will be invoked recursively with the same arguments.</dd></dl>
2120
+     * @return the current list
2121
+     *
2122
+     * @see ##fill() works like <var>add()</var>, but deletes all children before adding the new nodes.
2123
+     * @see ##addFront() adds nodes as first child, not as last.
2124
+     * @see ##addAfter() adds nodes not as children but as siblings.
2125
+     * @see ##addBefore() also adds nodes not as children but as siblings.
2126
+     * @see ##replace() replaces existing nodes.
2127
+     */
2128
+    'add': function (children, addFunction) {
2129
+      return this['each'](function(e, index) {
2130
+        var lastAdded;
2131
+        function appendChildren(c) {
2132
+          if (isList(c))
2133
+            flexiEach(c, appendChildren);
2134
+          else if (isFunction(c))
2135
+            appendChildren(c(e, index));
2136
+          else if (c != _null) {   // must check null, as 0 is a valid parameter
2137
+            var n = isNode(c) ? c : document.createTextNode(c);
2138
+            if (lastAdded)
2139
+              lastAdded['parentNode']['insertBefore'](n, lastAdded['nextSibling']);
2140
+            else if (addFunction)
2141
+              addFunction(n, e, e['parentNode']);
2142
+            else
2143
+              e.appendChild(n);
2144
+            lastAdded = n;
2145
+          }
2146
+        }
2147
+        appendChildren(index &&!isFunction(children) ? clone(children) : children);
2148
+      });
2149
+    },
2150
+
2151
+    /*$
2152
+     * @id on
2153
+     * @group EVENTS
2154
+     * @requires dollar each
2155
+     * @configurable default
2156
+     * @name .on()
2157
+     * @syntax list.on(names, eventHandler)
2158
+     * @syntax list.on(selector, names, eventHandler)
2159
+     * @syntax list.on(names, customFunc, args)
2160
+     * @syntax list.on(selector, names, customFunc, args)
2161
+     * @syntax list.on(names, eventHandler, bubbleSelector)
2162
+     * @syntax list.on(names, customFunc, args, bubbleSelector)
2163
+     * @module WEB
2164
+     * Registers the function as event handler for all items in the list.
2165
+     *
2166
+     * By default, Minified cancels event propagation and disables element's default behavior for all elements that have an event handler.
2167
+     * You can override this, either by prefixing the event name with a '|', or by prefixing them with '?' and returning a <var>true</var>
2168
+     * in the handler. Both will reinstate the original JavaScript behavior.
2169
+     *
2170
+     * Handlers are called with the original event object as first argument, the index of the source element in the
2171
+     * list as second argument and 'this' set to the source element of the event (e.g. the button that has been clicked).
2172
+     *
2173
+     * Instead of the event objects, you can also pass an array of arguments that will be passed instead of event object and index.
2174
+     *
2175
+     * Optionally you can specify two a selector strings to qualify only certain events. The first one is a selector
2176
+     * that allows you to select only specific children of the list elements. This is mostly useful for adding events to DOM trees
2177
+     * generated using ##HTML() or ##EE().
2178
+     *
2179
+     * The second type of selector is the bubble selector that allows you to receive only events that bubbled up from
2180
+     * elements matching the selector. The selector is executed in the context of the element you registered on to identify whether the
2181
+     * original target of the event qualifies. If not, the handler is not called.
2182
+     *
2183
+     * Minified always registers event handlers with event bubbling enabled. Event capture is not supported.
2184
+     *
2185
+     * Event handlers can be unregistered using #off#$.off().
2186
+     *
2187
+     * @example Adds a handler to all divs which paints the div background color to red when clicked.
2188
+     * <pre>
2189
+     * $('div').on('click', function() {
2190
+     *    this.style.backgroundColor = 'red';    // 'this' contains the element that caused the event
2191
+     * });
2192
+     * </pre>
2193
+     *
2194
+     * @example Registers a handler to call a method setStatus('running') using an inline function:
2195
+     * <pre>
2196
+     * $('#myButton').on('click', function() {
2197
+     *    setStatus('running');
2198
+     * });
2199
+     * </pre>
2200
+     * The previous example can bere written like this, using <var>on()</var>'s <var>args</var> parameter:
2201
+     * <pre>
2202
+     * $('#myButton').on('click', setStatus, ['running']);
2203
+     * </pre>
2204
+     *
2205
+     * @example Adds two handlers on an input field. The event names are prefixed with '|' and thus keep their original behavior:
2206
+     * <pre>
2207
+     * $('#myInput').on('|keypress |keydown', function() {
2208
+     *    // do something
2209
+     * });
2210
+     * </pre>
2211
+     *
2212
+     * @example Adds a click handler that will abort the operation by returning false, unless the user confirms it:
2213
+     * <pre>
2214
+     * $('#myLink').on('?click', function() {
2215
+     *    return window.confirm('Really leave?');
2216
+     * });
2217
+     * </pre>
2218
+     *
2219
+     * @example Adds a button and registers a click handler for it using a sub-selector.
2220
+     * <pre>
2221
+     * $('#myForm').add(HTML("&lt;li>&ltbutton>click me&lt/button>&lt/li>").on('button', 'click', myClickHandler));
2222
+     * </pre>
2223
+     *
2224
+     * @example Adds listeners for all clicks on a table's rows using the bubble selector 'tr'.
2225
+     * <pre>
2226
+     * $('#table').on('change', 'tr', function(event, index, selectedIndex) {
2227
+     *    alert("Click on table row number: " + selectedIndex);
2228
+     * }, 'tr');
2229
+     * </pre>
2230
+     * Please note that bubble selectors will even listen to events for
2231
+     * table rows that have been added <strong>after you registered for the events</strong>.
2232
+     *
2233
+     * @param selector optional a selector string for ##dollar#$()## to register the event only on those children of the list elements that
2234
+     *                match the selector.
2235
+     *                Supports all valid parameters for <var>$()</var> except functions.
2236
+     * @param names the space-separated names of the events to register for, e.g. 'click'. Case-sensitive. The 'on' prefix in front of
2237
+     *             the name must not used. You can register the handler for more than one event by specifying several
2238
+     *             space-separated event names. If the name is prefixed
2239
+     *             with '|' (pipe), the event will be passed through and the event's default actions will be executed by the browser.
2240
+     *             If the name is prefixed with '?', the event will only be passed through if the handler returns <var>true</var>.
2241
+     * @param eventHandler the callback <code>function(event, index)</code> to invoke when the event has been triggered:
2242
+     * 		  <dl>
2243
+     *             <dt>event</dt><dd>The original DOM event object.</dd>
2244
+     *             <dt>index</dt><dd>The index of the target object in the ##list#Minified list## .</dd>
2245
+     *             <dt class="this">this</dt><dd>A ##list#Minified list## containing the target element as only item (same as <var>event.target</var>).</dd>
2246
+     *             <dt class="returnValue">(callback return value)</dt><dd>The return value will only be used if the event name prefix was '?'.
2247
+     *             Then, a return value <var>false</var> will stop all further processing of the event and disable event bubbling.
2248
+     *             <var>true</var> will keep the event alive.</dd>
2249
+     *             </dl>
2250
+     * @param customFunc a function to be called instead of a regular event handler with the arguments given in <var>args</var>.
2251
+     *                   'this' will be a ##list#Minified list## containing the target element as only item (same element as <var>event.target</var>).
2252
+     * @param args optional an array of arguments to pass to the custom callback function instead of the event objects. If omitted, the function is
2253
+     *             called as event handler with the event object as argument.
2254
+     * @param bubbleSelector optional a selector string for ##dollar#$()## to receive only events that bubbled up from an
2255
+     *                element that matches this selector.
2256
+     *                Supports all valid parameters for <var>$()</var> except functions. Analog to ##is(),
2257
+     *                the selector is optimized for the simple patterns '.classname', 'tagname' and 'tagname.classname'.
2258
+     * @return the list
2259
+     * @see ##off() allows you to unregister an event handler.
2260
+     * @see ##onClick() as a shortcut for 'click' events.
2261
+     * @see ##onOver() to simplify mouseover/mouseout events.
2262
+     * @see ##onFocus() as convenient way to register for focus events.
2263
+     * @see ##onChange() to get notified when an input's content changes.
2264
+     */
2265
+    'on': on,
2266
+
2267
+    /*$
2268
+     * @id trigger
2269
+     * @group EVENTS
2270
+     * @requires on each
2271
+     * @configurable default
2272
+     * @name .trigger()
2273
+     * @syntax list.trigger(name)
2274
+     * @syntax list.trigger(name, eventObject)
2275
+     * @module WEB
2276
+     *
2277
+     * Triggers event handlers registered with ##on().
2278
+     * Any event that has been previously registered using ##on() can be invoked with <var>trigger()</var>. Please note that
2279
+     * it will not simulate the default behavior on the elements, such as a form submit when you click on a submit button. Event bubbling
2280
+     * is supported, thus unless there's an event handler that cancels the event, the event will be triggered on all parent elements.
2281
+     *
2282
+     *
2283
+     * @example Simulates a 'click' event on the button.
2284
+     * <pre>
2285
+     * $('#myButton').trigger('click');
2286
+     * </pre>
2287
+     *
2288
+     * @param name a single event name to trigger
2289
+     * @param eventObj optional an object to pass to the event handler, provided the handler does not have custom arguments.
2290
+     *                 Anything you pass here will be directly given to event handlers as event object, so you need to know what
2291
+     *                 they expect.
2292
+     * @return the list
2293
+     * @see ##on() registers events that can be triggered.
2294
+     */
2295
+    'trigger': function (eventName, eventObj) {
2296
+      return this['each'](function(element, index) {
2297
+        var bubbleOn = true, el = element;
2298
+        while(el && bubbleOn) {
2299
+          eachObj(el['M'], function(id, f) {
2300
+            bubbleOn = bubbleOn && f(eventName, eventObj, element);
2301
+          });
2302
+          el = el['parentNode'];
2303
+        }
2304
+      });
2305
+    }
2306
+
2307
+    /*$
2308
+     * @stop
2309
+     */
2310
+    // @cond !trigger dummyTrigger:0
2311
+    ,
2312
+    ///#/snippet webListFuncs
2313
+    ///#snippet extrasListFuncs
2314
+
2315
+    /*$
2316
+     * @id ht
2317
+     * @group ELEMENT
2318
+     * @requires set template
2319
+     * @configurable default
2320
+     * @name .ht()
2321
+     * @syntax list.ht(templateString, object...)
2322
+     * @syntax list.ht(templateFunction, object...)
2323
+     * @syntax list.ht(idSelector, object...)
2324
+     * @module WEB+UTIL
2325
+     * Replaces the content of the list elements with the HTML generated using the given template. The template uses
2326
+     * ##template() syntax and HTML-escaped its output using ##escapeHtml().
2327
+     *
2328
+     * @example When you have a HTML snippet like this:
2329
+     * <pre>
2330
+     * &lt;div id="price">&lt;/div>
2331
+     * </pre>
2332
+     * Then you can format the price value like this:
2333
+     * <pre>
2334
+     * var price = 14.9;
2335
+     * $('#price').ht('&lt;b>${{::0.00}}&lt;/b>', price);
2336
+     * </pre>
2337
+     * Results in:
2338
+     * <pre>
2339
+     * &lt;div id="price">&lt;b>$14.90&lt;/b>&lt;/div>
2340
+     * </pre>
2341
+     *
2342
+     * @example Render a list of names:
2343
+     * <pre>
2344
+     * var names = [ {first: 'James', last: 'Sullivan'},
2345
+     *               {first: 'Michael', last: 'Wazowski'} ];
2346
+     * $('#list').ht('&lt;h2>{{listName}}&lt;/h2>'+
2347
+     *               '&lt;ul>{{each n: names}}&lt;li>{{n.first}} {{n.last}}&lt;/li>{{/each}}&lt;/ul>',
2348
+     *               {listName: 'Guys', names: names});
2349
+     * </pre>
2350
+     * The code creates this:
2351
+     * <pre>
2352
+     * &lt;h2>Guys&lt;/h2>
2353
+     * &lt;ul>&lt;li>James Sullivan&lt;li>&lt;li>Michael Wazowski&lt;/li>&lt;/ul>
2354
+     * </pre>
2355
+     *
2356
+     * @example You can store templates in &lt;script&gt; tags. First you need to create a &lt;script&gt; tag with a type not
2357
+     *          supported by the browser and put your template in there, like this:
2358
+     * <pre>&lt;script id="myTimeTpl" type="minified-template"&gt;The time is {{HH:mm:ss}}.&lt;/script&gt;</pre>
2359
+     * Then you can specify the tag's id directly to access it:
2360
+     * <pre>$('#timeDisplay').ht('#myTimeTpl', new Date());</pre>
2361
+     *
2362
+     * @param templateString the template using ##template() syntax. Please note, because this is a template, you should
2363
+     *                     avoid creating the template itself dynamically, as compiling templates is expensive and
2364
+     *                     Minified will cache only a limited number of templates. Exception: If the template string does not use
2365
+     *                     any template functionality (no {{}}), it does not need to be compiled and won't be cached.<br/>
2366
+     *                     The template will use ##escapeHtml() as escape function, so all template substitutions will be HTML-escaped,
2367
+     *                     unless you use triple curly-braces.
2368
+     * @param templateFunction instead of a HTML template, <var>ht()</var> can also use a template function, e.g. one
2369
+     *                         created by ##template(). It will be invoked with the object as only argument.
2370
+     * @param idSelector if you pass an ID CSS selector in the form "#myScript", Minified will recognize this and use the content
2371
+     *                   of the specified &lt;script> element as template. This allows you to put your template into
2372
+     *                   a &lt;script&gt; tag with a non-JavaScript type (see example). Any string that starts with '#' and does not
2373
+     *                   contain any spaces is used as selector.
2374
+     * @param object optional one or more objects to pass to the template. If object is not set, the template is called with <var>undefined</var>
2375
+     *                        as object. If exactly one object is given, it is passed directly to the template. If you specify more than one
2376
+     *                        object, they are ##merge#merged##.
2377
+     * @return the current list
2378
+     *
2379
+     * @see ##HTML() creates only the nodes and can be used with ##add() and other methods to add the nodes to the DOM, giving you more flexibility than <var>ht()</var>.
2380
+     */
2381
+    'ht': function(htmlTemplate, object) {
2382
+      var o = arguments.length > 2 ? merge(sub(arguments, 1)) : object;
2383
+      return this['set']('innerHTML', isFunction(htmlTemplate) ? htmlTemplate(o) :
2384
+        /{{/.test(htmlTemplate) ? formatHtml(htmlTemplate, o) :
2385
+          /^#\S+$/.test(htmlTemplate) ? formatHtml($$(htmlTemplate)['text'], o) : htmlTemplate);
2386
+    }
2387
+    /*$
2388
+     * @stop
2389
+     */
2390
+    // @cond !ht dummyHt:0
2391
+    ///#/snippet extrasListFuncs
2392
+  }, M.prototype);
2393
+
2394
+  //// DOLLAR FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2395
+  copyObj({
2396
+    ///#snippet webDollarFuncs
2397
+    /*$
2398
+     * @id request
2399
+     * @group REQUEST
2400
+     * @requires
2401
+     * @configurable default
2402
+     * @name $.request()
2403
+     * @syntax $.request(method, url)
2404
+     * @syntax $.request(method, url, data)
2405
+     * @syntax $.request(method, url, data, settings)
2406
+     * @module WEB
2407
+     * Initiates a HTTP request to the given URL, using XMLHttpRequest. It returns a ##promiseClass#Promise## object that allows you to obtain the result.
2408
+     *
2409
+     * @example Invokes a REST web service and parses the resulting document using JSON:
2410
+     * <pre>
2411
+     * $.request('get', 'http://service.example.com/weather', {zipcode: 90210})
2412
+     *    .then(function(txt) {
2413
+     *         var json = $.parseJSON(txt);
2414
+     *         $('#weatherResult').fill('Today's forecast is is: ' + json.today.forecast);
2415
+     *    })
2416
+     *    .error(function(status, statusText, responseText) {
2417
+     *         $('#weatherResult').fill('The weather service was not available.');
2418
+     *    });
2419
+     * </pre>
2420
+     *
2421
+     * @example Sending a JSON object to a REST web service:
2422
+     * <pre>
2423
+     * var myRequest = {         // create a request object that can be serialized via JSON
2424
+     *      request: 'register',
2425
+     *      entries: [
2426
+     *        {name: 'Joe',
2427
+     *      	    job: 'Plumber'
2428
+     *        }
2429
+     *      ]};
2430
+     *
2431
+     * function failureHandler() {
2432
+     *   $('#registrationResult').fill('Registration failed');
2433
+     * }
2434
+     *
2435
+     * $.request('post', 'http://service.example.com/directory', $.toJSON(myRequest))
2436
+     *     .then(function(txt) {
2437
+     *        if (txt == 'OK')
2438
+     *             $('#registrationResult').fill('Registration succeeded');
2439
+     *        else
2440
+     *              failureHandler();
2441
+     *        })
2442
+     *     .error(failureHandler);
2443
+     * </pre>
2444
+     *
2445
+     * @example Using HTTP authentication and a custom XMLHttpRequest property.
2446
+     * <pre>var handler = $.request('get', 'http://service.example.com/userinfo', null, {xhr: {withCredentials: true}, user: 'me', pass: 'secret'});</pre>
2447
+     *
2448
+     *
2449
+     * @param method the HTTP method, e.g. 'get', 'post' or 'head' (rule of thumb: use 'post' for requests that change data
2450
+     *             on the server, and 'get' to request data). Not case sensitive.
2451
+     * @param url the server URL to request. May be a relative URL (relative to the document) or an absolute URL. Note that unless you do something
2452
+     *             fancy on the server (keyword to google:  Access-Control-Allow-Origin), you can only call URLs on the server your script originates from.
2453
+     * @param data optional data to send in the request, either as POST body or as URL parameters. It can be either a plain object as map of
2454
+     *             parameters (for all HTTP methods), a string (for all HTTP methods), a DOM document ('post' only) or a FormData object ('post' only).
2455
+     *             If the method is 'post', it will be sent as body, otherwise parameters are appended to the URL. In order to send several parameters with the
2456
+     *             same name, use an array of values in the map. Use null as value for a parameter without value.
2457
+     * @param settings optional a map of additional parameters. Supports the following properties (all optional):
2458
+     * <dl><dt>headers</dt><dd>a map of HTTP headers to add to the request. Note that you should use the proper capitalization for the
2459
+     *                header 'Content-Type', if you set it, because otherwise it may be overwritten.</dd>
2460
+     * <dt>xhr</dt><dd>a map of properties to set in the XMLHttpRequest object before the request is sent, for example <code>{withCredentials: true}</code>.</dd>
2461
+     * <dt>user</dt><dd>username for HTTP authentication, together with the <var>pass</var> parameter</dd>
2462
+     * <dt>pass</dt><dd>password for HTTP authentication, together with the <var>user</var> parameter</dd>
2463
+     * </dl>
2464
+     * @return a ##promiseClass#Promise## containing the request's status. If the request has successfully completed with a HTTP status 2xx,
2465
+     *         the promise's completion handler will be called as <code>function(text, xhr)</code>:
2466
+     *         <dl><dt>text</dt><dd>The response sent by the server as text.</dd>
2467
+     *         <dt>xhr</dt><dd>The XMLHttpRequest used for the request. This allows you to retrieve the response in different
2468
+     *         formats (e.g. <var>responseXml</var> for an XML document</var>), to retrieve headers and more.</dd></dl>
2469
+     *         The failure handler will be called as <code>function(statusCode, statusText, text)</code>:
2470
+     *         <dl><dt>statusCode</dt><dd>The HTTP status (never 200; 0 if no HTTP request took place).</dd>
2471
+     *         <dt>text</dt><dd>The response's body text, if there was any, or the exception as string if the browser threw one.</dd>
2472
+     *         <dt>xhr</dt><dd>The XMLHttpRequest used for the request. This allows you to retrieve the response in different
2473
+     *         formats (e.g. <var>responseXml</var> for an XML document</var>), to retrieve headers and more..</dd></dl>
2474
+     *         The returned promise supports ##stop(). Calling <var>stop()</var> will invoke the XHR's <var>abort()</var> method.
2475
+     *         The underlying XmlHttpRequest can also be obtained from the promise's <var>xhr</var> property.
2476
+     *
2477
+     * @see ##values() serializes an HTML form in a format ready to be sent by <var>$.request</var>.
2478
+     * @see ##$.parseJSON() can be used to parse JSON responses.
2479
+     * @see ##$.toJSON() can create JSON messages.
2480
+     * @see ##_.format() can be useful for creating REST-like URLs, if you use JavaScript's built-in <var>escape()</var> function.
2481
+     */
2482
+    'request': function (method, url, data, settings0) {
2483
+      var settings = settings0 || {};
2484
+      var xhr, callbackCalled = 0, prom = promise(), dataIsMap = data && (data['constructor'] == settings['constructor']);
2485
+      try {
2486
+        prom['xhr'] = xhr = new XMLHttpRequest();
2487
+
2488
+        prom['stop0'] = function() { xhr['abort'](); };
2489
+        // @condend
2490
+
2491
+        if (dataIsMap) { // if data is parameter map...
2492
+          data = collector(eachObj, data, function processParam(paramName, paramValue) {
2493
+            return collector(flexiEach, paramValue, function(v) {
2494
+              return encodeURIComponent(paramName) + ((v != _null) ?  '=' + encodeURIComponent(v) : '');
2495
+            });
2496
+          }).join('&');
2497
+        }
2498
+
2499
+        if (data != _null && !/post/i.test(method)) {
2500
+          url += '?' + data;
2501
+          data = _null;
2502
+        }
2503
+
2504
+        xhr['open'](method, url, true, settings['user'], settings['pass']);
2505
+        if (dataIsMap && /post/i.test(method))
2506
+          xhr['setRequestHeader']('Content-Type', 'application/x-www-form-urlencoded');
2507
+
2508
+        eachObj(settings['headers'], function(hdrName, hdrValue) {
2509
+          xhr['setRequestHeader'](hdrName, hdrValue);
2510
+        });
2511
+        eachObj(settings['xhr'], function(name, value) {
2512
+          xhr[name] = value;
2513
+        });
2514
+
2515
+        xhr['onreadystatechange'] = function() {
2516
+          if (xhr['readyState'] == 4 && !callbackCalled++) {
2517
+            if (xhr['status'] >= 200 && xhr['status'] < 300)
2518
+              prom['fire'](true, [xhr['responseText'], xhr]);
2519
+            else
2520
+              prom['fire'](false, [xhr['status'], xhr['responseText'], xhr]);
2521
+          }
2522
+        };
2523
+
2524
+        xhr['send'](data);
2525
+      }
2526
+      catch (e) {
2527
+        if (!callbackCalled)
2528
+          prom['fire'](false, [0, _null, toString(e)]);
2529
+      }
2530
+
2531
+      return prom;
2532
+    },
2533
+
2534
+    /*
2535
+     * JSON Module. Uses browser built-ins or json.org implementation if available. Otherwise its own implementation,
2536
+     * originally based on public domain implementation http://www.JSON.org/json2.js / http://www.JSON.org/js.html.
2537
+     * Extremely simplified code, made variables local, removed all side-effects (especially new properties for String, Date and Number).
2538
+     */
2539
+
2540
+    /*$
2541
+     * @id ready
2542
+     * @group EVENTS
2543
+     * @requires ready_vars ready_init
2544
+     * @configurable default
2545
+     * @name $.ready()
2546
+     * @syntax $.ready(handler)
2547
+     * @module WEB
2548
+     * Registers a handler to be called as soon as the HTML has been fully loaded in the browser. Does not necessarily wait for images and other elements,
2549
+     * only the main HTML document needs to be complete. On older browsers it is the same as <var>window.onload</var>.
2550
+     *
2551
+     * If you call <var>ready()</var> after the page is completed, the handler is scheduled for invocation in the event loop as soon as possible.
2552
+     *
2553
+     * A shortcut for <var>ready()</var> is to call ##dollar#$()## with the handler function. It does the same with fewer characters.
2554
+     *
2555
+     * @example Registers a handler that sets some text in an element:
2556
+     * <pre>
2557
+     * $.ready(function() {
2558
+     *   $('#someElement').fill('ready() called');
2559
+     * });
2560
+     * </pre>
2561
+     *
2562
+     * @param handler the <code>function()</code> to be called when the HTML is ready.
2563
+     * @see ##dollar#$()## calls <var>ready()</var> when invoked with a function, offering a more convenient syntax.
2564
+     */
2565
+    'ready': ready,
2566
+
2567
+    /*$
2568
+     * @id off
2569
+     * @group EVENTS
2570
+     * @requires on
2571
+     * @configurable default
2572
+     * @name $.off()
2573
+     * @syntax $.off(handler)
2574
+     * @module WEB
2575
+     * Removes the given event handler. The call will be ignored if the given handler has not been registered using ##on().
2576
+     * If the handler has been registered for more than one element or event, it will be removed from all instances.
2577
+     *
2578
+     * Please note that you can not unregister event handlers registered using ##onOver() or ##onChange().
2579
+     *
2580
+     * @example Adds a handler to an element:
2581
+     * <pre>
2582
+     * function myEventHandler() {
2583
+     *    this.style.backgroundColor = 'red';        // 'this' contains the element that caused the event
2584
+     * }
2585
+     * $('#myElement').on('click', myEventHandler);  // add event handler
2586
+     *
2587
+     * window.setInterval(function() {               // after 5s, remove event handler
2588
+     *    $.off(myEventHandler);
2589
+     * }, 5000);
2590
+     * </pre>
2591
+     *
2592
+     * @param handler the handler to unregister, as given to ##on(). It must be a handler that has previously been registered using ##on().
2593
+     *                If the handler is not registered as event handler, the function does nothing.
2594
+     *
2595
+     * @see ##on() registers an event handler.
2596
+     */
2597
+    'off': off
2598
+
2599
+    /*$
2600
+     * @stop
2601
+     */
2602
+    // @cond !off dummyOff:null
2603
+    ,
2604
+    ///#/snippet webDollarFuncs
2605
+    ///#snippet extrasDollarFuncs
2606
+
2607
+    /*$
2608
+     * @id wait
2609
+     * @group EVENTS
2610
+     * @configurable default
2611
+     * @requires promise
2612
+     * @name $.wait()
2613
+     * @syntax $.wait()
2614
+     * @syntax $.wait(durationMs)
2615
+     * @syntax $.wait(durationMs, args)
2616
+     * @module WEB+UTIL
2617
+     *
2618
+     * Creates a new  ##promise#Promise## that will be fulfilled as soon as the specified number of milliseconds have passed. This is mainly useful for animation,
2619
+     * because it allows you to chain delays into your animation chain.
2620
+     *
2621
+     * The operation can be interrupted by calling the promise's ##stop() function.
2622
+     *
2623
+     * @example Chained animation using Promise callbacks. The element is first moved to the position 200/0, then to 200/200, waits for 50ms
2624
+     *          and finally moves to 100/100.
2625
+     * <pre>
2626
+     * var div = $('#myMovingDiv').set({$left: '0px', $top: '0px'});
2627
+     * div.animate({$left: '200px', $top: '0px'}, 600, 0)
2628
+     *    .then(function() {
2629
+     *           div.animate({$left: '200px', $top: '200px'}, 800, 0);
2630
+     *    }).then(function() {
2631
+     *    	     return _.wait(50);
2632
+     *    }).then(function() {
2633
+     *           div.animate({$left: '100px', $top: '100px'}, 400);
2634
+     *    });
2635
+     * });
2636
+     * </pre>
2637
+     *
2638
+     *
2639
+     * @param durationMs optional the number of milliseconds to wait. If omitted, the promise will be fulfilled as soon as the browser can run it
2640
+     *                   from the event loop.
2641
+     * @param args optional an array or list of arguments to pass to the promise handler
2642
+     * @return a ##promise#Promise## object that will be fulfilled when the time is over, or fail when the promise's ##stop() has been called.
2643
+     *         The promise argument of a fulfilled promise is the <var>args</var> parameter as given to <var>wait()</var>. The returned promise supports ##stop()
2644
+     *         to interrupt the promise.
2645
+     */
2646
+    'wait': function(durationMs, args) {
2647
+      var p = promise();
2648
+      var id = setTimeout(function() {
2649
+        p['fire'](true, args);
2650
+      }, durationMs);
2651
+      p['stop0'] = function() { p['fire'](false); clearTimeout(id); };
2652
+      return p;
2653
+    }
2654
+
2655
+    /*$
2656
+     * @stop
2657
+     */
2658
+    // @cond !wait dummyWait:0
2659
+
2660
+    ///#/snippet extrasDollarFuncs
2661
+  }, $);
2662
+
2663
+  //// UNDERSCORE FUNCTIONS ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2664
+
2665
+  copyObj({
2666
+    ///#snippet utilUnderscoreFuncs
2667
+    // @condblock each
2668
+    'each': each,
2669
+    // @condend
2670
+    // @condblock each
2671
+    'toObject': toObject,
2672
+    // @condend
2673
+    // @condblock find
2674
+    'find': find,
2675
+    // @condend
2676
+    // @condblock equals
2677
+    'equals': equals,
2678
+    // @condend
2679
+
2680
+    /*$
2681
+     * @id copyobj
2682
+     * @group OBJECT
2683
+     * @requires
2684
+     * @configurable default
2685
+     * @name _.copyObj()
2686
+     * @syntax _.copyObj(from)
2687
+     * @syntax _.copyObj(from, to)
2688
+     * @module UTIL
2689
+     * Copies every property of the first object into the second object. The properties are copied as shallow-copies.
2690
+     *
2691
+     *  @example Copying properties:
2692
+     * <pre>var target = {a:3, c: 3};
2693
+     * _.copyObj({a: 1, b: 2}, target); // target is now {a: 1, b: 2, c: 3}</pre>
2694
+     *
2695
+     *  @example Inline property merge:
2696
+     * <pre>var target = _.copyObj({a: 1, b: 2}, {a:3, c: 3}); // target is now {a: 1, b: 2, c: 3}</pre>
2697
+     *
2698
+     *  @example Duplicating an object:
2699
+     * <pre>var target = _.copyObj({a: 1, b: 2}); // target is now {a: 1, b: 2}</pre>
2700
+     *
2701
+     * @param from the object to copy from
2702
+     * @param to optional the object to copy to. If not given, a new object will be created.
2703
+     * @return the object that has been copied to
2704
+     *
2705
+     * @see ##_.extend() is very similar to <var>copyObj()</var>, but with a slightly different syntax.
2706
+     * @see ##_.merge() copies a list of objects into a new object.
2707
+     */
2708
+    'copyObj': copyObj,
2709
+
2710
+    /*$
2711
+     * @id extend
2712
+     * @group OBJECT
2713
+     * @requires
2714
+     * @configurable default
2715
+     * @name _.extend()
2716
+     * @syntax _.extend(target, src...)
2717
+     * @module UTIL
2718
+     * Copies every property of the source objects into the first object. The source objects are specified using variable arguments.
2719
+     * There can be more than one.
2720
+     * The properties are copied as shallow-copies.
2721
+     *
2722
+     * <b>Please note:</b> Unlike jQuery, <var>extend</var> does not directly add a function to extend Minified, although
2723
+     * you can use it to for this. To add a function to ##list#Minified lists##, add a property to
2724
+     * ##M#MINI.M##. If you want to extend <var>$</var> or <var>_</var>, just assign the new function(s) as property.
2725
+     *
2726
+     *  @example Copying properties:
2727
+     * <pre>var target = {a:3, c: 3};
2728
+     * _.extend(target, {a: 1, b: 2}); // target is now {a: 1, b: 2, c: 3}</pre>
2729
+     *
2730
+     *  @example Using several source values:
2731
+     * <pre>var extend = _.extend({a: 1, b: 2}, {a:3, c: 3}, {d: 5}); // target is now {a: 1, b: 2, c: 3, d: 5}</pre>
2732
+     *
2733
+     * @param target the object to copy to
2734
+     * @param src the object(s) to copy from. Variable argument, there can be any number of sources. Nulls and <var>undefined</var>
2735
+     *            parameters will be ignored.
2736
+     * @return the target
2737
+     *
2738
+     * @see ##_.copyObj() is very similar to <var>extend()</var>, but with a slightly different and more straightforward syntax.
2739
+     * @see ##_.merge() copies a list of objects into a new object.
2740
+     */
2741
+    'extend': function(target) {
2742
+      return merge(sub(arguments, 1), target);
2743
+    },
2744
+
2745
+    /*$
2746
+     * @id eachobj
2747
+     * @group OBJECT
2748
+     * @requires
2749
+     * @configurable default
2750
+     * @name _.eachObj()
2751
+     * @syntax _.eachObj(obj, callback)
2752
+     * @syntax _.eachObj(obj, callback, ctx)
2753
+     * @module UTIL
2754
+     * Invokes the given function once for each property of the given object. The callback is not invoked for inherited properties.
2755
+     *
2756
+     * @example Dumps all properties of an object.
2757
+     * <pre>
2758
+     * var s = '';
2759
+     * _.eachObj({a: 1, b: 5, c: 2}, function(key, value) {
2760
+     *     s += 'key=' + key + ' value=' + value + '\n';
2761
+     * });
2762
+     * </pre>
2763
+     *
2764
+     * @param obj the object to use
2765
+     * @param callback The callback <code>function(key, value)</code> to invoke for each property.
2766
+     *                 <dl><dt>key</dt><dd>The name of the current property.</dd>
2767
+     *                 <dt>value</dt><dd>The value of the current property.</dd>
2768
+     *                 <dt class="this">this</dt><dd>The given context. If not set, the object itself.</dd>
2769
+     *                 The callback's return value will be ignored.
2770
+     * @param ctx optional a context to pass to the callback as 'this'.
2771
+     * @return the object
2772
+     *
2773
+     * @see ##_.each() iterates through a list.
2774
+     */
2775
+    'eachObj': eachObj,
2776
+
2777
+    /*$
2778
+     * @id isobject
2779
+     * @group TYPE
2780
+     * @requires
2781
+     * @configurable default
2782
+     * @name _.isObject()
2783
+     * @syntax _.isObject(obj)
2784
+     * @module UTIL
2785
+     * Checks whether the given reference is an object as defined by <var>typeof</var>.
2786
+     *
2787
+     * @param obj the object to test
2788
+     * @return <var>true</var> if the object is an object, <var>false</var> otherwise.
2789
+     */
2790
+    'isObject': isObject,
2791
+
2792
+    /*$
2793
+     * @id format
2794
+     * @group FORMAT
2795
+     * @requires template
2796
+     * @configurable default
2797
+     * @name _.format()
2798
+     * @syntax _.format()
2799
+     * @syntax _.format(template, object)
2800
+     * @syntax _.format(template, object, escapeFunction)
2801
+     * @module UTIL
2802
+     * Formats an object using a ##template#template##. The template syntax is shared with ##_.template(). The only difference is that
2803
+     * <var>format()</var> frees you from the extra step of creating the template. In any case, whether you use
2804
+     * <var>format()</var> or ##_.template(), the template will be cached. Be careful when you create templates dynamically, as
2805
+     * every template is cached and consumes memory.<br/>
2806
+     * If you only want to format a single value, use ##_.formatValue().
2807
+     *
2808
+     * @example Format a name:
2809
+     * <pre>var s = _.formatHtml("{{first}} {{last}}", {first: 'Tim', last: 'Taylor'});</pre>
2810
+     *
2811
+     * @example Format a list of dates:
2812
+     * <pre>var s = _.format("{{each}}{{this :: yyyy-MM-dd}}{{/each}}", dateList);</pre>
2813
+     *
2814
+     * @param template The ##template#template## as a string. The template, once created, will be cached.
2815
+     * @param object the object to format
2816
+     * @param escapeFunction optional The callback <code>function(inputString)</code> that will be used
2817
+     *        to escape all output:
2818
+     * <dl><dt>inputString</dt><dd>The string to escape.</dd>
2819
+     *     <dt class="returnValue">(callback return value)</dt><dd>The escaped string.</dd></dl>
2820
+     *        If no escapeFunction has been given, the output will not be escaped.
2821
+     *        ##_.escapeHtml() can be used as an escape function for HTML, and ##_.escapeRegExp() for regular expressions.
2822
+     *        JavaScript's built-in <var>escape()</var> function can escape URL components.
2823
+     *        See ##_.htmlFormat() for a version of <var>format()</var> that already includes HTML escaping.
2824
+     * @return the string created by the template
2825
+     *
2826
+     * @see ##_.template() creates a template function, using the same syntax.
2827
+     * @see ##_.formatHtml() is a variant of <var>format()</var> with HTML-escpaping built it.
2828
+     * @see ##_.formatValue() formats a single number or date.
2829
+     * @see ##_.escapeRegExp() can be used by <var>format()</var> to escape regular expressions.
2830
+     */
2831
+    'format': function(tpl, object, escapeFunction) {
2832
+      return template(tpl, escapeFunction)(object);
2833
+    },
2834
+
2835
+    /*$
2836
+     * @id template
2837
+     * @group FORMAT
2838
+     * @requires date_constants
2839
+     * @configurable default
2840
+     * @name _.template()
2841
+     * @syntax _.template(template)
2842
+     * @syntax _.template(template, escapeFunction)
2843
+     * @module UTIL
2844
+     * Parses a Handlebars-like template to create a reusable template function.
2845
+     *
2846
+     * The syntax of the template uses a syntax that superficially looks like
2847
+     * <a href="http://handlebarsjs.com/">Handlebars</a>. Unlike Handlebars, it is based on raw JavaScript expressions and thus gives you
2848
+     * complete freedom, but also offers you shortcuts for formatting, iteration and conditionals.
2849
+     *
2850
+     * Every template can receive exactly one object as input. If you need more than one value as input, put all required values
2851
+     * into an object.
2852
+     *
2853
+     * Use double curly braces to embed a JavaScript expression and insert its result:
2854
+     * <pre>{{a}} plus {{b}} is {{a+b}}</pre>
2855
+     *
2856
+     * To use such a template, create it with <var>template()</var> and then execute the resulting function:
2857
+     * <pre>var myTemplate = _.template('{{a}} plus {{b}} is {{a+b}}');
2858
+     * var result = myTemplate({a: 5, b: 7});</pre>
2859
+     * If you pass an object as input, its properties will be mapped using JavaScript's <code>with</code>
2860
+     * statement and are available as variables throughout the template.
2861
+     *
2862
+     * If you have only a simple value to render, you can pass it directly and access it through the pre-defined
2863
+     * variable <var>obj</var>:
2864
+     * <pre>var myTemplate = _.template('The result is {{obj}}.');
2865
+     * var result = myTemplate(17);</pre>
2866
+     * Alternatively, you could also access the input as <var>this</var>, but be aware that JavaScript wraps simples types
2867
+     * such as Number and Boolean. <var>this</var> is the default, so you can omit it to get the same result:
2868
+     * <pre>var myTemplate = _.template('The result is {{ }}.');
2869
+     * var result = myTemplate(17);</pre>
2870
+     *
2871
+     * Minified templates can use ##_.formatValue() formats directly. Just separate them from the expression by
2872
+     * a double-colon:
2873
+     * <pre>The price is {{obj::#.00}}.</pre>
2874
+     *
2875
+     * Conditions can be expressed using <code>if</code> and <code>else</code>:
2876
+     * <pre>Hello {{if visits==0}}New{{else if visits&lt;10}}Returning{{else}}Regular{{/if}} Customer.</pre>
2877
+     * You can use any JavaScript expression as condition.
2878
+     *
2879
+     * Use <code>each</code> to iterate through a list:
2880
+     * <pre>var myTemplate = _.template(
2881
+     * 	   '{{each names}}{{this.firstName}} {{this.lastName}}{{/each}}');
2882
+     * var result = myTemplate({names: [{firstName: 'Joe', lastName: 'Jones'},
2883
+     *                                  {firstName: 'Marc', lastName: 'Meyer'}]});</pre>
2884
+     * <code>each</code> will iterate through the members of the given object. It
2885
+     * calls its body for each item and put a reference to the item into <var>this</var>.
2886
+     * Optionally, you can specify up to two variables to store the value in and
2887
+     * the zero-based index of the current item:
2888
+     * <pre>var myTemplate = _.template(
2889
+     * 	   '{{each value, index: names}}{{index}}. {{value.firstName}} {{value.lastName}}{{/each}}');
2890
+     * </pre>
2891
+     *
2892
+     * If you do not pass an expression to <code>each</code>, it will take the list from <var>this</var>:
2893
+     * <pre>var myTemplate = _.template('{{each value:}}{{value}};{{/each}}');
2894
+     * var result = myTemplate([1, 2, 3]);</pre>
2895
+     *
2896
+     * Beside lists, you can also iterate through the properties of an object. The property name will be stored
2897
+     * in the first given parameter and the value in <var>this</var> and the second parameter:
2898
+     * <pre>var myTemplate = _.template('{{each key, value: nicknames}}{{key}}: {{value}}{{/each}}');
2899
+     * var result = myTemplate({nicknames: {Matt: 'Matthew', John: 'Jonathan'} });</pre>
2900
+     *
2901
+     * Shorter version of the previous example that uses <var>this</var> for the value:
2902
+     * <pre>var myTemplate = _.template('{{each key: nicknames}}{{key}}: {{this}}{{/each}}');</pre>
2903
+     *
2904
+     * If you do not need the key, you can omit the variable specification:
2905
+     * <pre>var myTemplate = _.template('{{each nicknames}}{{this}}{{/each}}');</pre>
2906
+     *
2907
+     * You can define your own variables, using the regular JavaScript syntax, with 'var':
2908
+     * <pre>var myTemplate = _.template('{{var s=very.long.name, sum=a+b;}}{{s.desc}}, {{sum}}');</pre>
2909
+     *
2910
+     * In some situations, it may be inevitable to embed raw JavaScript in the template.
2911
+     * To embed JavaScript code, prefix the code with a '#':
2912
+     * <pre>var myTemplate = _.template(
2913
+     *     '{{each}}{{#var sum = 0; for (var i = 0; i &lt; 3; i++) sum += this.numbers[i]; }}{{sum}}{{/each}}');
2914
+     * var result = myTemplate([['Foreword', 'Intro'], ['Something', 'Something else']]);</pre>
2915
+     *
2916
+     *
2917
+     * By default, all output will be escaped. You can prevent this by using triple-curly-braces:
2918
+     * <pre>Here's the original: {{{rawText}}}</pre>.
2919
+     *
2920
+     * The template's JavaScript code is executed in a sandbox without access to global variables. Minified defines the
2921
+     * following variables for you:
2922
+     * <table>
2923
+     * <tr><th>Name</th><th>Desciption</th></tr>
2924
+     * <tr><td>this</td><td>The template object outside of <code>each</code>. Inside <code>each</code>s, the current value.</td></tr>
2925
+     * <tr><td>obj</td><td>The parameter given to the template function.</td></tr>
2926
+     * <tr><td>_</td><td>A reference to Minified Util.</td></tr>
2927
+     * <tr><td>esc</td><td>The escape function given when the template has been defined. If no function has been given,
2928
+     *                     a default function that returns the input unmodified.</td></tr>
2929
+     * <tr><td>print</td><td>A <code>function(text,...)</code> that appends one or more strings to the template result.</td></tr>
2930
+     * <tr><td>each</td><td>A <code>function(listOrObject, eachCallback)</code> that can iterate over lists or object properties.
2931
+     * The <var>eachCallback</var> is a <code>function(key, value)</code> for objects or <code>function(value, index)</code>
2932
+     * for arrays that will be invoked for each item.
2933
+     * </table>
2934
+     *
2935
+     * Every template you create is already cached, so it not an expensive operation to call ##_.template() a second
2936
+     * time with the same template. However, because of caching, you should be careful when creating templates
2937
+     * dynamically, as this will fill the cache up quickly.
2938
+     *
2939
+     * @param template The template as a string using the syntax described below.
2940
+     * @param escapeFunction optional The callback <code>function(inputString)</code> that will be used
2941
+     *        to escape all output:
2942
+     * <dl><dt>inputString</dt><dd>The string to escape.</dd>
2943
+     *     <dt class="returnValue">(callback return value)</dt><dd>The escaped string.</dd></dl>
2944
+     *        If no escapeFunction has been given, the output will not be escaped.
2945
+     *        ##_.escapeHtml() can be used as an escape function for HTML, and ##_.escapeRegExp() for regular expressions.
2946
+     *        JavaScript's built-in <var>escape()</var> function can escape URL components.
2947
+     * @return the value returned by the last invocation of <var>func</var>
2948
+     *
2949
+     * @see ##_.format() shares <var>template()</var>'s syntax but returns the result directly.
2950
+     * @see ##_.formatHtml() is a variant of <var>format()</var> with HTML escaping.
2951
+     * @see ##_.escapeHtml() can be used by <var>template()</var> to escape HTML.
2952
+     * @see ##_.escapeRegExp() can be used by <var>template()</var> to escape regular expressions.
2953
+     * @see ##HTML() creates a HTML element tree from a template.
2954
+     */
2955
+    'template': template,
2956
+
2957
+    /*$
2958
+     * @id formathtml
2959
+     * @group FORMAT
2960
+     * @requires template
2961
+     * @configurable default
2962
+     * @name _.formatHtml()
2963
+     * @syntax _.formatHtml()
2964
+     * @syntax _.formatHtml(template, object)
2965
+     * @module UTIL
2966
+     * Formats an object using a ##template#template## with HTML escaping for the output.
2967
+     * The template syntax is shared with ##_.template(). Output in double curly braces is automatically escaped using ##_.escapeHtml().
2968
+     * <var>formatHtml()</var> just creates a new template with HTML escaping and invokes it immediately.
2969
+     * The template will be cached. Be careful when you create templates dynamically, as
2970
+     * every template is cached and consumes memory.<br/>
2971
+     * If you only want to format a single value, use ##_.formatValue().
2972
+     *
2973
+     * @example Format a name:
2974
+     * <pre>var s = _.formatHtml("{{first}} {{last}}", {first: 'Tim', last: 'Taylor'});</pre>
2975
+     *
2976
+     * @example Format a list of dates:
2977
+     * <pre>var s = _.formatHtml("{{each}}{{::yyyy-MM-dd}}{{/each}}", dateList);</pre>
2978
+     *
2979
+     * @param template The ##template#template## as a string. The template, once created, will be cached.
2980
+     * @param object the object to format
2981
+     * @return the string created by the template
2982
+     *
2983
+     * @see ##ht() works uses <var>formatHtml</var> to set element's innerHTML.
2984
+     * @see ##HTML() create HTML nodes using <var>formatHtml</var>.
2985
+     * @see ##_.template() creates a template function, using the same syntax.
2986
+     * @see ##_.format() allows you to specify alternative escape mechanisms.
2987
+     */
2988
+    'formatHtml': formatHtml
2989
+    /*$
2990
+     * @stop
2991
+     */
2992
+
2993
+    // @cond !format dummyFormatHtml:0
2994
+    ,
2995
+
2996
+    ///#/snippet utilUnderscoreFuncs
2997
+    ///#snippet extrasUnderscoreFuncs
2998
+    // @condblock promise
2999
+    'promise': promise
3000
+    // @condend promise
3001
+
3002
+    /*$
3003
+     * @stop
3004
+     */
3005
+    // @cond !promise dummyPromise:0
3006
+
3007
+    ///#/snippet extrasUnderscoreFuncs
3008
+  }, _);
3009
+
3010
+  ////INITIALIZATION ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
3011
+  ///#snippet webInit
3012
+  /*$
3013
+   * @id ready_init
3014
+   * @dependency
3015
+   */
3016
+  document.addEventListener("DOMContentLoaded", function() {
3017
+    callList(DOMREADY_HANDLER);
3018
+    DOMREADY_HANDLER = _null;
3019
+  }, false);
3020
+  /*$
3021
+   @stop
3022
+   */
3023
+
3024
+
3025
+  ///#/snippet webInit
3026
+
3027
+  return {
3028
+    ///#snippet extrasExports
3029
+
3030
+    /*$
3031
+     * @id html
3032
+     * @group ELEMENT
3033
+     * @requires template ht
3034
+     * @configurable default
3035
+     * @name HTML()
3036
+     * @syntax HTML(templateString, object...)
3037
+     * @syntax HTML(templateFunction, object...)
3038
+     * @syntax HTML(idSelector, object...)
3039
+     * @module WEB
3040
+     * Creates a ##list#list## of HTML nodes from the given HTML template. The list is compatible with ##add(), ##fill() and related methods.
3041
+     * The template uses the ##template() syntax with ##escapeHtml() escaping for values.
3042
+     *
3043
+     * Please note that the function <var>HTML</var> will not be automatically exported by Minified. You should always import it
3044
+     * using the recommended import statement:
3045
+     * <pre>
3046
+     * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE, <strong>HTML = MINI.HTML</strong>;
3047
+     * </pre>
3048
+     *
3049
+     * @example Creating a HTML element showing a number:
3050
+     * <pre>
3051
+     * &lt;div id="price">-&lt;/div>
3052
+     * </pre>
3053
+     * Then the price can be set like this:
3054
+     * <pre>
3055
+     * var price = 14.9;
3056
+     * $('#price').fill(HTML('&lt;b>${{::0.99}}&lt;/b>', price));
3057
+     * </pre>
3058
+     * Results in:
3059
+     * <pre>
3060
+     * &lt;div id="price">&lt;b>$14.90&lt;/b>&lt;/div>
3061
+     * </pre>
3062
+     *
3063
+     * @example Adding elements to an existing list:
3064
+     * <pre>
3065
+     * var names = [ {first: 'James', last: 'Sullivan'},
3066
+     *               {first: 'Michael', last: 'Wazowski'} ];
3067
+     * $('#list').add(HTML('{{each}}&lt;li>{{this.first}} {{this.last}}&lt;/li>{{/each}}', names);
3068
+     * </pre>
3069
+     * The code adds this to #list:
3070
+     * <pre>
3071
+     * &lt;li>James Sullivan&lt;li>&lt;li>Michael Wazowski&lt;/li>
3072
+     * </pre>
3073
+     *
3074
+     * @example You can store templates in &lt;script&gt; tags. First you need to create a &lt;script&gt; tag with a type not
3075
+     *          supported by the browser and put your template in there, like this:
3076
+     * <pre>&lt;script id="myTimeTpl" type="minified-template"&gt;The time is {{HH:mm:ss}}.&lt;/script&gt;</pre>
3077
+     * Then you can specify the tag's id directly to access it:
3078
+     * <pre>$('#timeDisplay').fill(HTML('#myTimeTpl', new Date()));</pre>
3079
+     *
3080
+     * @param templateString the template using ##template() syntax. Please note, because this is a template, you should
3081
+     *                     avoid creating the template itself dynamically, as compiling templates is expensive and
3082
+     *                     Minified will cache only a limited number of templates. Exception: If the template string does not use
3083
+     *                     any template functionality (no {{}}), it does not need to be compiled and won't be cached.
3084
+     *                     The template will use ##escapeHtml() as escape function, so all template substitutions will be HTML-escaped,
3085
+     *                     unless you use triple curly-braces.
3086
+     * @param templateFunction instead of a HTML template <var>HTML()</var> also accepts a template function, e.g. one
3087
+     *                         created by ##template(). It will be invoked with the object as only argument.
3088
+     * @param idSelector if you pass an ID CSS selector in the form "#myScript", Minified will recognize this and use the content
3089
+     *                   of the specified &lt;script> element as template. This allows you to put your template into
3090
+     *                   a &lt;script&gt; tag with a non-JavaScript type (see example). Any string that starts with '#' and does not
3091
+     *                   contain any spaces is used as selector.
3092
+     * @param object optional one or more objects to pass to the template. If object is not set, the template is called with <var>undefined</var>
3093
+     *                        as object. If exactly one object is given, it is passed directly to the template. If you specify more than one
3094
+     *                        object, they are ##merge#merged##.
3095
+     * @return the list containing the new HTML nodes
3096
+     *
3097
+     * @see ##ht() is a shortcut for <code>fill(HTML())</code>.
3098
+     * @see ##EE() is a different way of creating HTML nodes.
3099
+     */
3100
+    'HTML': function () {
3101
+      var div = EE('div');
3102
+      return  _(call(div['ht'], div, arguments)[0].childNodes);
3103
+    },
3104
+    /*$
3105
+     * @stop
3106
+     */
3107
+
3108
+    ///#/snippet extrasExports
3109
+    ///#snippet utilExports
3110
+    /*$
3111
+     * @id underscore
3112
+     * @group LIST
3113
+     * @name _()
3114
+     * @syntax _(item...)
3115
+     * @configurable default
3116
+     * @module UTIL
3117
+     * Creates a new Minified list. Supports variable arguments so you can add items directly to the list. For arguments that are lists
3118
+     * (as defined by ##_.isList()), the list content will be added to the new list. Unlike #dollar#$()#, this is not done recursively
3119
+     * and thus you can create a list of lists by wrapping arguments in a list. Another difference between <var>_()</var> and <var>$()</var>
3120
+     * is that <var>$()</var> will automatically remove <var>null</var> values while <var>_()</var> will keep them.
3121
+     *
3122
+     * @example Creating an empty list:
3123
+     * <pre>_()</pre>
3124
+     *
3125
+     * @example Creating a list with three items:
3126
+     * <pre>_(1, 2, 3)</pre>
3127
+     *
3128
+     * @example Creating the same list, but by passing an array. One array level will be flattened:
3129
+     * <pre>_([1, 2, 3])</pre>
3130
+     *
3131
+     * @example Creating a list containing the arrays [1, 2] and [3, 4].
3132
+     * <pre>_([[1, 2], [3, 4]])</pre>
3133
+     *
3134
+     * @example Merging two lists:
3135
+     * <pre>var a = _("a", "b", "c");
3136
+     * var b = _("x", "y", "z");
3137
+     * var merged = _(a, b);    // contains _("a", "b", "c", "x", "y", "z")
3138
+     * </pre>
3139
+     *
3140
+     * @example Adding two elements to a list:
3141
+     * <pre>var a = _(1, 2, 3);
3142
+     * var a4 = _(a, 4);       // contains _(1, 2, 3, 4)
3143
+     * </pre>
3144
+     *
3145
+     * @example Mixing different list types and single elements:
3146
+     * <pre>_(1, [], [2, 3], _(), _(4, 5)); // same content as _(1, 2, 3, 4, 5)</pre>
3147
+     *
3148
+     * @param item an item to add to the new list. If it is a list (as defined by ##_.isList()), its content will be to the new
3149
+     *        ##Minified list#list## (but NOT recursively).
3150
+     */
3151
+    '_': _,
3152
+    /*$
3153
+     * @stop
3154
+     */
3155
+    ///#/snippet utilExports
3156
+    ///#snippet webExports
3157
+
3158
+    /*$
3159
+     * @id dollar
3160
+     * @group SELECTORS
3161
+     * @requires
3162
+     * @dependency yes
3163
+     * @name $()
3164
+     * @syntax $()
3165
+     * @syntax $(selector)
3166
+     * @syntax $(selector, context)
3167
+     * @syntax $(selector, context, childOnly)
3168
+     * @syntax $(list)
3169
+     * @syntax $(list, context)
3170
+     * @syntax $(list, context, childOnly)
3171
+     * @syntax $(object)
3172
+     * @syntax $(object, context)
3173
+     * @syntax $(object, context, childOnly)
3174
+     * @syntax $(domreadyFunction)
3175
+     * @module WEB
3176
+     * Creates a new ##list#Minified list##, or register a DOMReady-handler.
3177
+     * The most common usage is with a CSS-like selector. <var>$()</var> will then create a list containing all elements of the current HTML
3178
+     * document that fulfill the filter conditions. Alternatively you can also specify a list of objects or a single object.
3179
+     * Nested lists will automatically be flattened, and nulls will automatically be removed from the resulting list.
3180
+     * If you call <var>$()</var> without any arguments, it will return an empty list.
3181
+     *
3182
+     * Additionally, you can specify a second argument to provide a context. Contexts only make sense if you selected
3183
+     * HTML nodes with the first parameter. Then the context limits the resulting list to include only those nodes
3184
+     * that are descendants of the context nodes. The context can be either a selector, a list or a single HTML node, and will be
3185
+     * processed like the first argument. A third arguments allows you to limit the list to
3186
+     * only those elements that are direct children of the context nodes (so a child of a child would be filtered out).
3187
+     *
3188
+     * The lists created by <var>$()</var> are the same type as the ##list#Minified lists## created by Util's #underscore#_() constructor and other
3189
+     * Util methods. All Util methods work on lists created by <var>$()</var>. If you want to add your own methods to those lists,
3190
+     * use ##M#MINI.M##.
3191
+     *
3192
+     * As a special shortcut, if you pass a function to <var>$()</var>, it will be registered using #ready#$.ready() to be executed
3193
+     * when the DOM model is complete.
3194
+     *
3195
+     * @example A simple selector to find an element by id.
3196
+     * <pre>
3197
+     * var l0 = $('#myElementId');
3198
+     * </pre>
3199
+     *
3200
+     * @example You can pass an object reference to create a list containing only this element:
3201
+     * <pre>
3202
+     * var l1 = $(document.getElementById('myElementId'));
3203
+     * </pre>
3204
+     *
3205
+     * @example Lists and arrays will be copied:
3206
+     * <pre>
3207
+     * var l2 = $([elementA, elementB, elementC]);
3208
+     * </pre>
3209
+     *
3210
+     * @example Lists will be automatically flattened and nulls removed. So this list <var>l3</var> has the same content as <var>l2</var>:
3211
+     * <pre>
3212
+     * var l3 = $([elementA, [elementB, null, elementC], null]);
3213
+     * </pre>
3214
+     *
3215
+     * @example This is a simple selector to find all elements with the given class.
3216
+     * <pre>
3217
+     * var l4 = $('.myClass');
3218
+     * </pre>
3219
+     *
3220
+     * @example A selector to find all elements of the given type.
3221
+     * <pre>
3222
+     * var l5 = $('input'); // finds all input elements
3223
+     * </pre>
3224
+     *
3225
+     * @example A selector to find all elements with the given type and class.
3226
+     * <pre>
3227
+     * var l6 = $('input.myRadio'); // finds all input elements with class 'myRadio'
3228
+     * </pre>
3229
+     *
3230
+     * @example A selector to find all elements that are descendants of the given element.
3231
+     * <pre>
3232
+     * var l7 = $('#myForm input'); // finds all input elements contained in the element myForm
3233
+     * </pre>
3234
+     *
3235
+     * @example A selector to find all elements that have either a CSS class 'a' or class 'b':
3236
+     * <pre>
3237
+     * var l8 = $('.a, .b'); // finds all elements that have class a or class b
3238
+     * </pre>
3239
+     *
3240
+     * @example A selector that finds all elements that are descendants of the element myDivision, are inside an element with the
3241
+     * class .myForm and are input elements:
3242
+     * <pre>
3243
+     * var l9 = $('#myDivision .myForm input');
3244
+     * </pre>
3245
+     *
3246
+     * @example Contexts can make it easier to specify ancestors:
3247
+     * <pre>
3248
+     * var l10 = $('.myRadio', '#formA, #formB, #formC');
3249
+     * </pre>
3250
+     * The result is identical to:
3251
+     * <pre>
3252
+     * var l10 = $('#formA .myRadio, #formB .myRadio, #formC .myRadio');
3253
+     * </pre>
3254
+     *
3255
+     * @example Using one of the list functions, ##set(), on the list, and setting the element's text color. '$' at the beginning of the property name sets a CSS value.
3256
+     * <pre>
3257
+     * $('#myElementId').set('$color', 'red');
3258
+     * </pre>
3259
+     *
3260
+     * @example Most list methods return the list you invoked them on, allowing you to chain them:
3261
+     * <pre>
3262
+     * $('#myForm .myRadio').addClass('uncheckedRadio')
3263
+     *                      .set('checked', true)
3264
+     *                      .on('click', function() {
3265
+     *                             $(this).set({@: 'uncheckedRadio');
3266
+     *                      });
3267
+     * </pre>
3268
+     *
3269
+     * @example Using $() as a #ready#$.ready() shortcut:
3270
+     * <pre>
3271
+     * $(function() {
3272
+     *   // in here you can safely work with the HTML document
3273
+     * });
3274
+     * </pre>
3275
+     *
3276
+     * @param selector a simple, CSS-like selector for HTML elements. It supports '#id' (lookup by id), '.class' (lookup by class),
3277
+     *             'element' (lookup by elements) and 'element.class' (combined class and element). Use commas to combine several selectors.
3278
+     *             You can also join two or more selectors by space to find elements which are descendants of the previous selectors.
3279
+     *             For example, use 'div' to find all div elements, '.header' to find all elements containing a class name called 'header', and
3280
+     *             'a.popup' for all a elements with the class 'popup'. To find all elements with 'header' or 'footer' class names,
3281
+     *             write '.header, .footer'. To find all divs elements below the element with the id 'main', use '#main div'.
3282
+     *             The selector "*" will return all elements.
3283
+     * @param list a list to copy. It can be an array, another Minified list, a DOM nodelist or anything else that has a <var>length</var> property and
3284
+     *             allows read access by index. A shallow copy of the list will be returned. Nulls will be automatically removed from the copy. Nested lists
3285
+     *             will be flattened, so the result only contains nodes.
3286
+     * @param object an object to create a single-element list containing only the object. If the argument is null, an empty list will be returned.
3287
+     * @param domreadyFunction a function to be registered using #ready#$.ready().
3288
+     * @param context optional an optional selector, node or list of nodes which specifies one or more common ancestor nodes for the selection. The context can be specified as
3289
+     *             a selector, a list or using a single object, just like the first argument.
3290
+     *             The returned list will contain only descendants of the context nodes. All others will be filtered out.
3291
+     * @param childOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not
3292
+     *             true, all descendants of the context will be included.
3293
+     * @return the array-like ##list#Minified list## object containing the content specified by the selector.
3294
+     *             Please note that if the first argument was a list, the existing order will be kept. If the first argument was a simple selector, the nodes are in document order.
3295
+     *             If you combined several selectors using commas, only the individual results of the selectors will keep the document order,
3296
+     *             but will then be joined to form a single list. This list will
3297
+     *             not be in document order anymore, unless you use a build without legacy IE support.
3298
+     *             Duplicate nodes will be removed from selectors, but not from lists.
3299
+     *
3300
+     * @see #underscore#_() is Util's alternative constructor for ##list#Minified lists##
3301
+     * @see ##dollardollar#$$()## works like <var>$()</var>, but returns the resulting list's first element.
3302
+     */
3303
+    '$': $,
3304
+
3305
+    /*$
3306
+     * @id dollardollar
3307
+     * @group SELECTORS
3308
+     * @requires
3309
+     * @configurable default
3310
+     * @name $$()
3311
+     * @syntax $(selector)
3312
+     * @syntax $(selector, context)
3313
+     * @syntax $(selector, context, childOnly)
3314
+     * @shortcut $$() - It is recommended that you assign MINI.$$ to a variable $$.
3315
+     * @module WEB
3316
+     * Returns a DOM object containing the first match of the given selector, or <var>undefined</var> if no match was found.
3317
+     * <var>$$</var> allows you to easily access an element directly. It is the equivalent to writing <code>$(selector)[0]</code>.
3318
+     *
3319
+     * Please note that the function <var>$$</var> will not be automatically exported by Minified. You should always import it
3320
+     * using the recommended import statement:
3321
+     * <pre>
3322
+     * var MINI = require('minified'), $ = MINI.$, $$ = MINI.$$, EE = MINI.EE;
3323
+     * </pre>
3324
+     *
3325
+     * @example Select the checkbox 'myCheckbox':
3326
+     * <pre>
3327
+     * $$('#myCheckbox').checked = true;
3328
+     * </pre>
3329
+     *
3330
+     * @param selector a simple, CSS-like selector for the element. Uses the same syntax as #dollar#$(). The most common
3331
+     *                 parameter for this function is the id selector with the syntax "#id".
3332
+     * @param context optional an optional selector, node or list of nodes which specifies one or more common ancestor nodes for the selection. The context can be specified as
3333
+     *             a selector, a list or using a single object, just like the first argument.
3334
+     *             The returned list will contain only descendants of the context nodes. All others will be filtered out.
3335
+     * @param childOnly optional if set, only direct children of the context nodes are included in the list. Children of children will be filtered out. If omitted or not
3336
+     *             true, all descendants of the context will be included.
3337
+     * @return a DOM object of the first match, or <var>undefined</var> if the selector did not return at least one match
3338
+     *
3339
+     * @see ##dollar#$()## creates a list using the selector, instead of returning only the first result.
3340
+     */
3341
+    '$$': $$,
3342
+
3343
+    /*$
3344
+     * @id M
3345
+     * @name M
3346
+     * @syntax MINI.M
3347
+     * @module WEB, UTIL
3348
+     *
3349
+     * Exposes the internal class used by all  ##list#Minified lists##. This is mainly intended to allow you adding your
3350
+     * own functions.
3351
+     *
3352
+     * @example Adding a function printLength() to <var>M</var>:
3353
+     * <pre>
3354
+     * MINI.M.prototype.printLength = function() { console.log(this.length); };
3355
+     * </pre>
3356
+     */
3357
+    'M': M,
3358
+
3359
+    /*$
3360
+     * @id getter
3361
+     * @requires get
3362
+     * @name MINI.getter
3363
+     * @syntax MINI.getter
3364
+     * @module WEB
3365
+     *
3366
+     * Exposes a map of prefix handlers used by ##get(). You can add support for a new prefix in <var>get()</var>
3367
+     * by adding a function to this map. The prefix can be any string consisting solely of non-alphanumeric characters
3368
+     * that's not already used by Minified.
3369
+     *
3370
+     * You must not replace <var>getters</var> by a new map, but must always modify the existing map.
3371
+     *
3372
+     * The function's signature is <code>function(list, name)</code> where
3373
+     * <dl><dt>list</dt><dd>Is the Minified list to get the value from. By convention you should always use only the first element. The list is
3374
+     *                      non-empty and the first elememt can't be null or undefined (get() automatically returns <var>undefined</var> in
3375
+     *                      all other case).</dd>
3376
+     *     <dt>name</dt><dd>The name of the property. That's the part AFTER the prefix.</dd>
3377
+     *     <dt class="returnValue">(callback return value)</dt><dd>The value to return to the user.</dd></dl>
3378
+     *
3379
+     * @example Adding a shortcut '||' for accessing border style properties:
3380
+     * <pre>
3381
+     * MINI.getter['||'] = function(list, name) {
3382
+     * 	return list.get('$border' + name.replace(/^[a-z]/, function(a) { return a.toUpperCase()});
3383
+     * };
3384
+     *
3385
+     * var borderColor = $('#box').get('||color'); // same as '$borderColor'
3386
+     * var borderLeftRadius = $('#box').get('||leftRadius'); // same as '$borderLeftRadius'
3387
+     * </pre>
3388
+     *
3389
+     * @example Adding XLink attribute support to get(). This is useful if you work with SVG. The prefix is '>'.
3390
+     * <pre>
3391
+     * MINI.getter['>'] = function(list, name) {
3392
+     * 	return list[0].getAttributeNS('http://www.w3.org/1999/xlink', name);
3393
+     * };
3394
+     *
3395
+     * var xlinkHref = $('#svgLink').get('>href');
3396
+     * </pre>
3397
+     */
3398
+    'getter': getter,
3399
+
3400
+    /*$
3401
+     * @id setter
3402
+     * @requires set
3403
+     * @name MINI.setter
3404
+     * @syntax MINI.setter
3405
+     * @module WEB
3406
+     *
3407
+     * Exposes a map of prefix handlers used by ##set(). You can add support for a new prefix in <var>set()</var>
3408
+     * by adding a function to this map. The prefix can be any string consisting solely of non-alphanumeric characters
3409
+     * that's not already used by Minified.
3410
+     *
3411
+     * You must not replace <var>setters</var> by a new map, but must always modify the existing map.
3412
+     *
3413
+     * The function's signature is <code>function(list, name, value)</code> where
3414
+     * <dl><dt>list</dt><dd>Is the Minified list to use.</dd>
3415
+     *     <dt>name</dt><dd>The name of the property. That's the part AFTER the prefix.</dd>
3416
+     *     <dt>value</dt><dd>Either the value to set, or a callback function to create the value that you must call for each
3417
+     *     value (see ##set() ).</dd>
3418
+     *     </dl>
3419
+     *
3420
+     * If you provide complete ##get() and ##set() support for a prefix, you are also able to use it in other Minified
3421
+     * function such as ##animate() and ##toggle().
3422
+     *
3423
+     * @example Adding a shortcut '||' for accessing border style properties. As it's just calling ##set() for an existing
3424
+     * property, it is not required to extra code for the callback.
3425
+     * <pre>
3426
+     * MINI.setter['||'] = function(list, name, value) {
3427
+     * 	list.set('$border' + name.replace(/^[a-z]/, function(a) { return a.toUpperCase()}, value);
3428
+     * };
3429
+     *
3430
+     * $('#box').set('||color', 'red');   // same as set('$borderColor', 'red')
3431
+     * $('#box').set('||leftRadius', 4);  // same as set('$borderLeftRadius', 4)
3432
+     * </pre>
3433
+     *
3434
+     * @example Adding XLink attribute support to set(). This is useful if you work with SVG. The prefix is '>'.
3435
+     * <pre>
3436
+     * MINI.setter['>'] = function(list, name, value) {
3437
+     * 	list.each(function(obj, index) {
3438
+     * 		var v;
3439
+     * 		if (_.isFunction(value))
3440
+     * 			v = value(obj.getAttributeNS('http://www.w3.org/1999/xlink', name), index, obj);
3441
+     * 		else
3442
+     * 			v = value;
3443
+     *
3444
+     *		if (v == null)
3445
+     *			obj.removeAttributeNS('http://www.w3.org/1999/xlink', name);
3446
+     *		else
3447
+     *			obj.setAttributeNS('http://www.w3.org/1999/xlink', name, v);
3448
+     *	});
3449
+     * };
3450
+     *
3451
+     * $('#svgLink').set('>href', 'http://minifiedjs.com/');
3452
+     * </pre>
3453
+     */
3454
+    'setter': setter
3455
+    /*$
3456
+     * @stop
3457
+     */
3458
+    ///#/snippet webExports
3459
+  };
3460
+
3461
+  ///#snippet commonAmdEnd
3462
+});
3463
+///#/snippet commonAmdEnd
3464
+///#snippet  webDocs
3465
+
3466
+/*$
3467
+ * @id list
3468
+ * @name Minified Lists
3469
+ * @module WEB, UTIL
3470
+ *
3471
+ * <i>Minified lists</i> are Array-like objects provided by Minified. Like a regular JavaScript array,
3472
+ * they provide a <var>length</var> property and you can access their content using the index operator (<code>a[5]</code>).
3473
+ * However, they do not provide the same methods as JavaScript's native array and are designed to be immutable, so
3474
+ * there is no direct way to add something to a Minified list. Instead Minified provides a number of functions and methods
3475
+ * that take a list and create a modified copy which, for example, may contain additional elements.
3476
+ *
3477
+ * Minified lists are typically created either using the Web module's #dollar#$()</a></code> function or with the Util module's
3478
+ * #underscore#_()</a></code> function, but many functions in the Util module also return a Minified list.
3479
+ *
3480
+ * The Util module provides a function ##_.array() that converts a Minified list to a regular JavaScript array.
3481
+ */
3482
+
3483
+/*$
3484
+ * @id promiseClass
3485
+ * @name Promise
3486
+ * @module WEB, UTIL
3487
+ *
3488
+ * <i>Promises</i> are objects that represent the future result of an asynchronous operation. When you start such an operation, using #request#$.request(),
3489
+ * ##animate(), or ##wait(), you will get a Promise object that allows you to get the result as soon as the operation is finished.
3490
+ *
3491
+ * Minified's full distribution ships with a <a href="http://promises-aplus.github.io/promises-spec/">Promises/A+</a>-compliant implementation of Promises that should
3492
+ * be able to interoperate with most other Promises implementations. Minified's Web module in stand-alone distribution comes with a limited implementation.
3493
+ * See below for details.
3494
+ *
3495
+ * What may be somewhat surprising about this Promises specification is that the only standard-compliant way to access the result is to
3496
+ * register callbacks. They will be invoked as soon as the operation is finished.
3497
+ * If the operation already ended when you register the callbacks, the callback will then just be called from the event loop as soon
3498
+ * as possible (but never while the ##then() you register them with is still running).<br/>
3499
+ * This design forces you to handle the operation result asynchronously and disencourages 'bad' techniques such as polling.
3500
+ *
3501
+ * The central method of a Promise, and indeed the only required function in Promises/A+, is ##then(). It allows you to register
3502
+ * two callback methods, one for success (called 'fulfillment' in Promises/A+ terminology) and one for failures (called 'rejection' in Promises/A+).
3503
+ *
3504
+ * This example shows you how to use <var>then()</var>:
3505
+ * <pre>
3506
+ * $.request('get', 'http://example.com/weather?zip=90210')
3507
+ *  .then(function success(result) {
3508
+ *      alert('The weather is ' + result);
3509
+ *  }, function error(exception) {
3510
+ *  	alert('Something went wrong');
3511
+ *  });
3512
+ * </pre>
3513
+ *
3514
+ * What makes Promises so special is that ##then() itself returns a new Promise, which is based on the Promise <var>then()</var> was called on, but can be
3515
+ * modified by the outcome of callbacks. Both arguments to <var>then()</var> are optional, and you can also write the code like this:
3516
+ * <pre>
3517
+ * $.request('get', 'http://example.com/weather?zip=90210')
3518
+ *  .then(function success(result) {
3519
+ *      alert('The weather is ' + result);
3520
+ *  })
3521
+ *  .then(null, function error(exception) {
3522
+ *  	alert('Something went wrong');
3523
+ *  });
3524
+ * </pre>
3525
+ *
3526
+ * Because the first ##then() returns a new Promise based on the original Promise, the second <var>then()</var> will handle errors of the request just like
3527
+ * the first one did. There is only one subtle difference in the second example: the error handler will not only be called if the request failed,
3528
+ * but also when the request succeded but the success handler threw an exception. That's one of the two differences between the original Promise and
3529
+ * the Promise returned by <var>then()</var>. Any exception thrown in a callback causes the new Promise to be in error state.
3530
+ *
3531
+ * Before I show you the second difference between the original Promise and the new Promise, let me make the example a bit more readable
3532
+ * by using ##error(), which is not part of Promises/A+, but a simple extension by Minified. It just registers the failure callback without
3533
+ * forcing you to specify <var>null</var> as first argument:
3534
+ * <pre>
3535
+ * $.request('get', 'http://example.com/weather?zip=90210')
3536
+ *  .then(function success(result) {
3537
+ *      alert('The weather is ' + result);
3538
+ *  })
3539
+ *  .error(function error(exception) {  // error(callback) is equivalent to then(null, callback)
3540
+ *  	alert('Something went wrong');
3541
+ *  });
3542
+ * </pre>
3543
+ *
3544
+ * A very powerful capability of Promises is that you can easily chain them. If a ##then() callback returns a value, the new Promise returned
3545
+ * by <var>then()</var> will be marked as success (fulfilled) and this value is the result of the operation. If a callback returns a Promise,
3546
+ * the new Promise will assume the state of the returned Promise. You can use the latter to create chains of asynchronous operations,
3547
+ * but you still need only a single error handler for all of them and you do not need to nest functions to achieve this:
3548
+ * <pre>
3549
+ * $.request('get', 'http://example.com/zipcode?location=Beverly+Hills,+CA')
3550
+ *  .then(function(resultZip) {
3551
+ *      return $.request('get', 'http://example.com/weather', {zip: resultZip});
3552
+ *  })
3553
+ *  .then(function(resultWeather) {
3554
+ *      alert('The weather in Beverly Hills is ' + resultWeather);
3555
+ *  })
3556
+ *  .error(function(exception) {
3557
+ *  	alert('Something went wrong');
3558
+ *  });
3559
+ * </pre>
3560
+ *
3561
+ * Only the full Minified distribution allows you to create promises yourself, using the ##promise() function. The Promises/A+
3562
+ * specification does not specify how to fulfill a promise, but in Minified's implementation every Promise object has a function <code>fire()</code>
3563
+ * that needs to be called when the promise result is ready. It requires two arguments.
3564
+ * The first is a boolean, <var>true</var> for a successful operation and <var>false</var> for a failure. The second is an array or list containing the
3565
+ * arguments to call the corresponding ##then() handler with.
3566
+ *
3567
+ * The following example is a function, similar to ##wait(), that returns a Promise which succeeds after the given amount
3568
+ * of milliseconds has passed.
3569
+ * It then fulfills the promise with the number of milliseconds as argument.
3570
+ *
3571
+ * <pre>
3572
+ * function timeout(durationMs) {
3573
+ *		var p = _.promise();
3574
+ *		setTimeout(function() { p.fire(true, [durationMs]); }, durationMs);
3575
+ *		return p;
3576
+ * }
3577
+ * </pre>
3578
+ * Call it like this:
3579
+ * <pre>
3580
+ * timeout(1000).then(function(ms) { window.alert(ms+ ' milliseconds have passed.'); });
3581
+ * </pre>
3582
+ *
3583
+ * <h3>Limited Promises Implementation in Web module</h3>
3584
+ * If you use only the Web module, instead of the full implementation, the promises implementation is not fully Promises/A+ compliant.
3585
+ * One major difference is that it does not allow you create promises yourself. The only way to get a promise in the Web module
3586
+ * is from functions like ##animate() and ##request(). The other difference is that the interoperability with other promises frameworks
3587
+ * is limited, even though it should be good enough most of the time.
3588
+ *
3589
+ * There are two things you may run into when you use Web's simplified implementation with a complete implementation:
3590
+ * <ol><li>The simplified implementation does not support recursive thenables. So when you register callbacks with ##then(),
3591
+ * you can return a promise or a thenable, but only if that promise is not also returning a promise.</li>
3592
+ * <li>Many corner cases required by the Promises/A+ specification are not handled. When interoperating using
3593
+ * reasonable implementations, you may never run into this, but Promises/A+ has detailed rules for things like ##then()
3594
+ * methods implemented as dynamic getter and returning a new value on each invocation or throwing exceptions. If you need
3595
+ * a water-proof implementation, you need to use the complete implementation in Minified's full package.</li></ol>
3596
+ */
3597
+/*$
3598
+ * @stop
3599
+ */
3600
+
3601
+///#/snippet  webDocs
3602
+
0 3603
new file mode 100644
... ...
@@ -0,0 +1,2 @@
1
+@import "clay/vars";
2
+@import "clay/mixins";
0 3
new file mode 100644
... ...
@@ -0,0 +1,201 @@
1
+@import "bourbon";
2
+@import "clay";
3
+
4
+html, body {
5
+  @include font-pfdin(regular);
6
+  -webkit-font-smoothing: antialiased;
7
+  font-size: $em-base;
8
+  line-height: $base-line-height;
9
+  height:100%;
10
+  color: $color-white;
11
+
12
+  &.platform-ios {
13
+    font-size: 16px;
14
+  }
15
+
16
+}
17
+
18
+body {
19
+  background-color: $color-gray-2;
20
+  padding: 0 $item-spacing-h $item-spacing-v;
21
+}
22
+
23
+em {
24
+  font-style: italic;
25
+}
26
+
27
+strong {
28
+  @include font-pfdin(medium);
29
+  color: $color-orange;
30
+}
31
+
32
+a {
33
+  color: $color-gray-8;
34
+
35
+  &:hover {
36
+    color: inherit;
37
+  }
38
+}
39
+
40
+h1, h2, h3, h4 {
41
+  text-transform: uppercase;
42
+  @include font-pfdin(medium);
43
+  @include pfdin-uppercase();
44
+}
45
+
46
+h1 {
47
+  @include font-size(2);
48
+}
49
+
50
+h2 {
51
+  @include font-size(1.8);
52
+}
53
+
54
+h3 {
55
+  @include font-size(1.5);
56
+}
57
+
58
+h4 {
59
+  @include font-size(1.2);
60
+}
61
+
62
+h5 {
63
+  @include font-size(1);
64
+}
65
+
66
+h6 {
67
+  @include font-size(0.8);
68
+}
69
+
70
+input {
71
+  font-family: inherit;
72
+  font-size: inherit;
73
+  line-height: inherit;
74
+}
75
+
76
+label {
77
+  display: flex;
78
+  justify-content: space-between;
79
+  align-items: center;
80
+  padding: $item-spacing-v $item-spacing-h;
81
+
82
+  .input {
83
+    white-space: nowrap;
84
+    display: flex;
85
+    max-width: 50%;
86
+    margin-left: $item-spacing-h;
87
+  }
88
+
89
+  &.invalid .input:after {
90
+    $size: 1.1rem;
91
+
92
+    content: "!";
93
+    display: inline-block;
94
+    color: $color-white;
95
+    background: $color-orange;
96
+    border-radius: $size / 2;
97
+    width: $size;
98
+    text-align: center;
99
+    height: $size;
100
+    font-size: $size * 0.75;
101
+    vertical-align: middle;
102
+    line-height: $size;
103
+    box-shadow: $box-shadow-small-components;
104
+    @include font-pfdin(medium);
105
+    flex: 0 0 $size;
106
+    margin-left: 0.3rem;
107
+  }
108
+}
109
+
110
+.hide {
111
+  display: none !important;
112
+}
113
+
114
+.tap-highlight {
115
+  @include tap-highlight();
116
+  border-radius: $border-radius;
117
+}
118
+
119
+.component {
120
+  padding-top: $item-spacing-v;
121
+
122
+  &.disabled {
123
+    pointer-events: none;
124
+    > * {
125
+      opacity: 0.25;
126
+    }
127
+  }
128
+}
129
+
130
+.section {
131
+  background: $color-gray-4;
132
+  border-radius: 0.25rem;
133
+  box-shadow: $color-gray-1 0 0.15rem 0.25rem;
134
+
135
+  > .component {
136
+    padding-bottom: $item-spacing-v;
137
+    padding-right: $item-spacing-h;
138
+    padding-left: $item-spacing-h;
139
+    position: relative;
140
+    margin-top: 1rem;
141
+
142
+    &:not(.hide) ~ .component {
143
+      margin-top: 0;
144
+    }
145
+
146
+    &:first-child:after {
147
+      display: none;
148
+    }
149
+
150
+    &:after {
151
+      content: "";
152
+      background: $color-gray-6;
153
+      display: block;
154
+      position: absolute;
155
+      top: 0;
156
+      left: $item-spacing-h / 2;
157
+      right: $item-spacing-h / 2;
158
+      height: 1px;
159
+      pointer-events: none;
160
+    }
161
+  }
162
+
163
+  // don't show the separator for the first non-hidden item
164
+  > .component:not(.hide):after {
165
+    display: none;
166
+  }
167
+
168
+  > .component:not(.hide) ~ .component:not(.hide):after {
169
+    display: block;
170
+  }
171
+
172
+  > .component-heading:first-child {
173
+    background: $color-gray-3;
174
+    border-radius: $border-radius $border-radius 0 0;
175
+
176
+    // don't show the separator for the first non-hidden item after the heading
177
+    &:after,
178
+    ~ .component:not(.hide):after {
179
+      display: none;
180
+    }
181
+
182
+    ~ .component:not(.hide) ~ .component:not(.hide):after {
183
+      display: block;
184
+    }
185
+  }
186
+
187
+}
188
+
189
+.description {
190
+  padding: 0 $item-spacing-h $item-spacing-v ;
191
+  @include font-size(0.9);
192
+  color: $color-gray-9;
193
+  text-align: left;
194
+}
195
+
196
+.inputs {
197
+  display: block;
198
+  width:100%;
199
+  border-collapse: collapse;
200
+}
201
+
0 202
new file mode 100644
... ...
@@ -0,0 +1,6 @@
1
+@font-face {
2
+  font-family: PFDinDisplayProRegularWebfont;
3
+  src: url(data:application/font-woff;charset=utf-8;base64,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) format('woff');
4
+  font-weight: normal;
5
+  font-style: normal;
6
+}
0 7
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+@import "vars";
2
+
3
+@mixin font-pfdin($weight: normal) {
4
+
5
+  font-weight: normal;
6
+
7
+  @if $weight == normal or $weight == regular {
8
+    font-family: 'PFDinDisplayPro-Regular', PFDinDisplayProRegularWebfont, sans-serif;
9
+  }
10
+
11
+  @if $weight == medium {
12
+    // iOS includes the PFDinDisplayPro-Medium in the webview but Android does not,
13
+    // so we apply a faux bold on the regular weight.
14
+    font-family: 'PFDinDisplayPro-Medium', PFDinDisplayProRegularWebfont, sans-serif;
15
+
16
+    .platform-android & {
17
+      font-family: PFDinDisplayProRegularWebfont, sans-serif;
18
+      font-weight: bold;
19
+      letter-spacing: 0.025em;
20
+    }
21
+  }
22
+}
23
+
24
+@mixin pfdin-uppercase {
25
+  text-transform: uppercase;
26
+  position: relative;
27
+  top: 0.05rem;
28
+  line-height: 0.9;
29
+}
30
+
31
+@mixin font-size($size: 1) {
32
+  $font-size:  $size * 1rem;
33
+  font-size:$font-size;
34
+  line-height: $base-line-height * ceil($font-size / $base-line-height);
35
+}
36
+
37
+@mixin tap-highlight($color: rgba(255, 255, 255, 0.1)) {
38
+  -webkit-tap-highlight-color: $color;
39
+
40
+  &:active {
41
+    background-color: $color;
42
+  }
43
+}
0 44
new file mode 100644
... ...
@@ -0,0 +1,58 @@
1
+/* http://meyerweb.com/eric/tools/css/reset/
2
+   v2.0b1 | 201101
3
+   NOTE: WORK IN PROGRESS
4
+   USE WITH CAUTION AND TEST WITH ABANDON */
5
+
6
+html, body, div, span, applet, object, iframe,
7
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8
+a, abbr, acronym, address, big, cite, code,
9
+del, dfn, em, img, ins, kbd, q, s, samp,
10
+small, strike, strong, sub, sup, tt, var,
11
+b, u, i, center,
12
+dl, dt, dd, ol, ul, li,
13
+fieldset, form, label, legend,
14
+table, caption, tbody, tfoot, thead, tr, th, td,
15
+article, aside, canvas, details, figcaption, figure,
16
+footer, header, hgroup, menu, nav, section, summary,
17
+time, mark, audio, video {
18
+  margin: 0;
19
+  padding: 0;
20
+  border: 0;
21
+  outline: 0;
22
+  font-size: 100%;
23
+  font: inherit;
24
+  vertical-align: baseline;
25
+}
26
+
27
+input, textarea, button {
28
+  outline: none;
29
+}
30
+
31
+/* HTML5 display-role reset for older browsers */
32
+article, aside, details, figcaption, figure,
33
+footer, header, hgroup, menu, nav, section {
34
+  display: block;
35
+}
36
+
37
+body {
38
+  line-height: 1;
39
+}
40
+
41
+ol, ul {
42
+  list-style: none;
43
+}
44
+
45
+blockquote:before, blockquote:after,
46
+q:before, q:after {
47
+  content: '';
48
+  content: none;
49
+}
50
+
51
+/* apply a natural box layout model to all elements, but allowing components to change */
52
+html {
53
+  box-sizing: border-box;
54
+}
55
+
56
+*, *:before, *:after {
57
+  box-sizing: inherit;
58
+}
0 59
new file mode 100644
... ...
@@ -0,0 +1,39 @@
1
+@import "bourbon";
2
+
3
+// Bourbon settings
4
+$em-base: 17px;
5
+
6
+// custom vars
7
+$base-line-height: 1.4;
8
+$base-height: rem($base-line-height * $em-base);
9
+$border-radius: 0.25rem;
10
+$item-spacing-v: $base-height / 2;
11
+$item-spacing-h: 0.75rem;
12
+$small-component-width: $base-height * $golden;
13
+
14
+// ---- Colors ------
15
+$color-orange: #ff4700;
16
+$color-orange-dark: #993d19;
17
+$color-red: #ff0000;
18
+$color-white: #ffffff;
19
+$color-black: #000000;
20
+
21
+// background color
22
+$color-gray-0: #111111;
23
+$color-gray-1: #2f2f2f;
24
+$color-gray-2: #333333;
25
+$color-gray-3: #414141;
26
+$color-gray-4: #484848; // divider
27
+$color-gray-5: #5b5b5b;
28
+$color-gray-6: #666666;
29
+$color-gray-7: #767676;
30
+$color-gray-8: #858585;
31
+$color-gray-9: #a4a4a4 ;
32
+$color-gray-10: #ececec;
33
+$color-gray-11: #f2f2f2;
34
+
35
+$button-padding: 0.6rem;
36
+$button-padding-ios: 0.5rem;
37
+
38
+$box-shadow-small-components: 0 0.1rem 0.1rem $color-gray-1;
39
+$box-shadow-large-components: 0 rem(3px) rem(15px) rgba(0,0,0,0.4);
0 40
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+.component-button {
2
+  text-align: center;
3
+
4
+  .section & {
5
+    padding-bottom: 0;
6
+  }
7
+
8
+  .description {
9
+    padding-left: 0;
10
+    padding-right: 0;
11
+  }
12
+}
0 13
new file mode 100644
... ...
@@ -0,0 +1,70 @@
1
+@import "bourbon";
2
+@import "clay";
3
+
4
+.component-checkbox {
5
+
6
+  display: block;
7
+
8
+  .section & {
9
+    padding-right: $item-spacing-h / 2;
10
+  }
11
+
12
+  > .label {
13
+    display: block;
14
+    padding-bottom: $item-spacing-v / 2;
15
+  }
16
+
17
+  .checkbox-group {
18
+
19
+    padding-bottom: $item-spacing-v / 2;
20
+
21
+    label {
22
+      padding: $item-spacing-v / 2 $item-spacing-h / 2;
23
+    }
24
+
25
+    .label {
26
+      font-size: 0.9em;
27
+    }
28
+
29
+    input {
30
+      opacity: 0;
31
+      position: absolute;
32
+    }
33
+
34
+    i {
35
+      display: block;
36
+      position: relative;
37
+      border-radius: $border-radius;
38
+      width: $base-height;
39
+      height: $base-height;
40
+      border: rem(2px) solid $color-gray-7;
41
+      flex-shrink: 0;
42
+    }
43
+
44
+    input:checked + i {
45
+      border-color: $color-orange;
46
+      background: $color-orange;
47
+      
48
+      &:after {
49
+        content: '';
50
+        box-sizing: border-box;
51
+        transform: rotate(45deg);
52
+        position: absolute;
53
+        left: 0.35rem;
54
+        top: -0.05rem;
55
+        display: block;
56
+        width: 0.5rem;
57
+        height: 1rem;
58
+        border: 0 solid $color-white;
59
+        border-right-width: rem(2px);
60
+        border-bottom-width: rem(2px);
61
+
62
+      }
63
+    }
64
+  }
65
+
66
+  .description {
67
+    padding-left: 0;
68
+    padding-right: 0;
69
+  }
70
+}
0 71
new file mode 100644
... ...
@@ -0,0 +1,98 @@
1
+@import "clay";
2
+
3
+.component-color {
4
+
5
+  .section & {
6
+    padding: 0;
7
+  }
8
+
9
+  .value {
10
+    width: $small-component-width;
11
+    height: $base-height;
12
+    border-radius: $base-height / 2;
13
+    box-shadow: $box-shadow-small-components;
14
+    display: block;
15
+    background: #000;
16
+  }
17
+
18
+  .picker-wrap {
19
+    left: 0;
20
+    top: 0;
21
+    right: 0;
22
+    bottom: 0;
23
+    position: fixed;
24
+    padding: $item-spacing-v $item-spacing-h /2;
25
+    background: rgba(0, 0, 0, 0.65);
26
+    opacity: 0;
27
+    transition: opacity 100ms ease-in 175ms;
28
+    pointer-events: none;
29
+    z-index: 100;
30
+    display: flex;
31
+    flex-direction: column;
32
+    justify-content: center;
33
+    align-items: center;
34
+
35
+    .picker {
36
+      padding: $item-spacing-v $item-spacing-h;
37
+      background: $color-gray-4;
38
+      box-shadow: $box-shadow-large-components;
39
+      border-radius: $border-radius;
40
+      width: 100%;
41
+      max-width: 26rem;
42
+      overflow: auto;
43
+    }
44
+
45
+    &.show {
46
+      transition-delay: 0ms;
47
+      pointer-events: auto;
48
+      opacity: 1;
49
+    }
50
+  }
51
+
52
+  .color-box-wrap {
53
+    box-sizing: border-box;
54
+    position: relative;
55
+    height: 0;
56
+    width: 100%;
57
+    padding: 0 0 100% 0; // overridden with inline style
58
+
59
+    .color-box-container {
60
+      position: absolute;
61
+      height: 99.97%;
62
+      width: 100%;
63
+      left: 0;
64
+      top: 0;
65
+
66
+      .color-box {
67
+        float:left;
68
+        cursor: pointer;
69
+        -webkit-tap-highlight-color: rgba(0,0,0,0);
70
+
71
+        &.rounded-tl {
72
+          border-top-left-radius: $border-radius;
73
+        }
74
+
75
+        &.rounded-tr {
76
+          border-top-right-radius: $border-radius;
77
+        }
78
+
79
+        &.rounded-bl {
80
+          border-bottom-left-radius: $border-radius;
81
+        }
82
+
83
+        &.rounded-br {
84
+          border-bottom-right-radius: $border-radius;
85
+        }
86
+
87
+        &.selected {
88
+          transform: scale(1.1);
89
+          border-radius: $border-radius;
90
+          box-shadow: #111 0 0 0.24rem;
91
+          position: relative;
92
+          z-index: 100;
93
+        }
94
+      }
95
+
96
+    }
97
+  }
98
+}
0 99
new file mode 100644
... ...
@@ -0,0 +1,49 @@
1
+@import "clay";
2
+
3
+.component-input {
4
+
5
+  .section & {
6
+    padding: 0;
7
+  }
8
+
9
+  label {
10
+    display: block;
11
+  }
12
+
13
+  .label {
14
+    padding-bottom: $item-spacing-v;
15
+  }
16
+
17
+  .input {
18
+    position: relative;
19
+    min-width: 100%;
20
+    margin-top: $item-spacing-v;
21
+    margin-left: 0;
22
+  }
23
+
24
+  input {
25
+    display:block;
26
+    width: 100%;
27
+    background: $color-gray-2;
28
+    border-radius: $border-radius;
29
+    padding: $item-spacing-v / 2 $item-spacing-h / 2;
30
+    border: none;
31
+    vertical-align: baseline;
32
+    color: $color-white;
33
+    font-size: inherit;
34
+    appearance: none;
35
+    min-height: $item-spacing-v + ($base-height + 0rem) ;
36
+
37
+    @include placeholder {
38
+      color: $color-gray-8;
39
+    }
40
+
41
+    &:focus {
42
+      @include placeholder {
43
+        color: $color-gray-6;
44
+      }
45
+      border: none;
46
+      box-shadow: none ;
47
+    }
48
+  }
49
+}
0 50
new file mode 100644
... ...
@@ -0,0 +1,68 @@
1
+@import "bourbon";
2
+@import "clay";
3
+
4
+.component-radio {
5
+
6
+  display: block;
7
+
8
+  .section & {
9
+    padding-right: $item-spacing-h / 2;
10
+  }
11
+
12
+  > .label {
13
+    display: block;
14
+    padding-bottom: $item-spacing-v / 2;
15
+  }
16
+
17
+  .radio-group {
18
+
19
+    padding-bottom: $item-spacing-v / 2;
20
+
21
+    label {
22
+      padding: $item-spacing-v / 2 $item-spacing-h / 2;
23
+    }
24
+
25
+    .label {
26
+      font-size: 0.9em;
27
+    }
28
+
29
+    input {
30
+      opacity: 0;
31
+      position: absolute;
32
+    }
33
+
34
+    i {
35
+      display: block;
36
+      position: relative;
37
+      border-radius: $base-height;
38
+      width: $base-height;
39
+      height: $base-height;
40
+      border: 2px solid $color-gray-7;
41
+      flex-shrink: 0;
42
+    }
43
+
44
+    input:checked + i {
45
+      border-color: $color-orange;
46
+      
47
+      &:after {
48
+        $padding: 15%;
49
+        content: '';
50
+        display: block;
51
+        position: absolute;
52
+        left: $padding;
53
+        right: $padding;
54
+        top: $padding;
55
+        bottom: $padding;
56
+        border-radius: $base-height;
57
+        background: $color-orange;
58
+
59
+      }
60
+    }
61
+
62
+  }
63
+
64
+  .description {
65
+    padding-left: 0;
66
+    padding-right: 0;
67
+  }
68
+}
0 69
new file mode 100644
... ...
@@ -0,0 +1,43 @@
1
+@import "bourbon";
2
+@import "clay";
3
+
4
+.component-select {
5
+
6
+  .section & {
7
+    padding: 0;
8
+  }
9
+
10
+  label {
11
+    position: relative;
12
+  }
13
+
14
+  .value {
15
+    $triangle-size: 0.85rem;
16
+    position: relative;
17
+    padding-right: $triangle-size + 0.25rem;
18
+    display: block;
19
+
20
+    &:after {
21
+      content: "";
22
+      position: absolute;
23
+      right: 0;
24
+      top: 50%;
25
+      margin-top: -0.1rem;
26
+      @include triangle($triangle-size, $color-orange, down);
27
+    }
28
+  }
29
+
30
+  select {
31
+    opacity: 0;
32
+    position: absolute;
33
+    display: block;
34
+    left: 0;
35
+    right: 0;
36
+    top: 0;
37
+    bottom: 0;
38
+    width: 100%;
39
+    border: none;
40
+    margin:0;
41
+    padding:0;
42
+  }
43
+}
0 44
new file mode 100644
... ...
@@ -0,0 +1,127 @@
1
+@import "clay";
2
+
3
+.component-slider {
4
+
5
+  .section & {
6
+    padding: 0;
7
+  }
8
+
9
+  label {
10
+    display: block;
11
+  }
12
+
13
+  .label-container {
14
+    display: flex;
15
+    align-items: center;
16
+    width: 100%;
17
+    padding-bottom: $item-spacing-v;
18
+  }
19
+
20
+  .label {
21
+    flex: 1;
22
+    min-width: 1rem;
23
+    display: block;
24
+    padding-right: $item-spacing-h;
25
+  }
26
+
27
+  .value-wrap {
28
+    display: block;
29
+    position: relative;
30
+  }
31
+
32
+  .value,
33
+  .value-pad {
34
+    display: block;
35
+    background: $color-gray-2;
36
+    border-radius: $border-radius;
37
+    padding: $item-spacing-v / 2 $item-spacing-h / 2;
38
+    border: none;
39
+    vertical-align: baseline;
40
+    color: $color-white;
41
+    text-align: right;
42
+    margin: 0;
43
+    min-width: 1rem;
44
+  }
45
+
46
+  .value-pad {
47
+    visibility: hidden;
48
+
49
+    &:before {
50
+      content: ' ';
51
+      display: inline-block;
52
+    }
53
+  }
54
+
55
+  .value {
56
+    max-width: 100%;
57
+    position: absolute;
58
+    left:0;
59
+    top:0
60
+  }
61
+
62
+  .input-wrap {
63
+    padding: 0 $item-spacing-h $item-spacing-v;
64
+  }
65
+
66
+  .input {
67
+    $track-height: rem(3px);
68
+
69
+    display: block;
70
+    position: relative;
71
+    min-width: 100%;
72
+    height: $base-height;
73
+    overflow: hidden;
74
+    margin-left: 0;
75
+
76
+    &:before {
77
+      content: '';
78
+      display: block;
79
+      position: absolute;
80
+      height: $track-height;
81
+      background: $color-gray-6;
82
+      width: 100%;
83
+      top: $base-height / 2 - $track-height / 2;
84
+    }
85
+
86
+    .slider {
87
+      display: block;
88
+      width: 100%;
89
+      appearance: none;
90
+      position: relative;
91
+      height: $base-height;
92
+      margin: 0;
93
+      background-color: transparent;
94
+
95
+      &:focus {
96
+        outline: none;
97
+      }
98
+
99
+      &::-webkit-slider-runnable-track {
100
+        border: none;
101
+        height: $base-height;
102
+        width: 100%;
103
+        background-color: transparent;
104
+      }
105
+
106
+      &::-webkit-slider-thumb {
107
+        appearance: none;
108
+        position: relative;
109
+        height: $base-height;
110
+        width: $base-height;
111
+        background-color: $color-orange;
112
+        border-radius: 50%;
113
+
114
+        &:before {
115
+          content: "";
116
+          position: absolute;
117
+          left: -1000px;
118
+          top: $base-height / 2 - $track-height / 2;
119
+          height: $track-height;
120
+          width: 1001px;
121
+          background: $color-orange;
122
+        }
123
+      }
124
+    }
125
+  }
126
+
127
+}
0 128
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+.component-submit {
2
+  text-align: center;
3
+}
0 4
new file mode 100644
... ...
@@ -0,0 +1,55 @@
1
+@import "clay";
2
+
3
+.component-toggle {
4
+
5
+  $slide-height: $base-height * 0.75;
6
+  $slide-width: $small-component-width;
7
+  $marker-diameter: $base-height;
8
+
9
+  .section & {
10
+    padding: 0;
11
+  }
12
+
13
+  input {
14
+    display: none; // @todo make sure this doesn't mess up interactivity on iOS
15
+  }
16
+
17
+  .graphic {
18
+    display: inline-block;
19
+    position: relative;
20
+
21
+    .slide {
22
+      display:block;
23
+      border-radius: $slide-height;
24
+      height: $slide-height;
25
+      width: $slide-width;
26
+      background: $color-gray-1;
27
+      transition: background-color 150ms linear;
28
+    }
29
+
30
+    .marker {
31
+      background: $color-gray-10;
32
+      width: $marker-diameter;
33
+      height: $marker-diameter;
34
+      border-radius: $marker-diameter;
35
+      position: absolute;
36
+      left: 0;
37
+      display: block;
38
+      top: ($marker-diameter - $slide-height) / 2 * -1;
39
+      transition: transform 150ms linear;
40
+      box-shadow: $box-shadow-small-components;
41
+    }
42
+  }
43
+
44
+  input:checked + .graphic {
45
+    .slide {
46
+      background: $color-orange-dark;
47
+    }
48
+
49
+    .marker {
50
+      background: $color-orange;
51
+      transform: translateX($slide-width - $marker-diameter);
52
+    }
53
+  }
54
+
55
+}
0 56
new file mode 100644
... ...
@@ -0,0 +1,35 @@
1
+@import "clay";
2
+
3
+button,
4
+.button {
5
+  @include font-pfdin(medium);
6
+  @include font-size(1);
7
+  text-transform: uppercase;
8
+  background-color: $color-gray-7;
9
+  border-radius: $border-radius;
10
+  border: none;
11
+  display: inline-block;
12
+
13
+  color: $color-white;
14
+  min-width: 12rem;
15
+  text-align: center;
16
+  margin: 0 auto $item-spacing-v;
17
+  padding: $button-padding;
18
+
19
+  @include tap-highlight($color-gray-8);
20
+
21
+  .platform-ios & {
22
+    padding: $button-padding-ios;
23
+  }
24
+
25
+  &.primary, &[type="submit"] {
26
+    background-color: $color-orange;
27
+
28
+    @include tap-highlight($color-red);
29
+  }
30
+}
31
+
32
+a.button {
33
+  text-decoration: none;
34
+  color: $color-white;
35
+}
0 36
new file mode 100644
... ...
@@ -0,0 +1,4 @@
1
+@import "clay/fonts";
2
+@import "clay/reset";
3
+@import "clay/base";
4
+@import "clay/elements/button";
0 5
new file mode 100644
... ...
@@ -0,0 +1,11 @@
1
+<div class="component component-button">
2
+  <button
3
+    type="button"
4
+    data-manipulator-target
5
+    class="{{primary ? 'primary' : ''}}"
6
+    {{each key: attributes}}{{key}}="{{this}}"{{/each}}
7
+  ></button>
8
+  {{if description}}
9
+    <div class="description">{{{description}}}</div>
10
+  {{/if}}
11
+</div>
0 12
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+<div class="component component-checkbox">
2
+  <span class="label">{{{label}}}</span>
3
+  <div class="checkbox-group">
4
+    {{each options}}
5
+      <label class="tap-highlight">
6
+        <span class="label">{{{this}}}</span>
7
+        <input type="checkbox" value="1" name="clay-{{clayId}}" />
8
+        <i></i>
9
+      </label>
10
+    {{/each}}
11
+  </div>
12
+  {{if description}}
13
+    <div class="description">{{{description}}}</div>
14
+  {{/if}}
15
+</div>
0 16
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+<div class="component component-color">
2
+  <label class="tap-highlight">
3
+    <input
4
+      data-manipulator-target
5
+      type="hidden"
6
+    />
7
+    <span class="label">{{{label}}}</span>
8
+    <span class="value"></span>
9
+  </label>
10
+  {{if description}}
11
+    <div class="description">{{{description}}}</div>
12
+  {{/if}}
13
+  <div class="picker-wrap">
14
+    <div class="picker">
15
+      <div class="color-box-wrap">
16
+        <div class="color-box-container"></div>
17
+      </div>
18
+    </div>
19
+  </div>
20
+</div>
0 21
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+<footer data-manipulator-target class="component component-footer"></footer>
0 2
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+<div class="component component-heading">
2
+  <h{{size}} data-manipulator-target></h{{size}}>
3
+</div>
0 4
new file mode 100644
... ...
@@ -0,0 +1,15 @@
1
+<div class="component component-input">
2
+  <label class="tap-highlight">
3
+    <span class="label">{{{label}}}</span>
4
+    <span class="input">
5
+      <input
6
+      data-manipulator-target
7
+        {{each key: attributes}}{{key}}="{{this}}"{{/each}}
8
+    />
9
+    </span>
10
+  </label>
11
+
12
+  {{if description}}
13
+    <div class="description">{{{description}}}</div>
14
+  {{/if}}
15
+</div>
0 16
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+<div class="component component-radio">
2
+  <span class="label">{{{label}}}</span>
3
+  <div class="radio-group">
4
+    {{each options}}
5
+      <label class="tap-highlight">
6
+        <span class="label">{{{this.label}}}</span>
7
+        <input
8
+          type="radio"
9
+          value="{{this.value}}"
10
+          name="clay-{{clayId}}"
11
+          {{each key: attributes}}{{key}}="{{this}}"{{/each}}
12
+        />
13
+        <i></i>
14
+      </label>
15
+    {{/each}}
16
+  </div>
17
+  {{if description}}
18
+    <div class="description">{{{description}}}</div>
19
+  {{/if}}
20
+</div>
0 21
new file mode 100644
... ...
@@ -0,0 +1,22 @@
1
+<div class="component component-select">
2
+  <label class="tap-highlight">
3
+    <span class="label">{{{label}}}</span>
4
+    <span class="value"></span>
5
+    <select data-manipulator-target {{each key: attributes}}{{key}}="{{this}}"{{/each}}>
6
+      {{each options}}
7
+        {{if Array.isArray(this.value)}}
8
+          <optgroup label="{{this.label}}">
9
+            {{each this.value}}
10
+              <option value="{{this.value}}" class="item-select-option">{{this.label}}</option>
11
+            {{/each}}
12
+          </optgroup>
13
+        {{else}}
14
+          <option value="{{this.value}}" class="item-select-option">{{this.label}}</option>
15
+        {{/if}}
16
+      {{/each}}
17
+    </select>
18
+  </label>
19
+  {{if description}}
20
+    <div class="description">{{{description}}}</div>
21
+  {{/if}}
22
+</div>
0 23
new file mode 100644
... ...
@@ -0,0 +1,25 @@
1
+<div class="component component-slider">
2
+  <label class="tap-highlight">
3
+    <span class="label-container">
4
+      <span class="label">{{{label}}}</span>
5
+      <span class="value-wrap">
6
+        <span class="value-pad"></span>
7
+        <input type="text" class="value" />
8
+      </span>
9
+    </span>
10
+    <span class="input">
11
+      <input
12
+        data-manipulator-target
13
+        class="slider"
14
+        type="range"
15
+        min="{{min}}"
16
+        max="{{max}}"
17
+        step="{{step}}"
18
+        {{each key: attributes}}{{key}}="{{this}}"{{/each}}
19
+      />
20
+    </span>
21
+</label>
22
+  {{if description}}
23
+    <div class="description">{{{description}}}</div>
24
+  {{/if}}
25
+</div>
0 26
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+<div class="component component-submit">
2
+  <button
3
+    data-manipulator-target
4
+    type="submit"
5
+    {{each key: attributes}}{{key}}="{{this}}"{{/each}}
6
+  ></button>
7
+</div>
0 8
new file mode 100644
... ...
@@ -0,0 +1,3 @@
1
+<div class="component component-text">
2
+  <p data-manipulator-target></p>
3
+</div>
0 4
new file mode 100644
... ...
@@ -0,0 +1,19 @@
1
+<div class="component component-toggle">
2
+  <label class="tap-highlight">
3
+    <span class="label">{{{label}}}</span>
4
+    <span class="input">
5
+      <input
6
+        data-manipulator-target
7
+        type="checkbox"
8
+        {{each key: attributes}}{{key}}="{{this}}"{{/each}}
9
+      />
10
+      <span class="graphic">
11
+        <span class="slide"></span>
12
+        <span class="marker"></span>
13
+      </span>
14
+    </span>
15
+  </label>
16
+  {{if description}}
17
+    <div class="description">{{{description}}}</div>
18
+  {{/if}}
19
+</div>
0 20
new file mode 100644
... ...
@@ -0,0 +1,37 @@
1
+{
2
+  "name": "agenda_sommeil",
3
+  "author": "MakeAwesomeHappen",
4
+  "version": "1.0.0",
5
+  "keywords": [
6
+    "pebble-app"
7
+  ],
8
+  "private": true,
9
+  "dependencies": {
10
+    "pebble-clay": "^1.0.0"
11
+  },
12
+  "pebble": {
13
+    "displayName": "agenda_sommeil",
14
+    "uuid": "a79298cf-ffc1-4901-bf39-cd00c482c6fb",
15
+    "sdkVersion": "3",
16
+    "enableMultiJS": true,
17
+    "targetPlatforms": [
18
+      "aplite"
19
+    ],
20
+    "watchapp": {
21
+      "watchface": false
22
+    },
23
+    "messageKeys": [
24
+      "gotosleep",
25
+      "awake",
26
+      "wakeup",
27
+      "status",
28
+      "JSReady"
29
+    ],
30
+    "capabilities": [
31
+      "configurable"
32
+    ],
33
+    "resources": {
34
+      "media": []
35
+    }
36
+  }
37
+}
0 38
new file mode 100644
... ...
@@ -0,0 +1,213 @@
1
+#include <pebble.h>
2
+
3
+static Window *s_window;
4
+static StatusBarLayer *s_status_text_layer;
5
+static TextLayer *s_upperleft_text_layer;
6
+static TextLayer *s_upperright_text_layer;
7
+static TextLayer *s_main_text_layer;
8
+static TextLayer *s_lowerleft_text_layer;
9
+static TextLayer *s_lowerright_text_layer;
10
+static TextLayer *s_lower_text_layer;
11
+
12
+// Largest expected inbox and outbox message sizes
13
+const uint32_t inbox_size = 150;
14
+const uint32_t outbox_size = 64;
15
+
16
+static uint32_t size ;
17
+static char s_status[4];
18
+static char s_msg[50];
19
+
20
+static bool s_js_ready;
21
+
22
+typedef enum {
23
+  status,
24
+  event
25
+} AppKey;
26
+
27
+
28
+static void send_message(char * msg){
29
+
30
+  // Declare the dictionary's iterator
31
+  DictionaryIterator *out_iter;
32
+
33
+  // Prepare the outbox buffer for this message
34
+  AppMessageResult result = app_message_outbox_begin(&out_iter);
35
+
36
+  if(result == APP_MSG_OK) {
37
+    dict_write_cstring(out_iter, status, msg);
38
+
39
+    // Send this message
40
+    result = app_message_outbox_send();
41
+    if(result != APP_MSG_OK) {
42
+      APP_LOG(APP_LOG_LEVEL_ERROR, "Error sending the outbox: %d", (int)result);
43
+    }
44
+  } else {
45
+    // The outbox cannot be used right now
46
+    APP_LOG(APP_LOG_LEVEL_ERROR, "Error preparing the outbox: %d", (int)result);
47
+  }
48
+}
49
+
50
+static void prv_up_click_handler(ClickRecognizerRef recognizer, void *context) {
51
+  text_layer_set_text(s_main_text_layer, "wakeup");
52
+  send_message("wakeup");
53
+}
54
+static void prv_select_click_handler(ClickRecognizerRef recognizer, void *context) {
55
+  text_layer_set_text(s_main_text_layer, "awake");
56
+  send_message("awake");
57
+}
58
+static void prv_down_click_handler(ClickRecognizerRef recognizer, void *context) {
59
+  text_layer_set_text(s_main_text_layer, "gotosleep");
60
+  send_message("gotosleep");
61
+}
62
+
63
+static void prv_click_config_provider(void *context) {
64
+  window_single_click_subscribe(BUTTON_ID_SELECT, prv_select_click_handler);
65
+  window_single_click_subscribe(BUTTON_ID_UP, prv_up_click_handler);
66
+  window_single_click_subscribe(BUTTON_ID_DOWN, prv_down_click_handler);
67
+}
68
+
69
+static void prv_window_load(Window *window) {
70
+  Layer *window_layer = window_get_root_layer(window);
71
+  GRect bounds = layer_get_bounds(window_layer);
72
+
73
+  s_main_text_layer = text_layer_create(GRect(0, 72, bounds.size.w, 20));
74
+  text_layer_set_text(s_main_text_layer, "Press a button");
75
+  text_layer_set_text_alignment(s_main_text_layer, GTextAlignmentCenter);
76
+  layer_add_child(window_layer, text_layer_get_layer(s_main_text_layer));
77
+}
78
+
79
+static void prv_window_unload(Window *window) {
80
+  text_layer_destroy(s_main_text_layer);
81
+}
82
+
83
+void comm_is_ready() {
84
+
85
+  // set the text
86
+  text_layer_set_text(s_main_text_layer, "ready");
87
+  /*text_layer_set_text(s_upperleft_text_layer, "-");
88
+  text_layer_set_text(s_upperleft_text_layer, "-");
89
+  text_layer_set_text(s_main_text_layer, "Ready");
90
+  text_layer_set_text(s_lowerleft_text_layer, "-");
91
+  text_layer_set_text(s_lowerright_text_layer, "-");
92
+  text_layer_set_text(s_lower_text_layer, "--:--:--");*/
93
+
94
+}
95
+
96
+static void inbox_received_callback(DictionaryIterator *iter, void *context) {
97
+  // A new message has been successfully received
98
+  APP_LOG(APP_LOG_LEVEL_INFO, "New message! ");
99
+
100
+  size = dict_size(iter);
101
+
102
+  // JS readiness
103
+  Tuple *ready_tuple = dict_find(iter, MESSAGE_KEY_JSReady);
104
+
105
+  if(ready_tuple){
106
+    //Pebblekit JS is ready ! Safe to send messages
107
+    s_js_ready = true;
108
+    comm_is_ready();
109
+    //APP_LOG(APP_LOG_LEVEL_DEBUG, "received jsready message on watch... ");
110
+  }
111
+  
112
+
113
+  // Read status returns
114
+  Tuple *status_tuple = dict_find(iter, MESSAGE_KEY_status);
115
+
116
+  if(status_tuple) {
117
+    memset(s_status,'\0',sizeof(s_status));
118
+    strncpy(s_status, status_tuple->value->cstring, 4);
119
+    //APP_LOG(APP_LOG_LEVEL_DEBUG, "status message received : %s",s_status);
120
+
121
+    // DEBUG concatenate all data received
122
+    /*
123
+      memset(s_msg,'\0',sizeof(s_msg));
124
+      strncpy(s_msg, "Acc. ",5);
125
+      strcat(s_msg, s_accuracy);
126
+      strcat(s_msg, "    Alt. ");
127
+      strcat(s_msg, s_altitude);
128
+      strcat(s_msg, "\n Max. ");
129
+      strcat(s_msg, s_max_speed);
130
+      strcat(s_msg, "\n Lat. ");
131
+      strcat(s_msg, s_latitude);
132
+      strcat(s_msg, "\n Long. ");
133
+      strcat(s_msg, s_longitude);
134
+      strcat(s_msg, "\n Time. ");
135
+      strcat(s_msg, s_timestamp);
136
+    */
137
+
138
+    //APP_LOG(APP_LOG_LEVEL_DEBUG, "to display : %s ",s_msg);
139
+    if(strcmp(s_status, "L200")==0){
140
+      /*text_layer_set_text(s_upperleft_text_layer, s_altitude);
141
+      text_layer_set_text(s_upperright_text_layer, s_distance);
142
+      text_layer_set_text(s_main_text_layer, s_speed);
143
+      text_layer_set_text(s_lowerleft_text_layer, s_avg_speed);
144
+      text_layer_set_text(s_lowerright_text_layer, s_max_speed);
145
+      text_layer_set_text(s_lower_text_layer, s_duration);*/
146
+    }else if(strcmp(s_status, "S200")==0){
147
+      //text_layer_set_text(s_lower_text_layer, "upload OK");
148
+      vibes_short_pulse();
149
+    }else if(strcmp(s_status, "S401")==0){
150
+      //text_layer_set_text(s_lower_text_layer, "auth err, retrying");
151
+    }else{
152
+      //text_layer_set_text(s_lower_text_layer, s_status);
153
+      vibes_double_pulse();
154
+    }
155
+  }else{
156
+    //APP_LOG(APP_LOG_LEVEL_DEBUG, "not status message... ");
157
+  }
158
+
159
+}
160
+
161
+
162
+static void inbox_dropped_callback(AppMessageResult reason, void *context) {
163
+  // A message was received, but had to be dropped
164
+  APP_LOG(APP_LOG_LEVEL_ERROR, "Message dropped. Reason: %d", (int)reason);
165
+}
166
+
167
+static void outbox_sent_callback(DictionaryIterator *iter, void *context) {
168
+  // The message just sent has been successfully delivered
169
+  APP_LOG(APP_LOG_LEVEL_INFO, "Message sent. ");
170
+}
171
+
172
+static void outbox_failed_callback(DictionaryIterator *iter, AppMessageResult reason, void *context) {
173
+  // The message just sent failed to be delivered
174
+  APP_LOG(APP_LOG_LEVEL_ERROR, "Message send failed. Reason: %d", (int)reason);
175
+}
176
+
177
+static void prv_init(void) {
178
+  
179
+  // Open AppMessage
180
+  app_message_open(inbox_size, outbox_size);
181
+
182
+  // Register to be notified about inbox received events
183
+  app_message_register_inbox_received(inbox_received_callback);
184
+  // Register to be notified about inbox dropped events
185
+  app_message_register_inbox_dropped(inbox_dropped_callback);
186
+  // Register to be notified about outbox sent events
187
+  app_message_register_outbox_sent(outbox_sent_callback);
188
+  // Register to be notified about outbox failed events
189
+  app_message_register_outbox_failed(outbox_failed_callback);
190
+
191
+
192
+  s_window = window_create();
193
+  window_set_click_config_provider(s_window, prv_click_config_provider);
194
+  window_set_window_handlers(s_window, (WindowHandlers) {
195
+    .load = prv_window_load,
196
+    .unload = prv_window_unload,
197
+  });
198
+  const bool animated = true;
199
+  window_stack_push(s_window, animated);
200
+}
201
+
202
+static void prv_deinit(void) {
203
+  window_destroy(s_window);
204
+}
205
+
206
+int main(void) {
207
+  prv_init();
208
+
209
+  //APP_LOG(APP_LOG_LEVEL_DEBUG, "Done initializing, pushed window: %p", s_window);
210
+
211
+  app_event_loop();
212
+  prv_deinit();
213
+}
0 214
new file mode 100644
... ...
@@ -0,0 +1,32 @@
1
+module.exports = [
2
+    {
3
+        "type": "section",
4
+        "items": [{
5
+                "type": "heading",
6
+                "defaultValue": "Send event to PHP server"
7
+            },
8
+            {
9
+                "type": "input",
10
+                "messageKey": "web_url",
11
+                "label": "Full URL of server receiving the event (https://domain/path/endpoint.php)"
12
+            }
13
+        ]
14
+    },{
15
+        "type": "section",
16
+        "items": [{
17
+                "type": "heading",
18
+                "defaultValue": "User"
19
+            },
20
+            {
21
+                "type": "input",
22
+                "messageKey": "username",
23
+                "label": "this is your name to label data"
24
+            }
25
+        ]
26
+    },
27
+    {
28
+        "type": "submit",
29
+        "id": "submitButton",
30
+        "defaultValue": "Save"
31
+    }
32
+];
0 33
\ No newline at end of file
1 34
new file mode 100644
... ...
@@ -0,0 +1,119 @@
1
+var Clay = require('pebble-clay');
2
+var clayConfig = require('./config');
3
+var clay = new Clay(clayConfig, null, { autoHandleEvents: false });
4
+var messageKeys = require('message_keys');
5
+
6
+var message;
7
+var locate_me
8
+
9
+var firstlocationInterval = false;
10
+var locationInterval = false;
11
+var instantLocationInterval = false;
12
+
13
+
14
+Pebble.addEventListener('showConfiguration', function(e) {
15
+    clay.config = clayConfig;
16
+    console.log("Clay config is showing...")
17
+    Pebble.openURL(clay.generateUrl());
18
+});
19
+
20
+Pebble.addEventListener('webviewclosed', function(t) {
21
+    console.log("Clayview closed")
22
+    if (!t || t.response) {
23
+        console.log("Clay config is submitted : " + t.response)
24
+        try {
25
+            if (data = JSON.parse(t.response), data.code && data.scope == "read,activity:write") {
26
+                if (data.state == "agenda_sommeil" && data.scope == "read,activity:write") {
27
+                    getTokens(data.code);
28
+                } else {
29
+                    console.log("Error on response returned : scope is " + grantcode.scope + " and state is " + grantcode.state);
30
+                }
31
+            } else {
32
+                clay.getSettings(t.response);
33
+                console.log("Clay settings in Localstorage looks like " + localStorage.getItem("clay-settings"));
34
+            }
35
+        } catch (t) {
36
+            console.log("Oauth parsing error, continue on saving clay settings");
37
+            clay.getSettings(t.response);
38
+            var claysettings = JSON.parse(localStorage.getItem('clay-settings'))
39
+            claysettings.strava_enabled = false;
40
+            localStorage.setItem("clay-settings", JSON.stringify("claysettings"));
41
+            console.log("Clay settings in Localstorage looks like " + localStorage.getItem("clay-settings"));
42
+        }
43
+
44
+    }
45
+});
46
+
47
+function PostToWeb(event) {
48
+    console.log(localStorage.getItem('clay-settings'))
49
+    var url = JSON.parse(localStorage.getItem('clay-settings')).web_url + "?event="+event+"&user="+JSON.parse(localStorage.getItem('clay-settings')).username;
50
+    var xhr = new XMLHttpRequest();
51
+    xhr.timeout = 10000; // time in milliseconds
52
+    xhr.open("GET", url, false);
53
+    //console.log('------ CSV / xhr opened')
54
+    xhr.onload = function() {
55
+        //console.log('------xhr onloaded')
56
+        if (xhr.readyState === 4) {
57
+            //console.log('------xhr request returned with ' + xhr.status);
58
+            //console.log(this.responseText);
59
+            //localStorage.setItem("custom_uploaded", true);
60
+            if (xhr.status == 200) {
61
+                //console.log('--> HTTP 200');
62
+                return true;
63
+            } else {
64
+                //console.log('--> HTTP ' + xhr.status);
65
+                return false;
66
+            }
67
+        }
68
+    };
69
+
70
+  //send xhr without body (GET)
71
+  xhr.send();
72
+}
73
+
74
+function init() {
75
+    //init vars
76
+    // get vars from clay: 
77
+    //var su = localStorage.getItem("strava_uploaded")
78
+    
79
+    //debug : 
80
+    //console.log("Locate_me = " + locate_me);
81
+
82
+    //actions:
83
+    //PostToWeb()
84
+
85
+
86
+    //set var in clay :
87
+    //localStorage.setItem("strava_uploaded", 0);
88
+
89
+}
90
+
91
+// Get JS readiness events
92
+Pebble.addEventListener('ready', function(e) {
93
+    console.log('PebbleKit JS is ready');
94
+    // Update Watch on this
95
+    Pebble.sendAppMessage({ 'JSReady': 1 });
96
+
97
+    //init();
98
+});
99
+
100
+// Get AppMessage events
101
+Pebble.addEventListener('appmessage', function (e) {
102
+    // Get the dictionary from the message
103
+    var dict = e.payload;
104
+    //console.log(dict[0].toString());
105
+    switch (dict[0]) {
106
+        case 'gotosleep':
107
+            PostToWeb("gotosleep")
108
+            break;
109
+        case 'awake':   
110
+            PostToWeb("awake")
111
+            break;
112
+        case 'wakeup':   
113
+            PostToWeb("wakeup")  
114
+            break;
115
+      default:
116
+        console.log('Sorry. I don\'t understand your request :' + dict[0]);
117
+    }
118
+  
119
+  });
0 120
\ No newline at end of file