Introduction
Welcome to the Usabilla API documentation. Here you will find a detailed guide on how to access the data related to your customers feedback.
You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right. On top of this, we've also included our client repositories we have on GitHub.
Usabilla maintains the following client libraries:
- Usabilla API PHP Client
- Usabilla API Python Client
- Usabilla API Go Client
- Usabilla API Node.js Client
Client libraries by third parties:
- Usabilla API Ruby On Rails Client - maintained by Jon Molinaro (CareerBuilder.com)
- Usabilla API Shell Script - maintained by Alexander Vellekoop (Aegon.nl)
If you wrote a public client library that would be beneficial to fellow coders, we would love to hear about it and include it in our documentation, please send us a link to your project repository.
If you prefer to use a language we do not provide a client library for you can continue to the next section to see how our authentication method works. Please contact support if you need help calling our API.
Authentication
The authentication code for each language can be found under the respective GitHub pages:
GitHub - PHP Client
GitHub - Python Client
GitHub - Go Client
GitHub - Node.js Client
GitHub - Ruby On Rails Client
GitHub - Shell Script
The credentials consist in an access and a secret key used for authentication purposes. You can acquire the credentials by logging into your Usabilla account and access the following link or navigating to the settings menu under the tab Usabilla API. If you're new to the Usabilla API then we recommend you to read through our support article on Getting Started with the Usabilla Public API. Our API authentication system is inspired by the AWS version 4 request signing process.
1. Create a Canonical Request
To begin the signing process, you create a string that includes information from your request in a standardized (canonical) format. This step will allow you to create a canonical request string which will be used by our servers to verify the signed request.
Follow the steps here to create a canonical version of the request. Otherwise, your version and the version calculated by our servers won't match, and the request will be denied.
The following example shows the pseudocode to create a canonical request:
CanonicalRequest =
HTTPRequestMethod + '\n' +
CanonicalURI + '\n' +
CanonicalQueryString + '\n' +
CanonicalHeaders + '\n' +
SignedHeaders + '\n' +
HexEncode(Hash(RequestPayload))
Example request
To show you how to construct the canonical form of an HTTP request, we'll use the following example request. The original request might look like this as it is sent from the client to our servers, except that this example does not include the signing information yet.
GET https://data.usabilla.com/ HTTP/1.1
Host: data.usabilla.com
Date: 20150830T123600Z
To create a canonical request, concatenate the following components from each step into a single string:
Start with the GET, HTTP request method written in upper case, followed by a newline character. Example request method:
GET
Add the canonical URI parameter, followed by a newline character.
If the absolute path is empty, use a forward slash (/). In the example request, nothing follows the host in the URI, so the absolute path is empty.
Example canonical URI:
/button
Add the canonical query string, followed by a newline character.
If the request does not include a query string, use an empty string (essentially, a blank line). The example request does not contain a query string:
Example canonical query string:
?limit=1&since=123456789
To construct the canonical query string, complete the following steps:
a. URI-encode each parameter name and value according to the following rules:
*Do not URL-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen ( - ), underscore ( _ ), period ( . ), and tilde ( ~ ).
*Percent-encode all other characters with %XY, where X and Y are hexadecimal characters (0-9 and uppercase A-F).
b. Sort the encoded parameter names by character code.
c. Build the canonical query string by starting with the first parameter name in the sorted list.
d. For each parameter, append the URI-encoded parameter name, followed by the character '=' (ASCII code 61), followed by the URI-encoded parameter value. Use an empty string for parameters that have no value.
e. Append the character '&' (ASCII code 38) after each parameter value except for the last value in the list.
Example authentication parameters in a query string:
The following example shows a query string that includes authentication information.
Algorithm=USBL1-HMAC-SHA256&
Version=2010-05-08&
Credential=AKIAIOSFODNN7EXAMPLE%2F20150112%2Fusbl1_request&
Date=20150112T135139Z&
SignedHeaders=date%3BhostAdd the canonical headers, followed by a newline character. The canonical headers consist of a list of all the HTTP headers. The required headers are host and date.
Example canonical headers:
host:data.usabilla.com\n
date:20150111T003735Z\n
To create the canonical headers list, convert all header names to lowercase and trim excess white space characters out of the header values. When you trim, remove leading spaces and trailing spaces, and convert sequential spaces in the value to a single space. However, do not remove extra spaces from any values that are inside quotation marks.
The following pseudocode describes how to construct the canonical list of headers:
CanonicalHeaders =
CanonicalHeadersEntry0 + CanonicalHeadersEntry1 + ... +
CanonicalHeadersEntryN
CanonicalHeadersEntry =
Lowercase(HeaderName) + ':' + Trimall(HeaderValue) + '\n'Lowercase represents a function that converts all characters to lowercase. The Trimall function removes excess white space before and after values and from inside non-quoted strings, per RFC 2616 Section 4.2.
Build the canonical headers list by iterating through the collection of header names and sorting the headers lowercase character code. Construct each header by using the following rules:
Append the lowercase header name followed by a colon.
Append a comma-separated list of values for that header. If there are duplicate headers, the values are comma-separated. Do not sort the values in headers that have multiple values.
Append a new line ('\n').
The following two samples compare a more complex set of headers with their canonical form:
Example original headers:
host:data.usabilla.com\n
date:20150111T003735Z\nExample canonical form:
date:20150111T003735Z\n
host:data.usabilla.com\nTo create the signed headers list, convert all header names to lowercase, sort them by character code, and use a semicolon to separate the header names. The following pseudocode describes how to construct a list of signed headers. LOWERCASE represents a function that converts all characters to lowercase.
SignedHeaders =
Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ";"
+ ... + Lowercase(HeaderNameN)Build the signed headers list by iterating through the collection of header names, sorted by lowercase character code. For each header name except the last, append a semicolon (';') to the header name to separate it from the following header name.
Only the host and date headers are required. Optionally if the users have added additional headers to the CanonicalHeaders these will also be required. Note: Certain API calls require additional headers to be present in the signed headers list.
Example request: Signed headers
host;date
Use the hash (digest) function SHA256 and create a hashed value from the RequestPayload in the body of the HTTP or HTTPS request. Since none of the current API calls support a request body the RequestPayload must always be the empty string. Therefore the RequestPayload will always be the hexadecimal SHA-256 hash of an empty string.
HashedPayload = Lowercase(HexEncode(Hash(requestPayload)))
Example request: RequestPayload
empty string
Example request: Hashed RequestPayload
The following example shows the result of using SHA-256 to hash the example RequestPayload.
3511de7e95d28ecd39e9513b642aee07e54f4941150d8df8bf94b328ef7e55e2
To construct the finished canonical request, combine all the components from each step as a single string. As noted, each component ends with a newline character. If you follow the canonical request pseudocode explained earlier, the resulting canonical request is shown in the following example:
Example canonical request:
GET
/live/website/button
date:Mon, 12 Jan 2015 13:57:54 GMT
host:data.usabilla.dev
date;host
3511de7e95d28ecd39e9513b642aee07e54f4941150d8df8bf94b328ef7e55e2Create a digest (hash) of the canonical request by using the same algorithm that you used to hash the RequestPayload. The hashed canonical request must be represented as a string of lowercase hexademical characters.
Example hashed canonical request:
3511de7e95d28ecd39e9513b642aee07e54f4941150d8df8bf94b328ef7e55e2
2. Create a String to Sign
The string to sign includes meta information about your request and about the canonical request. To create the string to sign, concatenate the algorithm, date, credential scope, and the digest of the canonical request, as shown in the following pseudocode:
Structure of the String to Sign:
StringToSign =
Algorithm +
RequestDate +
CredentialScope +
HashedCanonicalRequest
Example HTTPS request:
GET
/live/website/button
date:Mon, 12 Jan 2015 13:57:54 GMT
host:data.usabilla.dev
date;host
3511de7e95d28ecd39e9513b642aee07e54f4941150d8df8bf94b328ef7e55e2
To create the string to sign:
Start with the algorithm designation, followed by a newline character. This value is the hashing algorithm that you're using to calculate the digests in the canonical request.
USBL1-HMAC-SHA256\n
Append the request date value, followed by a newline character. The date is specified by using the ISO8601 Basic format via the Date header in the YYYYMMDD'T'HHMMSS'Z' format. This value must match the value you used in any previous steps.
20150112T135139Z\n
Append the credential scope value, followed by a newline character. This value is a string that includes the date and termination string ("usbl1_request") in lowercase characters.
20150112/usbl1_request\n
The date must be in the YYYYMMDD format. Note that the date does not include a time value.
Append the hash of the canonical request that you created in task 1; Create a canonical Request. This value is not followed by a newline character. The hashed canonical request must be lowercase base-16 encoded, as defined by Section 8 of RFC 4648.
daf6b02d8ae6809bf3b2445c480c1ee6038da1a19a2bd5ad21b7a30acd0fdec2
Example string to sign:
USBL1-HMAC-SHA256
20150112T135139Z
20150112/usbl1_request
daf6b02d8ae6809bf3b2445c480c1ee6038da1a19a2bd5ad21b7a30acd0fdec2
3. Calculate the Signature
Before you calculate a signature, you derive a signing key from your Usabilla secret key.
To calculate a signature:
Derive your signing key. To do this, you use your secret access key to create a series of hash-based message authentication codes (HMACs) as shown by the following pseudocode, where HMAC(key, data) represents an HMAC-SHA256 function that returns output in binary format. The result of each hash function becomes input for the next one.
Pseudocode for deriving a signing key:
kSecret = Your Usabilla Secret Key
kDate = HMAC("USBL1" + kSecret, Date)
kSigning = HMAC(kDate, "usbl1_request")Use the digest for the key derivation. Most languages have functions to compute either a binary format hash, commonly called a digest, or a hex-encoded hash, called a hexdigest. The key derivation requires that you use a digest.
Example inputs:
HMAC(HMAC("USBL1" + kSecret,"20110909"),"usbl1_request")
The following example shows the derived signing key that results from this sequence of HMAC hash operations, using the inputs shown in the previous example. This representation shows the digit representation of each byte in the binary derived key.
Example signing key:
152 241 216 137 254 196 244 66 26 220 82 43 171 12 225 248 46 105 41 194 98 237 21 229 169 76 144 239 209 227 176 231
Calculate the signature. To do this, use the signing key that you derived and the string to sign as inputs to the keyed hash function. After you've calculated the signature as a digest, convert the binary value to a hexadecimal representation.
Pseudocode for calculating the signature:
signature = HexEncode(HMAC(derived-signing-key, string-to-sign))
Note: Make sure you specify the HMAC parameters in the correct order for the programming language you are using. This example shows the key as the first parameter and the data (message) as the second parameter, but the function that you use might specify the key and data in a different order.
Example signature:
ced6826de92d2bdeed8f846f0bf508e8559e98e4b0199114b84c54174deb456c
4. Signing the Request
After you have calculated the signature, add it to the Authorization header of your request.
The following pseudocode shows the construction of the Authorization header:
Authorization: algorithm
Credential=access key ID/credential scope,
SignedHeaders=SignedHeaders,
Signature=signature
The following example shows a finished Authorization header:
Authorization: USBL1-HMAC-SHA256
Credential=AccessKey/20130524/usbl1_request,
SignedHeaders=date;host;user-agent,
Signature=fe5f80f77d5fa3beca038a248ff027d0
445342fe2855ddc963176630326f1024
Note the following:
There is a space between the algorithm and Credential, not a comma. On the other hand, the SignedHeaders and Signature values are separated from the earlier values using a comma.
The Credential value starts with the access key, which is prefixed with a slash (/) onto the credential scope value that you calculated earlier. In contrast, the secret access key is used to derive the signing key for the signature, but is not included in the signing information that's sent in the request.
Request URL structure
This section covers the resources that can be requested.
https://data.usabilla.com/live/<product-name>/<resource-type>/<id>/<nested-resource>?params
Parameters
| Field | Type | Description |
|---|---|---|
| id | String | The id of the resource |
| params | String | Query URL parameters |
Success 200
Example Success 200 Response
HTTP/1.1 200 OK
{
"items": [
...
],
"count": 0,
"hasMore": false,
"lastTimestamp":<PHONE_NUMBER>645
}
| Field | Type | Description |
|---|---|---|
| items | Array | An array containing items of the requested resource type |
| count | Integer | The number of items returned |
| hasMore | Integer | A flag that indicates whether more items can be requested |
| lastTimestamp | Timestamp | The timestamp of the last item in the items array. Can be used to request more items when hasMore is true |
Errors
403
HTTP/1.1 403 Bad Request
{
"error": "Invalid client key"
}
| Field | Description |
|---|---|
| DateError | Date is not valid |
| SignatureDoesNotMatch | The signature does not match the content |
| SignatureMissing | Request doesn't have a signature |
| TokenMismatch | Token not found |
| HostError | Requested host is not valid |
404
| Field | Description |
|---|---|
| NotFound | Invalid URL |
429
| Field | Description |
|---|---|
| TooManyRequests | Request limit reached, please contact your Usabilla account manager |
| RateLimitExceeded | Request rate too high |
500
HTTP/1.1 500 Server Error
{
"error": "The server has encountered an error."
}
| Field | Description |
|---|---|
| DatabaseError | Account Provider not available |
| WrongCodec | Signed algorithm is not valid |
| QueryFailed | Could not query |
| AuthenticationFailed | Please re-authenticate |
Usabilla for Websites
Feedback Button
This section covers the resources that can be requested regarding Usabilla's Feedback buttons. The feedback button is a button widget that is shown on your website at a visible but non-obtrusive location to enable visitors to leave feedback on their experience.
The authorization code for each programming language can be found under the corresponding GitHub page we have for each client library.
Get Buttons
/* eslint-disable no-console */
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all buttons for this account.
usabilla.websites.buttons
.get()
.then(buttons => {
const button = buttons[0];
if (!button) {
return;
}
})
.catch(reason => {
// If the usabilla call fails, we want to see the error message
console.error(reason);
});
import usabilla as ub
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Get all buttons for this account
buttons = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_WEBSITES,api.RESOURCE_BUTTON)
# Print first button
first_button = buttons['items'][0]
print first_button['name']
// Under construction
package main
import (
"os"
"fmt"
"github.com/usabilla/api-go"
)
func main() {
key := os.Getenv("USABILLA_API_KEY")
secret := os.Getenv("USABILLA_API_SECRET")
// Pass the key and secret which should be defined as ENV vars
usabilla := usabilla.New(key, secret, nil)
resource := usabilla.Buttons()
// Get the first ten buttons
params := map[string]string{"limit": "10"}
buttons, _ := resource.Get(params)
}
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "8d73568ac2be",
"name": "My website feedback button"
}
HTTPS Request
https://data.usabilla.com/live/websites/button
This request returns all your feedback buttons in JSON format as shown to the right.
Request example
https://data.usabilla.com/live/websites/button
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier for a button. 12 characters long. |
| name | String | The name of the button given when created. Can be updated in the button setup page. |
Get Feedback Items
/* eslint-disable no-console */
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Use a button id to get feedback for a specific button.
let buttonFeedbackQuery = {
id: button.id,
params: {
limit: 10
}
};
usabilla.websites.buttons.feedback
.get(buttonFeedbackQuery)
.then(feedback => {
console.log('# button feedback', feedback.length);
})
.catch(reason => {
console.error(reason);
});
})
.catch(reason => {
// If the usabilla call fails, we want to see the error message
console.error(reason);
});
import usabilla as ub
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Get the feedback items from a specific button
feedback_items = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_WEBSITES, api.RESOURCE_FEEDBACK, 'button_id', iterate=True)
print len([item for item in feedback_items])
require 'vendor/autoload.php';
use Usabilla\API\Client\UsabillaClient;
// Creates a new Usabilla client.
$client = new UsabillaClient('ACCESS_KEY', 'SECRET_KEY');
// Specify the parameters as mentioned in the service description.
$params = ['id' => 'BUTTON_ID', 'limit' => 5];
// Gets the command.
$command = $client->getCommand('GetWebsiteFeedbackItems', $params);
// Executes the command.
$response = $client->execute($command);
// Prints the received response.
print_r($response);
package main
import (
"os"
"fmt"
"github.com/usabilla/api-go"
)
func main() {
key := os.Getenv("USABILLA_API_KEY")
secret := os.Getenv("USABILLA_API_SECRET")
// Pass the key and secret which should be defined as ENV vars
usabilla := usabilla.New(key, secret, nil)
resource := usabilla.Buttons()
// Get the first ten buttons
params := map[string]string{"limit": "10"}
buttons, _ := resource.Get(params)
// Print all feedback items for each button
for _, button := range buttons.Items {
feedback, _ := resource.Feedback().Get(button.ID, nil)
fmt.Printf("Feedback for button: %s\n%v\n", button.ID, feedback.Items)
}
}
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"buttonId": "07f5ec0c3b93",
"comment": "asd",
"custom": null,
"date": "2015-04-28T14:48:39.289Z",
"email": "",
"id": "553f9dc7d350221532dfa715",
"image": "",
"labels": [],
"location": "Netherlands",
"nps": 10,
"publicUrl": "https://www.usabilla.com/feedback/item/538ce51b93804a7f568324fbef81e6559743ba7e",
"rating": 5,
"tags": [],
"url": "https://staging.usabilla.com/",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36"
}
After a visitor leaves feedback on a button it becomes a feedback item that consists of several data fields.
HTTPS Request
https://data.usabilla.com/live/websites/button/<id>/feedback
Request example
https://data.usabilla.com/live/websites/button/8d73568ac2be/feedback/?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| id | String | The button id. If you wish to get all available feedback items use * (asterisk) as value. |
| limit | Integer | Optional URL query parameter that limits the number of retrieved results between 1 and 100. Default value is 100. |
| since | Timestamp | [Optional] UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier of the feedback item. |
| userAgent | String | Information about the browser's user-agent. |
| comment | String | Comment given by the user in the feedback form. |
| commentTranslated | String | The translated version of the comment given by the user. |
| commentTranslatedFrom | String | The language from which the translation was made. |
| location | String | String containing geographical information about the location of the user based on the user's ip address. |
| date | Date | The creation date of the feedback item, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| custom | Map | Custom variables that have been assigned in the button setup page. |
| String | Optional field that the user fills in in case he wishes to be contacted. | |
| image | String | The screenshot of the item that has been selected to give feedback for. |
| labels | Map | An array of labels that have been assigned to the feedback item. |
| nps | Integer | The Net Promoter Score given by the user (0-10). |
| publicUrl | String | When the owner of the button has publicized the feedback item it becomes publicly accesible through this URL. |
| rating | Integer | Rating given by the user (0-5). |
| buttonId | String | The source button of the feedback item. |
| tags | Array | An array of tags assigned to the feedback item. |
| url | Integer | The link through which the source button can be accessed in the backend. |
Campaigns
This section covers how to retrieve data for Usabilla Campaigns. These surveys are aimed towards web users with specific targeting options set up. The survey will trigger without the users intent, actively asking for feedback.
Get Campaigns
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all campaigns
usabilla.websites.campaigns
.get()
.then(campaigns => {
const campaign = campaigns[0];
console.log('# campaigns', campaigns.length);
if (!campaign) {
return;
}
import usabilla as ub
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Get all campaigns
campaigns = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_WEBSITES, api.RESOURCE_CAMPAIGN)
first_campaign = campaigns['items'][0]
print first_campaign['name']
//Under construction
//Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "5499612ec4698839368b4573",
"date": "2014-01-15T19:48:06.003Z",
"buttonId": "8d73568ac2be",
"analyticsId": "901f1d832a55",
"status": "active",
"name": "My campaign",
"type": "boost",
"url": ""
}
HTTPS Request
https://data.usabilla.com/live/websites/campaign
This request returns a list of your Usabilla for Websites Campaigns.
Request example
https://data.usabilla.com/live/websites/campaign?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| limit | Integer | Optional. URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional. UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier for a campaign. |
| date | Date | The creation date of the campaign, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| buttonId | String | The source button that triggers the campaign. |
| analyticsId | String | Analytics ID. |
| status | String | The status of the campaign. Possible values are created , active , paused and finished . |
| name | String | The name of the campaign given when created. Can be updated in the campaign setup page. |
| type | String | The type of the campaign. |
| url | String | The url of the campaign when the campaign is of type Survey , empty otherwise. |
Get Campaign Results
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Specify a campaign id
let campaignQuery = {
id: campaign.id
};
// Get the responses from a campaign with the specific id
usabilla.websites.campaigns.results
.get(campaignQuery)
.then(responses => {
console.log('# web campaign responses', responses.length);
})
.catch(reason => {
console.error(reason);
});
import usabilla as ub
if __name__ == '__main__':
# Get the responses of a specific campaign
responses = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_WEBSITES, api.RESOURCE_CAMPAIGN_RESULT, <CAMPAIGN_ID>, iterate=True)
print len([item for item in responses])
//Under construction
//Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "549972d5c469885e548b4570",
"campaignId": "5499612ec4698839368b4573",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"location": "Amsterdam, Netherlands",
"date": "2014-01-15T19:48:06.003Z",
"customData": {
"form_name": "form1"
},
"data": {
"text": "test"
},
"time": 5000,
"url": "https://usabilla.com"
}
HTTPS Request
https://data.usabilla.com/live/websites/campaign/<id>/results
This request returns the responses of a campaign with a specific id.
Request example
https://data.usabilla.com/live/websites/campaign/5499612ec4698839368b4573/results?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| id | String | The campaign id. Use * (asterisk) to request feedback of all campaigns. |
| limit | Integer | Optional. URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional. UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier for a campaign result. |
| date | Date | The creation date of the campaign result item, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| campaignId | String | Unique identifier for the campaign it belongs to. |
| userAgent | String | Information about the browser user agent. |
| url | String | Origin URL where the campaign result was registered. |
| customData | Map | Custom variables that have been assigned to the campaign result. |
| data | Array | An array containing the values of the campaign form fields. |
| time | Integer | The amount of time the user has taken to complete the survey. Expressed in miliseconds. |
| location | String | String containing geographical information about the location of the user based on the user's IP address. |
Get Campaign Statistics
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get the stats of the first campaign
usabilla.websites.campaigns.stats
.get(campaignQuery)
.then(stats => {
console.log('# web campaign stats', stats);
})
.catch(reason => {
console.error(reason);
});
import usabilla as ub
if __name__ == '__main__':
# Get the stats of the first campaign
stats = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_WEBSITES, api.RESOURCE_CAMPAIGN_STATS, first_campaign['id'])
print stats
//Under construction
//Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "549972d5c469885e548b4570",
"completed": 5,
"conversion": 83,
"views": 6
}
HTTPS Request
https://data.usabilla.com/live/websites/campaign/<id>/stats
This request returns the statistics of a campaign with a specific id.
Request example
https://data.usabilla.com/live/websites/campaign/5499612ec4698839368b4573/results?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| id | String | The campaign id. Use * (asterisk) to request feedback of all campaigns. |
| limit | Integer | Optional. URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional. UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier for a campaign result. |
| completed | Integer | The amount of completed campaign forms that were submitted. |
| views | Integer | The amount of views the campaign form got by counting how many times it was opened. |
| conversion | Integer | The percentage of conversion (views to completion). |
In-Page
This section is regarding the Usabilla In-Page product and how to retrieve the feedback data. The In-Page widget can be placed anywhere on your webpage for users to give valuable feedback on the web content.
Get In-Page Widgets
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all inpage widgets for this account.
usabilla.websites.inpage.get()
# Under construction
// Under construction
// Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "5499612ec4698839368b4573",
"date": "2014-01-15T19:48:06.003Z",
"name": "My In-Page widget"
}
HTTPS Request
https://data.usabilla.com/live/websites/inpage
This request returns a list of your Usabilla for Websites In-Page widgets.
Request example
https://data.usabilla.com/live/websites/inpage?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| limit | Integer | Optional. URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional. UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier for an In-Page widget. |
| date | Date | The creation date of the In-Page widget, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| name | String | The name of the In-Page widget given when created. Can be updated in the In-Page widget setup page. |
Get In-Page Feedback
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all inpage widgets for this account.
usabilla.websites.inpage
.get()
.then(inPageWidgets => {
// Get the feedback for an inpage widget with id.
let inPageQuery = {
id: inPageWidgets[0].id
};
// Get the feedback of the first inpage widget
usabilla.websites.inpage.feedback
.get(inPageQuery)
.then(feedback => {
console.log('# inpage feedback', feedback.length);
})
.catch(reason => {
console.error(reason);
});
})
.catch(reason => {
// If the Usabilla call fails, we want to see the error message
console.error(reason);
});
# Under construction
// Under construction
// Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "549972d5c469885e548b4570",
"date": "2014-01-15T19:48:06.003Z",
"widgetId": "5499612ec4698839368b4573",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"location": "Amsterdam, Netherlands",
"geo": {
"city": "Schoten",
"country": "BE",
"region": "01"
},
"comment": "Very nice indeed",
"data": {
"Did_you_enjoy_th": 5
},
"customData": {
"form_name": "form1"
},
"mood": 3,
"rating": 0.5,
"nps": 5,
"url": "https://usabilla.com"
}
HTTPS Request
https://data.usabilla.com/live/websites/inpage/<id>/feedback
This request returns a list of your Usabilla for Websites In-Page feedback.
Request example
https://data.usabilla.com/live/websites/inpage/5499612ec4698839368b4573/feedback?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| id | String | The In-Page widget id. Use * (asterisk) to request feedback of all In-Page widgets. |
| limit | Integer | Optional. URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional. UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier for the In-Page widget feedback item. |
| date | Date | The creation date of the in-page widget, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| data | Array | An array containing the values of the In-Page widget form fields. |
| customData | Array | An array containing the values of the widget's custom fields. |
| widgetId | String | Unique identifier for the In-Page widget it belongs. |
| mood | Integer | Mood given by the user (0-5). |
| rating | Float32 | Rating from 0.0 to 1.0. |
| nps | Integer | The Net Promoter Score given by the user (0-10). |
| comment | String | Comment given by the user in the feedback form. |
| userAgent | String | Information about the browser user agent. |
| url | String | Origin URL where the In-Page widget result was registered. |
| geo | Map | Geographic location of user, consisting of city , country and region . |
Usabilla for Email
Usabilla for Email is a real-time customer feedback solution for integration with your email system. This section covers the resources that can be requested regarding the Usabilla for Email product.
Get Email Widgets
The email feedback widget is a widget usually placed in the footer of an email. Your recipients can click on the feedback widget after reading your email in order to give feedback.
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all email widgets for this account.
usabilla.email.widgets.get()
import usabilla as ub
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Get all email widgets for this account
widgets = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_EMAIL, api.RESOURCE_BUTTON)
first_widget = widgets['items'][0]
print first_widget['name']
// Under construction
// Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"date": "2015-03-11T14:35:04.536Z",
"groups": [
{
"active": true,
"date": "2015-03-11T14:35:04.539Z",
"id": "af8c54de7067",
"name": "Joshua's email footer"
}
],
"id": "e4b5a0661176",
"introText": "We'd love your input",
"locale": "en_US",
"name": "Mail campaign"
}
HTTPS Request
https://data.usabilla.com/live/email/widget
This request returns a list of your email widgets
Request example
https://data.usabilla.com/live/email/widget?limit=1
Parameter
| Field | Type | Description |
|---|---|---|
| limit | Integer | Optional URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier of the widget. 12 characters long. |
| date | Date | The creation date of the email widget, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| name | String | The name of the widget. |
| introText | String | The name of the widget given when created. Can be updated in the widget setup page. |
| locale | String | Regional language of the widget and form text items. |
| groups | Array | List of groups this campaign item is member of. |
Get Email Feedback
After the reader leaves feedback on an email widget it becomes a feedback item that you can view in your Usabilla account.
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all email widgets for this account.
usabilla.email.widgets
.get()
.then(emailWidgets => {
// Get the feedback for a email widget with id.
let emailQuery = {
id: emailWidgets[0].id
};
// Get the feedback of the first email widget
usabilla.email.widgets.feedback
.get(emailQuery)
.then(feedback => {
console.log('# email feedback', feedback.length);
})
.catch(reason => {
console.error(reason);
});
})
.catch(reason => {
// If the usabilla call fails, we want to see the error message
console.error(reason);
});
import usabilla as ub
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Get all email widgets for this account
widgets = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_EMAIL, api.RESOURCE_BUTTON)
first_widget = widgets['items'][0]
print first_widget['name']
# Get the feedback of the first email widget
feedback = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_EMAIL, api.RESOURCE_FEEDBACK, first_widget['id'], iterate=True)
print len([item for item in feedback])
// Under construction
// Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"id": "5499612ec4698839368b4573",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36",
"comment": "Thx for your email.",
"location": "Amsterdam, Netherlands",
"date": "2014-01-15T19:48:06.003Z",
"customData": {
"form_name": "form1"
},
"email": "dev@usabilla",
"labels": [
"label 1",
"label 2"
],
"nps": 10,
"rating": 5,
"buttonId": "8d73568ac2be",
"tags": [
"interesting",
"unattractive"
],
"urlParams": {
"utm_campaign": "1234576_20160101_my_campaign",
"utm_medium": "email",
"utm_source": "email_feedback_form"
}
}
HTTPS Request
https://data.usabilla.com/live/email/widget/<id>/feedback
This request returns a list of your email widget feedback.
Request example
https://data.usabilla.com/live/email/widget/8d73568ac2be/feedback?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| id | String | The widget id. If you wish to get all available feedback items use * (asterisk) as value. |
| limit | Integer | Optional URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier of the feedback item. |
| userAgent | String | Information about the browser user agent. |
| comment | String | Commentary left by the user in the feedback form. |
| location | String | String containing geographical information about the location of the user based on the user's ip address. |
| date | Date | The creation date of the email widget, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| customData | Map | Custom variables that have been assigned in the widget setup page. |
| String | Optional field that the user fills in in case he wishes to be contacted. | |
| labels | Map | An array of labels that have been assigned to the feedback item. |
| nps | Integer | The Net Promoter Score given by the user (0-10). |
| rating | Integer | Rating given by the user (0-5). |
| buttonId | String | The source widget of the feedback item. |
| tags | Array | An array of tags assigned to the feedback item. |
| urlParams | Map | The URL parameters passed via the feedback URL. |
Usabilla for Apps
Usabilla for Apps is a real-time user feedback system for analysis of customer experience on your mobile applications. This section covers the resources that can be requested regarding the Usabilla for Apps product.
Get App Forms
**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all apps forms for this account.
usabilla.apps.forms.get().then(appsForms => {
const appsForm = appsForms[0];
if (!appsForm) {
return;
}
}
import usabilla as ub
from datetime import datetime, timedelta
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Set the limit of buttons to retrieve to 1
if False:
api.set_query_parameters({'limit': 1})
# Set a limit for last 7 days
# NB: You might need to convert the since_unix calculation from scientific notation or set the since parameter manually
if False:
epoch = datetime(1970, 1, 1)
since = timedelta(days=7)
since_unix = (datetime.utcnow() - since - epoch).total_seconds() * 1000
api.set_query_parameters({'since': since_unix})
# Get all apps forms for this account
forms = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_APPS, api.RESOURCE_APP)
first_form = forms['items'][0]
print first_form['name']
// Under construction
// Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"date": "2014-08-22T13:34:07.043Z",
"id": "53f746cfc469889e628b4568",
"name": "New untitled App Form",
"status": "active"
}
Each App has a feedback button placed somewhere in the mobile application. App users can click on the feedback button at any time in order to give feedback. The feedback form (App Form) is initialized in the mobile application by calling the Usabilla SDK with the Form ID.
HTTPS Request
https://data.usabilla.com/live/apps
This request returns a list of your App Forms that are created in your Usabilla dashboard.
Request example
https://data.usabilla.com/live/apps?limit=1
Parameter
| Field | Type | Description |
|---|---|---|
| limit | Integer | Optional URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier of the Form. 24 characters long. |
| date | Date | The creation date of the Form, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| name | String | The name of the Form. |
| status | String | The status the Form. |
Get Form Feedback
/**
* argv[0] Access Key
* argv[1] Secret Key
*/
const args = require('yargs').argv._;
const Usabilla = require('../dist/api-js-node');
const usabilla = new Usabilla(args[0], args[1]);
// Get all apps forms for this account.
usabilla.apps.forms
.get()
.then(appsForms => {
const appsForm = appsForms[0];
if (!appsForm) {
return;
}
// Get the feedback for a apps form with id.
let appsQuery = {
id: appsForm.id
};
// Get the feedback of the second app form
usabilla.apps.forms.feedback
.get(appsQuery)
.then(feedback => {
console.log('# apps feedback', feedback.length);
})
.catch(reason => {
console.error(reason);
});
})
.catch(reason => {
// If the usabilla call fails, we want to see the error message
console.error(reason);
});
import usabilla as ub
from datetime import datetime, timedelta
if __name__ == '__main__':
# Create an API client with access key and secret key
api = ub.APIClient('YOUR-ACCESS-KEY', 'YOUR-SECRET-KEY')
# Set the limit of buttons to retrieve to 1
if False:
api.set_query_parameters({'limit': 1})
# Set a limit for last 7 days
# NB: You might need to convert the since_unix calculation from scientific notation or set the since parameter manually
if False:
epoch = datetime(1970, 1, 1)
since = timedelta(days=7)
since_unix = (datetime.utcnow() - since - epoch).total_seconds() * 1000
api.set_query_parameters({'since': since_unix})
# Get all apps forms for this account
forms = api.get_resource(api.SCOPE_LIVE, api.PRODUCT_APPS, api.RESOURCE_APP)
first_form = forms['items'][0]
print first_form['name']
# Get the feedback of the first app form
feedback = api.get_resource(
api.SCOPE_LIVE,
api.PRODUCT_APPS,
api.RESOURCE_FEEDBACK,
first_form['id'],
iterate=True)
print len([item for item in feedback])
// Under construction
// Under construction
The data will be received in JSON format like this:
HTTP/1.1 200 OK
{
"appId": "53f746cfc469889e628b4568",
"appName": "Usabilla Test Frame",
"appVersion": "48",
"batteryLevel": -1,
"connection": "WiFi",
"customData": {
"custom_variable": "one",
"shaken": 1,
"user_id": "786690"
},
"data": {
"name": "pablo",
"nps": 8,
"rating": 4,
"speed": 5,
"subject": "Compliment"
},
"date": "2015-04-20T08:12:13.382Z",
"deviceName": "iPhone Simulator",
"freeMemory": 224776,
"freeStorage": 131880204,
"geoLocation": {
"country": "NL",
"region": "07",
"city": "Amsterdam",
"lat": 52.35,
"lon": 4.9167
},
"id": "5534b4dcea5b09b33557bb20",
"ipAddress": "<IP_ADDRESS>",
"language": "en",
"location": "Amsterdam, Netherlands",
"orientation": "Portrait",
"osName": "ios",
"osVersion": "8.3",
"rooted": false,
"screenshot": "https://usabilla-feedback-app.s3.amazonaws.com/staging/media/55/34/5534b4dcea5b09b33557bb20/screenshot",
"screensize": "320x568",
"timestamp": "1429517532",
"totalMemory": 14032256,
"totalStorage": 243924992
}
After the user sends feedback using the feedback button it becomes a feedback item that you can view in your Usabilla dashboard.
HTTPS Request
https://data.usabilla.com/live/apps/<id>/feedback
This request returns a list of your feedback items that are connected to a specific App Form. The App Form is loaded in from the Usabilla SDK once a user clicks on the feedback button in the application.
Request example
https://data.usabilla.com/live/apps/8d73568ac2be8d73568ac2be/feedback?limit=1&since=1419340238645
Parameter
| Field | Type | Description |
|---|---|---|
| id | String | The Form ID. For feedback items of all Forms use * (asterisk) as value. |
| limit | Integer | Optional URL query parameter that limits the number of retrieved results between 1 and 100. Defaults to 100 when omitted. |
| since | Timestamp | Optional UTC Timestamp (in milliseconds) URL query parameter used to retrieve items of which creation date is after the supplied value. |
Success 200
| Field | Type | Description |
|---|---|---|
| id | String | Unique identifier of the feedback item. |
| date | Date | The creation date of the Form, in UTC. The format being used is %Y-%m-%dT%H:%M:%S.%fZ as defined in ISO 8601. |
| timestamp | String | Date and time (Unix timestamp) when feedback was sent by the App. |
| deviceName | String | Device name on which the app is running. |
| data | Map | Map containing the Feedback data ("mood" and "nps" scores). |
| customData | Map | Map containing the optionally configured custom values. |
| appId | String | ID of the feedback form the feedback item belongs to. |
| appName | String | Name of the feedback form |
| appVersion | String | Version of the app. |
| osName | String | Operating System name on which the app is running. |
| osVersion | String | Operating System version on which the app is running. |
| location | String | Readable location (City, Country). |
| geoLocation | Map | Geographic location details ("country", "region", "city", "lat", "lon"). |
| freeMemory | Integer | Bytes of RAM left unused. |
| totalMemory | Integer | Bytes of RAM in total. |
| freeStorage | Integer | Bytes of storage memory left unused. |
| totalStorage | Integer | Bytes of storage memory in total. |
| screenshot | String | Screenshot URL. |
| screensize | String | Screen property size. |
| connection | String | Current connections. |
| ipAddress | String | Current IP address. |
| language | String | Language used. |
| orientation | String | The orientation of the screen at time of feedback ['Portrait','Landscape']. |
| batteryLevel | Float32 | Battery level from 0.0 to 1.0 (-1 means unknown). |


You can also define a custom style and color theme for the editor. This component provides a convenient
Java API that is a light wrapper around the underlying JavaScript API. Specify the available themes
via the customThemes
option on the editor. Then you can enable that theme by setting
the theme
option on the editorOptions
. See also the
example on the Monaco editor homepage.
When you need even more fine-grained control, consider using the
client-side API
directly via the extender
option.
${showcase:getFileContent('/sections/monacoEditor/example-customThemeDiff.xhtml')}
${showcase:getFileContent('/org/primefaces/extensions/showcase/controller/MonacoEditorController.java')}
${showcase:getFileContent('/org/primefaces/extensions/showcase/util/MonacoEditorSettings.java')}


Id: 377
Name: Voltematron
Status: Dead
Species: Alien
Type: Parasite
Gender: unknown
OriginName: unknown
OriginUrl:
LocationName: Earth (Replacement Dimension)
LocationUrl: https://rickandmortyapi.com/api/location/20
Image: https://rickandmortyapi.com/api/character/avatar/377.jpeg
Episode: ['https://rickandmortyapi.com/api/episode/29']
Url: https://rickandmortyapi.com/api/character/377
Created: 2018-01-10T19:29:08.116Z


A few things to know:
Click on the to add your first widget.
Dashboards can hold as many widgets as you like, each with their own settings.
To compare data across countries and regions, you can add multiple copies of widgets.
Once you've added some widgets, you can rearrange them however you'd like.
If you'd like to share this dashboard with others or visit it again later, make sure to keep a copy of the URL.
There are currently no widgets in this dashboard.
{{/if}}


WebSocket (incl. Flash-based)
Server-Sent Events
Multipart(/x-mixed-replace) -- Firefox only
Long Poll


Toggle navigation
YWCA CMS
Logout
News
class list
feedback list
import/export data
Classes
courses table
course id
course name
start date
end date
course image
total lessons
total students
view detail
student name(student id )
courses
attendances


CjsSS (Cascading Javascript Style Sheet) is LESS SASSy and more Stylush than the competition ;)
cjsss.min.js(Node.js optional for server-side preprocessing)
objects
camelCaseto
dash-caseof Javascript
objectkeys converted auto-magicially
evaluated Javascript fully sandboxed by default
SCRIPTreferences within the CSS (e.g.
<script src='https://github.com/gka/chroma.js'></script>).
Variables within
styleattributes
SCRIPTtag(s) in the
HEADof your HTML document below any
LINK/
STYLEtags you want to process:
<script type="text/javascript" src="cjsss-polyfill.js"></script> <!-- IE6-7 support --> <script type="text/javascript" src="cjsss.min.js"></script>
cjsssattribute to the
LINKand/or
STYLEtags you want to process:
<link rel="stylesheet" type="text/css" href="css/site.css" cjsss> <style type="text/css" cjsss>...</style>
optionsused by CjsSS.js (if any) using JSON-style object definitions (both keys and values are "double quoted"):
<style type="text/css" cjsss='{ "crlf": "\n" }'>...</style> <link rel="stylesheet" type="text/css" href="css/site.css" cjsss='{ "crlf": "\n" }'>
LINKand/or
STYLEtags to use CjsSS.js like this:
/*<script> var mainColor = 'blue'; </script>*/ DIV { color: /*mainColor*/; }
data-cjsssin place of
cjsssif you want to be HTML5 compliant.
autorunand
exposethe
window.cjsssobject (NOTE:
exposehappens auto-magicially when you disable
autorun) like so:
When CjsSS.js is<script> window.cjsss = { options: { selector: '', //# disables autorun expose: true //# exposes `window.cjsss` } }; </script> <script type="text/javascript" src="cjsss.min.js"></script> <!-- include CjsSS.js -->
exposed, the following properties are made available under
window.cjsss:
dataexposes the internal variables utilized by the
services:
cachestores the associative array that holds (amoung other things) the original
innerHTMLof the CjsSS.js processed
LINKand
STYLEtags, keyed by DOM reference.
injectstores the associative array that holds the values added via
cjsss.inject, keyed by the provided
sVarName.
servicesstores the unmodified default implementations of the internal services used by CjsSS.js.
inject(sVarName, variant)function injects the provided
variantinto the evaluated Javascript code via the provided
sVarName. This functionality allows you to expose any Javascript functionality you wish to the evaluated Javascript code. This call is always forwarded to the implementation present in
services.injectso there is no need to reset this property.
options* stores the default values as described in the options section.
process(vElements, oOptions)function processes the referenced
vElementswith preference to the provided
oOptions.
vElementscan be of type
string(as a CSS selector) or as an array-like collection of DOM element references (such as a NodeList, jQuery object or an Array).
oOptionsis an
objectdescribing the desired options. This call is always forwarded to the implementation present in
services.processso there is no need to reset this property.
services* stores the default implementations of the internal services used by CjsSS.js. Please view source code within
cjsss.jsfor further details.
versionstores the version number of CjsSS.js that is being run.
exposebeing run are preserved in addition to any other properties not described above (e.g.
window.cjsss.customwould be preserved).
injectCustom Functionality
autorun,
cjsss.injectcan be used to expose any Javascript variable or value to your CjsSS.js evaluated Javascript code:
The code above exposes a function called "invertColor" to all CjsSS.js evaluated Javascript code like this:<script> //# .inject a function named "invertColor" cjsss.inject("invertColor", function(sHex) { var r, g, b, sReturnVal; if (sHex.length === 7 && sHex.indexOf('#') === 0) { r = "0" + (255 - parseInt(sHex.substr(1, 2), 16)).toString(16); g = "0" + (255 - parseInt(sHex.substr(3, 2), 16)).toString(16); b = "0" + (255 - parseInt(sHex.substr(5, 2), 16)).toString(16); sReturnVal = "#" + r.substr(-2) + g.substr(-2) + b.substr(-2); } return sReturnVal; }); //# .inject an object named "userConfig" var defaultColor = { color: "green" }; cjsss.inject("userConfig", defaultColor); //# .inject an object named "span" var spanCss = { backgroundColor: "red" subObject: defaultColor }; cjsss.inject("span", spanCss); //# .inject a string named "textTransform" cjsss.inject("textTransform", "capitalize"); //# Process the LINK / STYLE tags with a "cjsss" attribute and no oOptions cjsss.process("[cjsss]", {}); </script>
/*<script> var sMainColor = "#cccccc"; </script>*/ DIV { color: /*invertColor(sMainColor)*/; //# invertColor returns '#333333' text-transform: /*textTransform*/; //# outputs 'capitalize' } P { /*mixin(userConfig)*/ //# outputs 'color: "green";' } /*mixin(span, true)*/ //# outputs 'span { background-color: "red"; color: "green"; }'
cjsss.servicesFactoryor
cjsss.services.
cjsss.servicesexposes all of the internal functionality of CjsSS.js, allowing every piece of functionality within CjsSS.js to be overridden. Implementing a
cjsss.servicesFactoryunder
window.cjsssprior to including the CjsSS.js
SCRIPTtag(s) allows you to override any
cjsss.servicesfunctionality prior to CjsSS.js loading, or you can replace any of the functions under
cjsss.servicesafter CjsSS.js has been exposed via
window.cjsss. For example, if you wanted to override the
exposefunctionality to make CjsSS.js available in a variable other than
window.cjsss, you could do the following:
<script> var newVar = null; window.cjsss = { options: { expose: true //# exposes CjsSS.js under `newVar` }, servicesFactory: function ($cjsss) { return { expose: function() { newVar = $cjsss; } }; } }; </script> <script type="text/javascript" src="cjsss.min.js"></script>
autorunbehavior of CjsSS.js then you will want to include the CjsSS.js
SCRIPTreference after all
cjsssattributed
LINK/
STYLEtags.
LINKtag CSS files are read via AJAX, the limitations of
XMLHttpRequestcan restrict where you serve your CSS files from. If your CSS files exist on the same server, this is a non-issue.
LINKtags are removed from the DOM, their CSS file contents are modified and placed within a new
STYLEtag that is appended into the
HEAD. This process can break some relative URLs within your CSS files (e.g.
background-image: url("../img/a.png");). It is therefore recommended that you use absolute URLs within your CSS files (e.g.
background-image: url("/img/a.png");) in order to avoid any such errors.
SCRIPTs are all evaluated in series at initilization prior to CSS modification, so the following will not work as expected:
At initilization/*<script> var mainColor = 'blue'; </script>*/ DIV { color: /*mainColor*/; //# expecting 'blue' but gets 'green' } /*<script> mainColor = 'green'; </script>*/ SPAN { color: /*mainColor*/; //# expecting 'green' }
mainColorwill be set to "blue" then "green" prior to any CSS modification, so the
colorof both DIV and SPAN will be set to "green".
document.querySelectorAlland
JSON.parsefunctionality has been polyfilled via
cjsss.polyfill.jsor with jQuery (which is auto-magicially imported) included prior to CjsSS.js. The required "advanced" JavaScript functionality is:
cjsss.polyfill.jsor jQuery's
$()
cjsss.polyfill.jsor jQuery's
$.parseJSON()
LINKtags are removed from the DOM, their CSS file contents are modified and placed within a new
STYLEtag that is appended into the
HEAD. This is done so that the original unprocessed CSS referenced by the
LINKtag does not apply to the webpage.
exposeCjsSS.js, the
window.cjsssobject will be added under the global scope.
scopeof either
global,
localor
this, CjsSS.js-embedded Javascript has the ability to modify the global scope.
scopeof
global, the
window.mixinfunction will be added under the global scope (though it will not overwrite an existing
window.mixinif one exists).
LINKand
STYLEtags is modified based on the embedded Javascript.
Oh, you mean Cee & Jay? They are the mascots for CjsSS.js!
CjsSS (cee-JAY-hiss or Cascading Javascript Style Sheet) is the union of two related web technologies joined seemlessly (unnaturally?) into one solution. Thanks to the akwardness of the acronym (ending in three S's) it seemed reminisent of a snake's hiss... "CSS and Javascript sss-ing"... "CJ hiss"... Hey! I need a two-headed snake!
CjsSS.js is a Vanilla-Javascript toolkit made by Nick Campbell, © 2014.
CjsSS.js is released under the MIT License. See the license.txt file in the source code for copy permission.
 Development is not supported by advertising nor the marketing of your email addresses. If you find this code useful, please consider tossing a few dollars into my tip jar. If you are a company that finds this code useful, please feel free to toss more than a few dollars into my tip jar ;)


Hello {{ user.first_name }}, Your ticket had been successfully submitted. You can find a summary below:
Location: {{ ticket.location }}
Category: {{ ticket.category }}
Description: {{ ticket.description }}
IP Address: {{ ticket.ipAddress }}


This feature is only available for registered users
Sign in
Sign in using your
cplusplus.com
account:
User name:
Password:
Remember me:
(keeps you logged in between sessions)
Or, using an external account:
[
I have lost my password
] [
Create a new account
]


1. Origin Installion Instructions and Advice
The setup and installation of Origin is described below.
1.1. Install Openshift Origin
Binary releases of Openshift Origin are available here: https://github.com/openshift/origin/releases
Openshift install steps:
-
download the binary release
-
untar the release to your local host
-
run as follows:
sudo ./openshift start
-
set the permissions on the admin kubeconfig file to allow changes
sudo chmod 666 ./openshift.local.config/master/admin.kubeconfig
-
add the following to your bash shell environment to allow you access to the openshift admin account:
export KUBECONFIG="$(pwd)"/openshift.local.config/master/admin.kubeconfig export CURL_CA_BUNDLE="$(pwd)"/openshift.local.config/master/ca.crt
-
edit the restricted settings, you will need to change the runAsUser type value to RunAsAny to allow the container to run as the postgres user.
oc login -u system:admin oc edit scc restricted --config=./openshift.local.config/master/admin.kubeconfig
-
login in as test user and create a project called pgproject
oc login -u test oc new-project pgproject
Openshift starts an internal DNS server when it starts, and it registers DNS names for each service that you create. To refer to this DNS server, you adjust your /etc/resolv.conf file to include the Openshift DNS server IP as your primary name server, also you adjust the searchpath if you dont want to type <[projectname].svc.cluster.local when you refer to the various Openshift services you create. Here is an example /etc/resolv.conf that uses an Openshift project name of 'pgproject:
search pgproject.svc.cluster.local crunchy.lab nameserver <IP_ADDRESS> nameserver <IP_ADDRESS>
This example used an Openshift project name of pgproject. The project name is used as part of the DNS names set by Openshift for Services.
1.2. Origin Prerequisites
NFS is required for some of the Openshift examples, those dealing with backups and restores will require a working NFS.
NFS is able to run in selinux Enforcing mode if you following the instructions here:
Other information on how to install and configure an NFS share is located here:
Examples of Openshift NFS can be found here:
The examples specify a test NFS server running at IP address <IP_ADDRESS>
On that server, the /etc/exports file looks like this:
/jeffnfs *(rw,sync)
if you are running your client on a VM, you will need to add insecure to the exportfs file on the NFS server, this is because of the way port translation is done between the VM host and the VM instance.
see this for more details:
2. Origin Tips
2.1. Tip 1: Finding the Postgresql Passwords
The passwords used for the PostgreSQL user accounts are generated by the Openshift process command. To inspect what value was supplied, you can inspect the master pod as follows:
oc get pod pg-master-rc-1-n5z8r -o json
Look for the values of the environment variables:
-
PG_USER
-
PG_PASSWORD
-
PG_DATABASE
2.2. Tip 2: Examining a backup job log
Database backups are implemented as a Kubernetes Job. A Job is meant to run one time only and not be restarted by Kubernetes. To view jobs in Openshift you enter:
oc get jobs oc describe job backupjob
You can get detailed logs by referring to the pod identifier in the job describe output as follows:
oc logs backupjob-pxh2o
2.3. Tip 3: Backup Lifecycle
Backups require the use of network storage like NFS in Openshift. There is a required order of using NFS volumes in the manner we do database backups.
So, first off, there is a one-to-one relationship between a PV (persistent volume) and a PVC (persistence volume claim). You can NOT have a one-to-many relationship between PV and PVC(s).
So, to do a database backup repeatably, you will need to following this general pattern: * as openshift admin user, create a unique PV (e.g. backup-pv-mydatabase) * as a project user, create a unique PVC (e.g. backup-pvc-mydatabase) * reference the unique PVC within the backup-job template * execute the backup job template * as a project user, delete the job * as a project user, delete the pvc * as openshift admin user, delete the unique PV
This procedure will need to be scripted and executed by the devops team when performing a database backup.
2.4. Tip 4: Persistent Volume Matching
Restoring a database from an NFS backup requires the building of a PV which maps to the NFS backup archive path. For example, if you have a backup at /backups/pg-foo/2016-01-29:22:34:20 then we create a PV that maps to that NFS path. We also use a "label" on the PV so that the specific backup PV can be identified.
We use the pod name in the label value to make the PV unique. This way, the related PVC can find the right PV to map to and not some other PV. In the PVC, we specify the same "label" which lets Kubernetes match to the correct PV.
2.5. Tip 5: Restore Lifecycle
To perform a database restore, we do the following: * locate the NFS path to the database backup we want to restore with * edit a PV to use that NFS path * edit a PV to specify a unique label * create the PV * edit a PVC to use the previously created PV, specifying the same label used in the PV * edit a database template, specifying the PVC to be used for mounting to the /backup directory in the database pod * create the database pod
If the /pgdata directory is blank AND the /backup directory contains a valid postgres backup, it is assumed the user wants to perform a database restore.
The restore logic will copy /backup files to /pgdata before starting the database. It will take time for the copying of the files to occur since this might be a large amount of data and the volumes might be on slow networks. You can view the logs of the database pod to measure the copy progress.
2.6. Tip 6: Password Mgmt
Remember that if you do a database restore, you will get whatever user IDs and passwords that were saved in the backup. So, if you do a restore to a new database and use generated passwords, the new passwords will not be the same as the passwords stored in the backup!
You have various options to deal with managing your passwords.
-
externalize your passwords using secrets instead of using generated values
-
manually update your passwords to your known values after a restore
Note that you can edit the environment variables when there is a dc using, currently only the slaves have a dc to avoid the possiblity of creating multiple masters, this might need to change in the future, to better support password management:
oc env dc/pg-master-rc PG_MASTER_PASSWORD=foo PG_MASTER=user1
2.7. Tip 7: Log Aggregation
Openshift can be configured to include the EFK stack for log aggregation. Openshift Administrators can configure the EFK stack as documented here:
2.8. Tip 8: nss_wrapper
If an Openshift deployment requires that random generated UIDs be supported by containers, the Crunchy containers can be modifed similar to those located here to support the use of nss_wrapper to equate the random generated UIDs/GIDs by openshift with the postgres user:
2.9. Tip 9: build box setup
golang is required to build the pgbadger container, on RH 7.2, golang is found in the server optional repository and needs to be enabled to install.
golang is required to build the pgbadger container, on RH 7.2, golang is found in the server optional repository and needs to be enabled to install.
2.10. Tip 10: encoding secrets
You can use kubernetes secrets to set and maintain your database credentials. Secrets requires you base64 encode your user and password values as follows:
echo -n 'myuserid' | base64
You will paste these values into your JSON secrets files for values.
2.11. Tip 11: DNS host entry and DeploymentConfig
If your openshift environment can not resolve your hostname via a DNS server (external to openshift!), you will get errors when trying to create a DeploymentConfig. So, you can either install dnsmasq and reconfigure openshift for that, or, you can run a DNS server on another host and add the openshift host entry to that DNS server. I use the skybridge2 Docker container for this purpose. You have to remember to adjust your /etc/resolv.conf to specify this new DNS server.
3. Legal Notices
Copyright © 2016 Crunchy Data Solutions, Inc.
CRUNCHY DATA SOLUTIONS, INC.
Crunchy, Crunchy Data Solutions, Inc. and the Crunchy Hippo Logo are trademarks of Crunchy Data Solutions, Inc.


Building dht.cc …
$ cmake -DMM_VERSION=UNKNOWN -DCMAKE_BUILD_TYPE=Debug ..
$ cmake -DMM_VERSION=UNKNOWN -DCMAKE_BUILD_TYPE=Debug ..
thread 'main' panicked at '
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! unwrap! called on Result::Err !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
mm2src/common/build.rs:899,5 in build_script_build
Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })


{% include "includes/nav.html" %}
Register
Email:
Username:
Password:
Confirm password:
Register
{% include "includes/footer.html" %}


This is part of the old website. New website begins at fontforge.github.io
Are you a web developer? Help us migrate this page on Github
The font view is a list of all the glyphs available in the given font.
You may chose to display it at various sizes, by default it will be displayed with the outline font rasterized on a 24 pixel em square. You may display it at 36, 48, 72 and 96 pixel sizes as well. You may also choose to look at an anti-aliased greymap (the above image is anti-aliased). These are slower to generate but look nicer (Comparison).
If you have an encoding slot which has nothing in it (as opposed to an encoding which maps to a space glyph) then that will be shown by a faint red X drawn across the box.
Above each image of the glyphs in the font is a label indicating the glyph in some conventional format. Usually this is just a small image of the glyph in a standard font (as it is above), but you can change it to show the glyph's name, unicode code point or encoding (in hex). In small views (24 pixel view for instance) there may not be room for the entire label, and it will appear truncated.
If a glyph has been changed since it was last hinted (PostScript), or if a glyph contains contours but has no instructions (TrueType), then its label will be edged with blue bars. If the glyph has out of date instructions (TrueType), then its label will be edged with red.
If one of your glyphs has something in its background layer then this will be indicated visually (currently by darkening the background of the glyph label).
Normally the view will display the foreground layer of the font, but you
may change it to display any layer (other than the background layer) with
View->Layers->?
You may also display any of the bitmap fonts you have generated from the outline glyphs. Simply go to the View menu and select the one you want.
If you look at a bitmap version of the font, and it does not contain a glyph for which there is an outline glyph (ie. the font needs its bitmaps regenerated) then the missing glyph will be outlined in red to bring it to your attention more easily.
Small bitmap fonts will be magnified. If the pixelsize of the font is less than 10 it will be shown 3 times normal size, if less than 20 twice normal size.
Underneath the menu bar is some information on the last glyph selected. First is the encoding of the glyph in the current font expressed in decimal. Next is the unicode code point for the glyph (or ???? if it is not a unicode character). Next the postscript name for the glyph, and finally the unicode name. Not all unicode characters will have unicode names (the CJK characters do not for example)
If you move the cursor to a glyph and let it rest there a small popup window will appear containing information about that glyph. If you depress the control key then this window is locked in place until you move the mouse.
You may display metrics lines (baseline, origin and advance width) in the font view. (View -> Show H Metrics). If you do so, I suggest viewing the font at a large pixel size, otherwise the window looks too confusing.
|
|
| A 96 pixel display showing the various horizontal metric lines. The blue line is the baseline The small red tick on the left marks the glyph origin. The green line on the right shows where the advance width is while the bottom green line shows how long it is. (normally you will not display both at once) The glyph is centered horizontally, and the font ascent is the top of the box displaying it, while the descent is the bottom. |
A 96 pixel display showing the various vertical metric lines. The blue line down the center is the vertical baseline. The red bar at the top (over writing the ascent line) is the vertical origin. The green line at the bottom shows where the vertical advance is while the green line on the right shows how long it is. (normally you will not display both at once) |
You may select any number of glyphs in the font by dragging through them. You may use shift-click to select (or deselect) additional glyphs. You may also use the arrow keys to move around (and shift-arrow to select). To some extent the order you select glyphs in will be remembered and a few commands will make use of that.
You may drag and drop selected glyphs into
The [Tab] key will move to the next glyph with something in it, and Shift-[Tab] will move to the previous glyph with something interesting.
You can perform various operations on the selected glyphs:
And, of course, you can cut and paste. Normally copying a glyph will copy that glyph and any bitmaps associated with it, but you can use the Edit->Copy From menu item to change this so that only entries from the currently displayed font are copied. So if a 12 pixel font is being displayed then only the bitmaps from the 12 pixel bitmap font will be copied in this mode. Cut and Clear will clear those things which would be copied.
Paste is a little more complicated. In general it will paste whatever is in the clipboard, regardless of the copy mode. So if the clipboard contains a 12pixel bitmap and the font view is displaying outlines, then pasting it will paste it into the 12pixel font none the less. There is one exception to this. If the clipboard contains a 12 pixel bitmap and the font view is currently display a 17pixel bitmap then the paste will go into the displayed bitmap.
A Paste from the font view will delete whatever splines were in the glyph beforehand (while a paste in the outline glyph view will merge the new set of splines with the old). Paste from the font view will also set the width of the glyph.
You can scroll the display to any particular character by typing that character. There is also a dialog which allows a slightly more general way of jumping around. You may type in the glyph's name (all glyphs in a font will be named), its encoding value, its unicode encoding value, or (for 2 byte fonts) its ku ten specification.
Pressing the right mouse button invokes a popup menu.
A Character Set is a set of characters (for example all the letters of the alphabet would be one character set). An encoding is a function that takes a number (often between 0 and 255) and maps it to a character. Often these two are used synonymously as an encoding generally implies a given character set. (strictly speaking a character set is an unordered collection with no implied encoding, and some encodings work with multiple character sets).
All fonts in fontforge have both a character set and an encoding. The character set is just the set of characters in the font. The encoding is the way those characters are ordered (or sometimes, the way the first 256 are ordered). The font info dialog allows you to chose the encoding (and character set) you wish for a font. Often a font will have a few extra glyphs that don't fit into the character set specified by the encoding, these glyphs will be placed at the end of the font and when the font is output (ie. postscript is generated, or a bitmap font created) the glyphs will be included in the font but they will not be encoded (this can be useful, especially in postscript where it is possible to reencode a font at run time. Thus a font might have all the glyphs needed both for a cyrillic character set and for a latin one, but only one character set at a time would be encoded).
It is possible for an encoding not to be one-to-one. That is there may be several characters that might lead to the same underlying glyph (the classic example is the non-breaking space which often uses the same glyph as the breaking space). When FontForge encounters such an encoding it will create a character structure for each entry, one of those structures will contain the data for drawing the glyph, the other(s) will contain a reference to the one real character. All characters will have the same name. When FontForge generates a font it looks for this case and turns it into a font whose encoding vector contains multiple references to a glyph.
It is also possible to have an encoding where a single character can lead to several different glyphs depending on the context. In arabic, for example, most characters have at least four different glyphs depending on whether the character is found initially, medially or finally in a word, or if it appears by itself (isolated).
You may also create a custom encoding. (Generally, only the first 256 entries of a Custom encodings will actually be part of a font's encoding vector). You may change the name of any glyph in the font with the Element->Char Info command. This will force the font to have a custom encoding.
There are many standard encodings built in to the program. There are 14 ISO 8859 encodings, the encoding used by the Macintosh for the US and Western Europe, the encoding used by MS Windows for the US and Europe (which is a slight extension of ISO 8859-1). There are also several 2-byte encodings built in. Several of these are subsets of unicode (whose goal is to specify every character currently used by humans). There are many large CJK (Chinese, Japanese, Korean) two byte encodings. You can also add your own encodings with the Encoding menu. A brief description of what's in the encodings also appears on that page.
There may be some slight differences between one vendor's definition of an encoding and another. I try to follow those encodings specified by the Unicode consortium. I notice that the Symbol encoding used by Microsoft differs from the Unicode one (usually just be substituting synonyms, Omega for Ohm sign for instance).
Adobe did not choose their naming conventions very well for Greek letters. They assigned the name "mu" to Micro Sign, "Delta" to Increment and "Omega" to Ohm Sign. So the Greek alphabet has ugly nameless holes in it.
CID fonts (see below) have no encodings. Instead they are designed to be associated with one or several cmap files which provide encodings in a general way. cmap files are beyond the scope of FontForge. Adobe has defined many which are freely available.
There is one final encoding called "Glyph Order". This encoding is just the glyphs in the order in which they were read from the original font.
PostScript® assigns a name to every unicode character. Some of these names are fairly obvious like "A" for the first letter of the latin alphabet, others are more obscure like "afii57664" for hebrew alef, while others are just "uni8765" for the unicode character at 0x8765.
PostScript Unicode encoding does not quite mesh with the unicode standard. This is probably because PostScript deals in glyphs and Unicode deals with characters so PostScript sees no distinction between space and nobreak space (and so does not encode the latter) while Unicode does.
According to the unicode website the first 256 character positions of unicode and ISO 8859-1 (ISO Latin1) are the same. However the PostScript encoding of ISOLatin1 is slightly different from that specified for unicode. I cannot explain the reasoning behind this. FontForge does not use PostScript's ISOLatin1 Encoding vector, instead it uses the first 256 code positions of the unicode encoding vector (slightly modified by me to conform to Unicode conventions rather than PostScript. So I include nobreak space and the soft-hyphen).
FontForge supports two slightly different unicode encodings. The first contains only the first 65536 characters of unicode (those in the Basic Multilingual Plane, or BMP), while the second can contain as many characters as you have memory for. Character definitions are still sparse outside of the BMP so at the moment you probably want to use just the BMP. Currently there are only definitions for plane 0 (BMP, U+0000-U+ffff), Plane 1 (SMP, Secondary Multilingual Plane, U+10000-U+1ffff), Plane 2 (SIP, Supplementary Ideographic Plane, U+20000-U+2ffff), and Plane 14 (SSP Supplementary Special-purpose Plane, U+e0000-U+effff).
The standard mechanisms that postscript provides work reasonably well for alphabets and syllabaries, but the massive number of characters needed for CJK (Chinese, Japanese or Korean) fonts require more complex machinations. Adobe's current solution is the CID-keyed font, a font consisting of several subfonts each a collection of glyph descriptions with no encoding imposed on them and no names given to them.
If FontForge loads in a CID keyed font it will enable a special menu called CID which (among other things) displays the list of all the sub-fonts in the font. When it starts up FontForge will pick (practically at random) a sub-font to display in the font view. You may change which font is displayed by the CID menu.
The CID menu also allows you to turn a normal font into a CID keyed font. It creates a collection containing just the original font (you may add other fonts, or blank fonts, later). But before it can create a collection FontForge needs to know what glyph set you will be using. A glyph set is just a collection of glyphs, and you may define your own if you wish (but if you do you have to define your own cmap files, etc and it's probably not worth it). Adobe has defined glyph sets for Japanese (actually there are two, one corresponding to JIS208 and one to JIS212), Korean (Wansung & Johab), Traditional Chinese (Big5) and Simplified Chinese (GB2312). Although these glyph sets are based on the standards mentioned, they each have many additional glyphs. Adobe also defines a glyph set that works for Unicode, but it is called "Identity" instead. FontForge does not have these glyph sets built in to it, each must be loaded the first time it is used. I provide one file for each of the above glyph sets, they have an extension of ".cidmap", and you may download them all from here.
(There are also many other character sets floating around feel free to install them yourself).
Adobe identifies each glyph set by a three values: a registry, an ordering
and a supplement. The registry is the name of the organization that is defining
the glyph set (Adobe calls itself Adobe), an ordering identifies the glyph
set (Japan1, Korea1, etc.) and the supplement indicates how many times the
ordering has been revised. Glyphs may only be added to an ordering, never
removed, so an old font will be perfectly described by a newer glyph set,
while a new font described by an old glyph set will have some unavailable
glyphs. So a full cidmap name will look like:
Adobe-Japan1-4.cidmap
Adobe-Korea1-2.cidmap
Warning: CID keyed fonts (actually any CJK font) use massive amounts of memory in FontForge. I am able to work on many of them on my 256M machine with 384M of swap space.
The Remove Undoes command will allow you to free up memory if you think you may be running short. FontForge is not always able to protect itself against running out of memory, sometimes the OS just sends it a SIGKILL signal.
If the font is a Multiple Master Font there will again be several subfonts only this time all the subfonts contain the same glyph set. Each subfont provides glyphs for one style of the font family. The MM menu allows you to control which style of the family is visible in the font view, and provides a few other commands for manipulating multiple masters.
CJK fonts generally should have vertical metrics. Latin (Cyrillic, Greek) fonts generally should not. If FontForge reads in a font with vertical metrics it will retain those metrics, but when FontForge creates a new font then that font will not have vertical metrics enabled.
To enable vertical metrics for a font go to
Element->Font Info
and
select the General
tab and check the [*] Has Vertical
Metrics
checkbox. This will allow you to set the vertical origin for
the font and it will give every glyph a default vertical advance of the emsize
of the font (ascent+descent).
The vertical origin is the y height (in the design coordinate system) of the origin for vertical metrics.
In the outline glyph view you will be able to adjust the vertical metrics just as you adjust the horizontal metrics.
You can view the vertical metrics in the font view just as you can the horizontal metrics with View->Show V Metrics.


AM2R Suit Editor
<
Power Suit
>
<
Front View
>
<
>
Reset Color
<
Speed: 1.0x
>
Reset All Colors
Import Palette
Export Palette
version 1.0
by Electrix


Athletics expects low of 6 golds, high of 12 in SEAG
by Manila Standard SportsPhilippine Athletics’ Track and Field Association president Philip Juico knows he has six athletes capable of winning gold medals in the 30th Southeast Asian Games.
But he also challenged his possible silver medalists to go for gold and leave it all on the track and field.
“Ang sabi namin sa kanila (possible silver medallists), you guys who are capable of silver, tirahin niyo na. Try your best to win the gold. Kasi sabi nila, a silver can also be gold,” said Juico.
In PATAFA’s projections, Juico sees a gold-silver-haul of 6-10-8 in the coming athletics’ competitions of the biennial meet, slated Dec. 5 to 10 at the 20,000-seat New Clark City athletics’ stadium inside the sprawling 9,500-hectare NCC sports complex.
“Sa triple jump, it’s Harry Diones. He has been a little inconsistent, kaya lang tumataas ang ranking niya. From silver, puwedeng mag-gold iyan. In decathlon, it’s Aries Toledo, who won gold in kuala lumpur. Probably good for a silver, pero puwede rin mag-gold,” said Juico. “We urge them to go for it. Ibigay na ang lahat for our country.”
Projections are quite conservative on reigning marathon champion Mary Joy Tabal due to a pair Thai runner, “breathing down her neck.”
“It [gold count] could be anywhere between 6 to 12 golds. That’s [12] the most optimistic,” he added.
The tracksters who are best-equipped to win golds are pole vaulters Ernest John Obiena and Natalie Uy, 800-meter specialist Carter Lilly, hurdles champ Eric Cray, sprinter Kristina Knott and new recruit, shot-putter William Morrison.
The 21-year-old Morrison heaved a distance of 20.4 meters in a Bloomington, Indiana meet last June. That mark, is over two meters better than the 17.42, which Promrob Juntima of Thailand achieved when he won the gold medal back in the 2017 SEA Games.
Morrison, in fact, is just half a meter short of the Olympic standard of 21.1 that would qualify him for the 2020 Tokyo Olympics.
“Morrison is a candidate for the Olympics. Kaya because he is throwing in the 20s,” said Juico.
Another FilAm in Cray is the best bet in the men’s 400-meter hurdles, since he is no. 1 in the SEA rankings.
Then’s there’ Lilly, who can go below 1:48.00 in the men’s 800-meter run.
Pole-vaulters Obiena and Uy, the gold and bronze medalists, respectively, in the Asian Athletics Championship in Doha, Qatar, are currently the best in the region.


The page represents number of links to various Zebra demos and applications. You can find more samples and snippets in Zebra "samples" folder.
Pay attention to have the referenced samples and demos workable you have to start small test HTTP server. If it has not been done yet, start
it as follow:


Click and Drag to arrange your Route
Add new Route
View In Map
No Car Stops
Car Stops
Delete
Edit
Your Menu (Original Menu will be Horizontal)
Route Name :
Add your Car Stops here
Car Stop #{idx.index + 1}
Car Stop Name :
Car Stop Latitude :
Car Stop Longitude :


This tool is designed for those situations during a pentest where you have upload access to a webserver that’s running PERL. Upload this script to somewhere in the web root then run it by accessing the appropriate URL in your browser.
Grab perl source (AND MODIFY LHOST/LPORT) from:
http://pentestmonkey.net/tools/perl-reverse-shell/perl-reverse-shell-1.0.tar.gz
Others:
Perl
http://home.arcor.de/mschierlm/test/pmsh.pl
http://pentestmonkey.net/tools/perl-reverse-shell/
http://freeworld.thc.org/download.php?t=r&f=rwwwshell-2.0.pl.gz


Your company email: {{ company.email | lowercase }}
Your company password: {{ company.password | hidePassword }}
Total company coupons: {{ coupons.length | number }}
Category {{ category.value | titlecase }} : {{ filterCoupons(coupons, category.key).length }}


Medical Scholars Program
Helping Undergraduates to Careers in Health and Biomedical Sciences
The Medical Scholars Program (MSP) is a program sponsored by the University of California, Riverside School of Medicine that is designed to help undergraduate students prepare for careers in health or biomedical sciences. Students in the MSP distinguish themselves through their leadership, commitment to program goals, and desire to provide service to underserved and diverse communities.
Students who are first generation to college, socioeconomically disadvantaged, and/or demonstrate commitment to helping underserved communities are strongly encouraged to apply.
All UCR undergraduate students, including new admits and transfer students, are eligible to apply. Admission is based upon a review of the application and interview. Once admitted, MSP students participate in the program throughout their undergraduate career.
Benefits of the Medical Scholars Program
The Medical Scholars Program provides students with a series of enrichment activities that hone their academic skills, expose them to a wide array of campus opportunities, and help them to become excellent candidates for continuing education in the health fields. Benefits include:
Academic Support
- Peer mentors & transfer ambassadors.
- Faculty and staff mentors and advisors.
- Academic coaches for science and math classes.
- Community college transfer student support.
- Study skills workshops.
- Advising nights.
- Community center for independent and group study sessions.
Research Opportunities
- Eight-week, full-time paid summer research internships with UCR faculty.
- Part-time academic year research program.
- Annual research symposium.
Professional Career Development
- Career planning workshops.
- Seminars and workshops on the graduate and professional school application process.
- Leadership development.
- Community service opportunities.
- Seminars and speaker programs with faculty and clinicians on community medicine and health disparities.
- Community meetings and student networking.
Contact Information
Have a question? Contact us at<EMAIL_ADDRESS>or call us at<PHONE_NUMBER>
Our office is located in the Biomedical Teaching Complex - Unit 1, near the School of Medicine Education Building


{% comment %} Form to update fileds related to how a project is executed. {% endcomment %} {% with tier=account.tier %}


The OI is the operator interface. It connects the buttons and joysticks that the operator uses to the commands which they should trigger. The buttons in the OI make it really easy to change the functions that each button performs as you test the code and add new commands to make the operators job easier.
There are a number of buttons that can be used to trigger commands.
| Button | Class |
|---|---|
| JoystickButton | A button on a joystick. This is probably the most useful type of button. |
| InternalButton | A virtual button that can be triggered in code or put on the SmartDashboard. |
| NetworkButton | A button that is triggered by a value on a network table. This is useful for allowing code not on the roboRIO to trigger commands. |
| Custom | Custom buttons can be created by subclassing Button and overriding the isPressed method. |


Open displays
Team names
Who's playing?
Goal score:
Ready?
Round #{{ roundNumber + 1 }}
Round type
Scoring
Scores: ({{ teamNames[0] || defaultTeamNames[0] }} {{ score[0] }}) vs ({{ teamNames[1] || defaultTeamNames[1] }} {{ score[1] }}) ~~Holdover: {{ holdoverScore }} ~~
Ready?
Clock
Time: {{ actingSeconds }}Words
Puzzle
Phrase: {{ curPuzzlePhrase }}Answer: {{ curPuzzleAnswer }}


Komodo
talk-trading
A channel to discuss trading. For useful links and more info click the pinned messages to the right.
100 messages
Before 05-Dec-19 12:00 AM
Neko
07-Aug-19 07:21 PM
yup
phideas
07-Aug-19 07:32 PM
there is a chance... altcoin dominance
https://twitter.com/Beastlyorion/status/1159170139587305473?s=19
Beastlorion (@Beastlyorion)
Altcoins aren't dead. They're only sleeping.
Markus
07-Aug-19 07:33 PM
its like right on the line
bounce incoming?!
Lanii
07-Aug-19 07:33 PM
What if support breaks
Markus
07-Aug-19 07:34 PM
quite heavy support line
since mid 2014
should not break easily
Lanii
07-Aug-19 07:35 PM
no it should not
not on first test
Markus
07-Aug-19 07:35 PM
and tbh it would just make sense to bounce up from it cause btc cant stay dominant forever
But we will see
Lanii
07-Aug-19 07:37 PM
Things like "it makes sense and it has to do a specific thing or not" is kinda meh
Caglio
07-Aug-19 07:37 PM
wow people drawing charts
Lanii
07-Aug-19 07:37 PM
I've realized markets need to do fuck all
Caglio
07-Aug-19 07:37 PM
chart chart
a little bit of a chart
c an we draw a chart kind sir ?
lets draw some triangles on our chart
im getting drugged soon again
i will draw triangles on paper and show you my work tommorow
Lanii
07-Aug-19 07:38 PM
Whats the point of hanging on a trading chat and bashing TA buddy?
(edited)
Caglio
07-Aug-19 07:38 PM
I expect to be paid
people and their charts
I am on work, its kinda boring
So I visited my friend and family @ komodo
#talk-trading
channel
dan.
07-Aug-19 07:43 PM
@Lanii
@Markus
interesting. I was about to ask if TA for alt market cap is even a relevant thing, but, that looks pretty convincing that it is.
Lanii
07-Aug-19 07:43 PM
I was thinking the same at first but looks decent to me aswell
(edited)
Caglio
07-Aug-19 07:44 PM
Lanii, am I allowed to be here now when I explained myself to you, kind sir ?
Lanii
07-Aug-19 07:44 PM
ofc you are but Im just gonna block you =/
dan.
07-Aug-19 07:45 PM
i dont quite understand the y axis, it seems log but its like, different sizes? maybe this is misleading
something is not right with the y axis or am i crazy
Lanii
07-Aug-19 07:49 PM
No I think its proper
I can't find the ticker for this chart
(edited)
dan.
07-Aug-19 07:50 PM
alright
Gordon Komodo
07-Aug-19 07:55 PM
Equalizer is done for
Caglio
07-Aug-19 08:00 PM
How do you mean done ?
That means we wont be able to build houses in zimbabwe using the coin ?
Shit, how is that possible
First we lost that amazing party project
I forgot the name, but you know, the one where you can visit lovely country of Myanmmar, and pay to watch local pop star with a coin
Now this
Shit
We need some amazing new eco system project
scytale
07-Aug-19 08:01 PM
and new smart chain
Caglio
07-Aug-19 08:02 PM
^ cant hurt
scytale
07-Aug-19 08:02 PM
minable if possible xD
mrtzmp3
07-Aug-19 08:02 PM
@Caglio
TNB ???
Time new bank
dan.
07-Aug-19 08:02 PM
seems like equalizer is shifting their business model if you look at their channel gateway
https://cdn.discordapp.com/attachments/455787938673065984/608205606888931340/file_139.jpg
(edited)
Caglio
07-Aug-19 08:02 PM
I dont really know what that is
Markus
07-Aug-19 08:03 PM
Cant find that ticker either
Caglio
07-Aug-19 08:03 PM
But yeah we should make a new great idea
That this world needs
1
I would like to make a postal office coin
Postal office in Croatia is a total mess
Would be amazing if there is a coin involved, so we make even more mess to the ladies working there
mrtzmp3
07-Aug-19 08:04 PM
@Caglio
in which country are you mate
If I can ask
Caglio
07-Aug-19 08:04 PM
They are already messed up, but I still leave the postal office after 30-45 minutes
Gordon Komodo
07-Aug-19 08:04 PM
IT seems someone in the project run away with the funds raised
1
Caglio
07-Aug-19 08:04 PM
Croatia
mrtzmp3
07-Aug-19 08:04 PM
Ok
Nice
scytale
07-Aug-19 08:04 PM
lovely country
Caglio
07-Aug-19 08:04 PM
Yes wonderful
mrtzmp3
07-Aug-19 08:04 PM
I bet
scytale
07-Aug-19 08:05 PM
in june i visited split
dan.
07-Aug-19 08:05 PM
thats a country not mentioned often in our bubbles
Caglio
07-Aug-19 08:05 PM
Oh nice
dan.
07-Aug-19 08:05 PM
looks beautiful
Caglio
07-Aug-19 08:05 PM
I love Split, people there are so hostile
1
The best hooligans are there
Markus
07-Aug-19 08:05 PM
@Gordon Komodo
what u mean
Caglio
07-Aug-19 08:05 PM
I feel like home every time I visit
scytale
07-Aug-19 08:05 PM
especially with plebs
Caglio
07-Aug-19 08:05 PM
Ultra festival is hosted there
Gordon Komodo
07-Aug-19 08:06 PM
@Markus
check the announcement on equalizer discord
mrtzmp3
07-Aug-19 08:06 PM
@Caglio
omg dude
You one of those brainfarts
??
Markus
07-Aug-19 08:06 PM
whats equalizer?
scytale
07-Aug-19 08:06 PM
new asset chain?
 It is gone.