diff --git a/fonts/slate-33847ce5.woff b/fonts/slate-33847ce5.woff new file mode 100644 index 00000000000..1e72e0ee001 Binary files /dev/null and b/fonts/slate-33847ce5.woff differ diff --git a/fonts/slate-7b7da4fe.ttf b/fonts/slate-7b7da4fe.ttf new file mode 100644 index 00000000000..ace9a46a7e1 Binary files /dev/null and b/fonts/slate-7b7da4fe.ttf differ diff --git a/fonts/slate-cfc9d06b.eot b/fonts/slate-cfc9d06b.eot new file mode 100644 index 00000000000..13c4839a197 Binary files /dev/null and b/fonts/slate-cfc9d06b.eot differ diff --git a/fonts/slate-ddd488db.woff2 b/fonts/slate-ddd488db.woff2 new file mode 100644 index 00000000000..7c585a72737 Binary files /dev/null and b/fonts/slate-ddd488db.woff2 differ diff --git a/fonts/slate-e55b8307.svg b/fonts/slate-e55b8307.svg new file mode 100644 index 00000000000..5f34982306b --- /dev/null +++ b/fonts/slate-e55b8307.svg @@ -0,0 +1,14 @@ + + + +Generated by IcoMoon + + + + + + + + + + diff --git a/images/logo-5d0c5f50.png b/images/logo-5d0c5f50.png new file mode 100644 index 00000000000..0f6cc6bfc31 Binary files /dev/null and b/images/logo-5d0c5f50.png differ diff --git a/images/navbar-cad8cdcb.png b/images/navbar-cad8cdcb.png new file mode 100644 index 00000000000..df38e90d87e Binary files /dev/null and b/images/navbar-cad8cdcb.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000000..9ff480b6087 --- /dev/null +++ b/index.html @@ -0,0 +1,3137 @@ + + + + + + + + Peek Plus API + + + + + + + + + + + NAV + Navbar + + +
+ +
+ graphql +
+ + + + +
+
+
+
+

Introduction

+

Welcome to the PeekPlus GraphQL API!

+ +

You can use our API to access thousands upon thousands of things to do, curated by us.

+ +

With the PeekPlus API you can

+ + +
💥💥  One Endpoint  💥💥
+https://api.peek.com/gql
+

Why GraphQL?

+

We chose GraphQL over some older standards because it is the best tool for us to expose our data to you in an elegant, self-documenting, flexible and performant way.

+ +

If you are new to GraphQL: we are confident you will never think about APIs the same way again.

+ +

If you are already familiar with GraphQL: we can feel your excitement; we're right there with you.

+

Smaller, Customizable Payloads

+

In a traditional "here is the endpoint to return activities" scenario, the original creators would include everything they felt "reasonable" - maybe something like:

+ + + +

Then someone comes along and makes a compelling case for exposing the location. So, for them, we add a few new fields for lat and lng.

+ +

Then someone comes along later and asks for review meta data because they want to expose it. Reasonable. So again we go and add a few new fields for the count and average_rating.

+ +

Then someone comes along and says they want a field that is actually pretty heavy. They are aware that it is heavier but are comfortable only asking for a few activities. So we add it.

+ +

Now the original users who just want the name and description are telling us the api is too slow; they were querying for a ton of activities and that heavy field is now a problem. So we hack together some query params where you can white-list fields:

+ +

http://example.com/activities?fields=name,description...

+ +

Great, but when you ask for activities, we actually want to also be able to get the tickets.. so now you are all

+ +

http://example.com/activities?fields=name,description,tickets.name...

+ +

..and everything starts to feel really dirty.

+ +

With GraphQL, we simply expose our object graph:

+ + + +

And you, the owner of your experience, ask for what you need and we return it to you. Simple as that. Furthermore, if you find your self wanting 4 or 5 different things, you can ask for them all at once saving many round trips to the server.

+ +

Wins. All. Around.

+

Strongly Typed

+

With a traditional REST API, you find yourself stringing together complex query params to filter content:

+ +

http://example.com/activities?sort=price&filter[state]=NY...

+ +

Inevitably the question comes in "what are possible values for SORT", or "what should I use for the STATE?". In those traditional APIs, you'd be digging for the email that linked to the docs or some light guessing and checking. It is then up to the api server to gracefully handle all possible mistakes to get you a reasonable error message if you deviate from what's expected. This is a lot of work for both parties, and is error prone.

+ +

With GraphQL, every query is Strongly Typed - you get immediate feedback of what the value can be, and if you deviate from it, the request doesn't even make it to our application logic; you are immediately given a good error explaining your mistake.

+ +

My client is catching a typo for me:

+ +

image

+

Self Documenting

+

Piggy-backing on the strongly type point from above, GraphQL was written from the ground up to be easy to "introspect". There are a host of great free clients out there; we are big fans of https://insomnia.rest/graphql/ - simply by downloading that client and pointing to our sandbox url, you have every query, field and mutation documented. We find crafting your queries there and then moving them into your app is a solid way to work.

+ +

image

+

Further Reading

+ +

Authentication

JWT

+

When you are granted access to the API, you will be given an Api Key ("your-api-key") and a Secret ("your-secret"). Every request you make will require you to create a JWT that includes your API Key in the sub field and a unique ID in the jti field, which is then signed w/ your secret:

+ +

{"sub": "your-api-key", "jti": "unique-id", "exp": 1516239022}

+ +

If you're new to JWTs, https://jwt.io/ is a GREAT place to start:

+ +

image

+
defmodule Token do
+  use Joken.Config
+
+  @doc """
+  Generate a signed token w/ default claims
+  """
+  def generate do
+    {:ok, claims} =
+      # NOTE: Joken automatically adds a uniq `jti` + `exp` for every token generated.
+      Token.generate_claims(%{
+        "sub" => "your-api-key"
+      })
+
+    {:ok, token, _claims} = encode_and_sign(claims, signer())
+
+    token
+  end
+
+  defp signer, do: Joken.Signer.create("HS256", "your-secret")
+end
+
+Token.generate()
+
+

The reason we chose JWT is because there exists a client for (nearly?) every language imaginable. No need to write your own logic, just find the library (all listed on the above site) for your language and it should be straightforward from there.

+ +

We are an Elixir Shop, so our library of choice is called Joken; on the right is how you might choose to implement the above w/ Joken.

+

Add Token as Header

+

The Token you generated above has to be included in the header for every request:

+ +

Authorization: Bearer TOKEN

+ + + + +

Idempotency

+

Since every request that you make must contain a unique request id inside the signed token, if you make a second request with the same request id we will assume this you replaying a request and will return the original response.

+ + +

Versioning

+

Another advantage of GraphQL is that the need for versioning largely goes away; the schema evolves overtime without the need for strict versions.

+

Backwards Compatible Changes

+

99% of our GraphQL changes are backwards compatible; they involve deprecating a field which just results in a warning if used but doesn't stop working. Or it's a new field altogether and since you aren't asking for it, it doesn't affect you.

+ +

image

+

Breaking Changes

+

We do everything possible to avoid these, and at the time of writing this, see no reason why we'll ever have them. That said, let's say a field has been deprecated for 6 months and an integration continues to use it even after being told that it's going away, eventually that field will have to go, which yes, would be a breaking change. Beyond this we don't see a reason why we can't evolve this API through clean deprecations. We will notify all clients using deprecated fields of the potential breaking change and give ample time to update before removing completely.

+

Entities

+ +

Activity

+

An Activity represents something people do to have fun. An Activity have a list of dates, the date when an instance of an Activity occurs. And, each date, have a list of times, the specific times for the given date when the activity starts and ends.

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescription
idid
The unique identifier for the object.
namestring
The name of the activity.
datesarray<AvailabiltyDate>
List of dates when the activity occurs.
ticketsarray<Ticket>
List of the supported tickets types for the activity.
requiresAdultboolean
Indicates if the quote must have 1 Adult or 1 Senior or 1 Traveler ticket types along the selected tickets sent.
minTravelersPerBookinginteger
Regarding all the ticket types and quantities selected, you must, at least, have this number of travelers selected for the booking.
maxTravelersPerBookinginteger
Regarding all the ticket types and quantities selected, you must, at most, have this number of travelers selected for the booking.
+

ActivityVariant

+

An ActivityVariant is a variation for the Activity that represents little differences between the original activity.

+ +

Any particular activity may consist of a number of variants, each of which might represent different departure times, tour routes, or packaged extras like additional meals, transport and so forth.

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + +
AttributeDescription
idid
The unique identifier for the object.
titlestring
Human readable text with the short name of the variant.
descriptionstring
Human readable text that contains specific information and details about the variant.
+

ActivityVariantQuestion

+

An ActivityVariantQuestion is a booking question that may be required to answer abd represents vital information specified by the supplier about the individual travelers or the group as a whole to be sent to the supplier as part of the request in order to complete a booking.

+ +

Implementations (or Types)

+ + + + + + + + + + + + + + + + + + + + + + + + +
Type name
StringQuestion
DateQuestion
TimeQuestion
SingleChoiceQuestion
LocationQuestion
NumberAndUnitQuestion
+ +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescription
idid
The unique identifier for the question. This must be sent with the answers when booking an activity.
requiredboolean
Indicates if answering the question is required (true) or not (false).
grouparray<ActivityVariantQuestionGroup>
Indicates how the question should be answered: once PER_TRAVELER or once PER_BOOKING.
hintstring
A string that contains information on how the field is expected to be answered. It may be not present.
labelnon-null string
A string that contains the human readable name of the question being asked. Examples: First Name, Last Name, Pickup Location, etc.
+ +

Other fields may be present depending on the question type. These are the specific fields for each question type:

+

StringQuestion

+

Attributes

+ + + + + + + + + + + +
AttributeDescription
max_lengthinteger
The maximum allowed length for the answer to this question.
+ +

Validation

+ +

The answer to this question must be a string that have at most max_length in size.

+

DateQuestion

+

Attributes

+ +

no other attributes present

+ +

Validation

+ +

The answer to this question must be a valid string representing a "Date" in the format described by ISO 8601:2019.

+

TimeQuestion

+

no other attributes present

+ +

Validation

+ +

The answer to this question must be a valid string representing a "Local time" in the format described by ISO 8601:2019.

+

SingleChoiceQuestion

+

Attributes

+ + + + + + + + + + + +
AttributeDescription
optionsarray<ActivityVariantQuestionOption>
The unique identifier for the question. This must be sent with the answers when booking an activity.
+ +

Validation

+ +

The answer to this question must be a string that is contained within the provided options value attribute.

+

LocationQuestion

+

Attributes

+ + + + + + + + + + + + + + + +
AttributeDescription
max_lengthinteger
The maximum allowed length for the answer to this question.
optionsarray<ActivityVariantQuestionOption>
The unique identifier for the question. This must be sent with the answers when booking an activity.
+ +

Validation

+ +

The answer to this question must be a string that is contained within the provided options value attribute.

+

NumberAndUnitQuestion

+

Attributes

+ + + + + + + + + + + +
AttributeDescription
unitsarray<string>
List of units for the question. The selected unit must be sent together with the answer for this type of question.
+ +

Validation

+ +

The answer to this question must be a string that correctly represents a number (1000, 105.56, 0.1234 are valid numbers) and the unit must be one of the values contained withing the units array.

+

ActivityVariantQuestionGroup

+

Indicates how the question should be answered: once PER_TRAVELER or once PER_BOOKING.

+ +

Values

+ + + + + + + + + + + + + + + +
ValueDescription
PER_BOOKINGIndicates that the answer to the question must be answered for each traveler, i.e., answered once per ticket added to the quote .
PER_TRAVELERIndicates that the answer to the question must be answered for the booked group as a whole, i.e., answered once per booking.
+

ActivityVariantQuestionOption

+

An ActivityVariantQuestionOption represents a possible answer for a given question inside a list of possible answers (or options). Each option may have a list of followup questions, i.e. questions that must be answered for a given answer to the parent question of this option.

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + +
AttributeDescription
namestring
Human readable text that indicates the value of this option.
valuestring
The actual value for the option that must be sent as an answer for the parent question.
questionsarray<ActivityVariantQuestion>
A list of follow up questions for the option, the may or may not be required to answer (based on each follow up question required attribute)
+

AvailabilityDate

+

An AvailabilityDate is the representation of a date when an Activity occurs. For a given date, multiple AvailabilityTime can be related to the same date, indicating possible start and end times for the activity on the given date.

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + +
AttributeDescription
datestring
Human readable text that indicates the value of this option.
isAvailablestring
The actual value for the option that must be sent as an answer for the parent question.
timesarray<AvailabilityTime>
A list of follow up questions for the option, the may or may not be required to answer (based on each follow up question required attribute)
+

AvailabilityTime

+

An AvailabilityTime represents a start and an end time for a given date when the parent Activity happens.

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescription
idstring
The unique identifier for this object.
localDateTimeStartstring
NaiveDateTime ISO8601 formatted string that indicates which date and time the activity starts, without timezone.
localDateTimeEndstring
NaiveDateTime ISO8601 formatted string that indicates which date and time the activity ends, without timezone.
statusAvailabilityTimeStatus
If the given time is available and if not, why.
variantActivityVariant
The activity variant that have the availability for this specific time.
+

AvailabilityTimeStatus

+

The status of a given AvailabilityTime.

+ +

Values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
AVAILABLECurrently available for sale, but has a fixed capacity.
CLOSEDCurrently not available for sale, but not sold out (e.g. temporarily on stop-sell) and may be available for sale soon.
FREESALEAlways available.
LIMITEDCurrently available for sale, but has a fixed capacity and may be sold out soon.
SOLD_OUTCurrently sold out, but additional availability may free up.
+

CancellationReason

+

The reason for the cancellation.

+ +

Values

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
BOOKED_WRONG_TOUR_DATEBooked the wrong tour date.
CANCELED_ENTIRE_TRIPCancelled the entire trip.
CHOSE_A_DIFFERENT_CHEAPER_TOURChose a different but cheaper tour.
DUPLICATE_BOOKINGDuplicate booking.
SIGNIFICANT_GLOBAL_EVENTSignificant global event.
SUPPLIER_NO_SHOWSupplier no show.
UNEXPECTED_MEDICAL_CIRCUMSTANCESUnexpected medical circumstances.
WEATHERWeather.
+

Ticket

+

A Ticket represents the supported ticket type for a given Activity, which may have different configurations and prices supported by the activity provider. They can be Adult, Child, Traveler, etc

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + +
AttributeDescription
idstring
The unique identifier for this object.
namestring
The name that represents the ticket, like Adult, Child, Traveler, etc.
minQuantityinteger
The minimum number of this ticket that can be booked at once.
maxQuantityinteger
The maximum number of this ticket that can be booked at once.
+

Queries

+

As mentioned earlier, the source of truth for what's available can be browsed from directly inside your GraphQL Client. Duplicating and maintaining the spec would defeat the advantages of GraphQL. With that in mind, this section will be very high level to help shape your understanding of what's available, not the source of truth.

+

Activities

+

The Activities query is the most powerful query in the API in that it can be used for two major use-cases:

+ +
    +
  1. Provide activities based on filters/sorting (location / price / keywords / etc). This could power real-time experiences where you need very specific activities for a given use-case.
  2. +
  3. You want to "ingest" our entire inventory through crawling every page of the results, pulling every field that is of importance to you.
  4. +
+
query Activities($filter: ActivitiesFilter!, $pagination: Pagination!, $sort: ActivitySort) {
+  activities(filter: $filter, pagination: $pagination, sort: $sort) {
+    entries {
+      name
+    }
+  }
+}
+
+

For the purposes of this example, let's say you just need each Activity's name. Your query for both use-cases would be identical.

+ +

In the two examples above, the main difference is what you pass in for variables. For a very specific query you'd pass in filters and sort values based on your desires. For crawling the whole inventory, you'd also likely not include any filters and you'd ask for totalPages so you can crawl through all of them, etc.

+ +
+

Example Response:

+
+
{
+  "activities": [{
+    "entries": [
+      { "name": "Activity 1" },
+      { "name": "Activity 2" },
+    ]
+  }]
+}
+

Availability

+

Determining whether something is available can be thought of as a two part process.

+ +
    +
  1. Get high-level cacheable dates + times to get an idea of, roughly speaking, when a given activity is available.
  2. +
  3. Given a specific set of tickets (1x Adult, 2x Child) for a specific time, is it available and what will the price be.
  4. +
+ +

The first is what we're going to talk about here. The second is in the next section as we call that a BookingQuote Mutation.

+ + + +

See ActivityVariants.

+ + +
query DocExampleGetActivityById($id: ID!, $startDate: Date!, $endDate: Date!, $quantity: Int) {
+  activity(id: $id) {
+    name
+    dates(startDate:$startDate, endDate: $endDate, quantity: $quantity) {
+      date
+      times {
+        id
+        localDateTimeStart
+        localDateTimeEnd
+        status
+        variant {
+          id
+          title
+          description
+        }
+      }
+    }
+  }
+}
+
+

With GraphQL, pulling availability is simply a "field" you can request for an activity.

+ +

Notice with GraphQL, "fields" can accept arguments (in this case the desired availability).

+ +

The power of the above is that you can do the exact same thing with a search result and in a single query to the server, answer the question "What are the top 10 things to do close by and what dates/times are available for them".

+ + +

ActivityVariants

+

An ActivityVariant is a variation for the Activity that represents little differences between the original activity.

+ +

Any particular activity may consist of a number of variants, each of which might represent different departure times, tour routes, or packaged extras like additional meals, transport and so forth.

+ +

Attributes

+ + + + + + + + + + + + + + + + + + + +
AttributeDescription
idid
The unique identifier for the activity variant.
titlestring
Human readable text with the short name of the variant.
descriptionstring
Human readable text that contains specific information and details about the variant.
+
fragment SimpleOptionsFields on ActivityQuestionOption {
+    name
+    value
+}
+
+fragment CompleteOptionsFields on ActivityQuestionOption {
+    name
+    questions {
+        __typename
+        id
+        group
+        required
+        label
+        hint
+
+        ... on NumberAndUnitQuestion {
+            units
+        }
+
+        ... on LocationQuestion {
+            allowCustomPickup
+            maxLength
+            options {
+                ...SimpleOptionsFields
+            }
+        }
+
+        ... on SingleChoiceQuestion {
+            options {
+                ...SimpleOptionsFields
+            }
+        }
+
+        ... on StringQuestion {
+            maxLength
+        }
+    }
+    value
+}
+
+query DocExampleGetActivityVariantById($id: ID!) {
+    activityVariant(id: $id) {
+        ... on ActivityVariant {
+            title
+            description
+            questions {
+                __typename
+                id
+                group
+                required
+                label
+                hint
+
+                ... on NumberAndUnitQuestion {
+                    units
+                }
+
+                ... on LocationQuestion {
+                    allowCustomPickup
+                    maxLength
+                    options {
+                        ...SimpleOptionsFields
+                    }
+                }
+
+                ... on SingleChoiceQuestion {
+                    options {
+                        ...CompleteOptionsFields
+                    }
+                }
+
+                ... on StringQuestion {
+                    maxLength
+                }
+            }
+        }
+    }
+}
+

CreateBookingQuote

+

A quote holds a set of inventory while locking in a price. You can think of a quote as a draft booking or a reservation.

+ +

There are times when something you thought would be available based on the Availability Calls is not available when making the quote.

+ +

This can happen for a few reasons:

+ +

1) The availability call was out of sync. Given this makes a real-time call to check the supplier's inventory, there's always a window where our initial call returned availability but this call didn't. Our goal is to make this window as small as possible

+ +

2) Certain suppliers have very complex rules on how they accept bookings. It might be that your specific tickets aren't available, or there are complex rules around time-cutoffs.

+ +

3) There are ticket rules to respect when asking for a quote. The specific activity and ticket fields are described below and how they affect the mutation result:

+

Activity

+ + + + + + + + + + + + + + + + + + +
AttributeDescription
requiresAdultboolean
Indicates if the quote must have 1 Adult or 1 Senior or 1 Traveler ticket types along the selected tickets sent.
maxTravelersPerBookinginteger
Regarding all the ticket types and quantities selected, you must, at least, have this number of travelers selected for the booking.
minTravelersPerBookinginteger
Regarding all the ticket types and quantities selected, you must, at most, have this number of travelers selected for the booking.
+

Ticket

+ + + + + + + + + + + + + + +
AttributeDescription
minQuantityinteger
The minimum number of this ticket that can be booked at once.
maxQuantityinteger
The maximum number of this ticket that can be booked at once.
+ +

With those caveats aside, making these requests might look like this:

+
mutation CreateQuote($request: BookingQuoteInput!) {
+  createBookingQuote(quoteInput: $request) {
+    __typename
+    ... on BookingQuote {
+      id
+      priceBreakdown {
+        price {
+          formatted
+        }
+        total {
+          formatted
+        }
+        taxes {
+          formatted
+        }
+      }
+      snapshot {
+        activity {
+          variant {
+            id
+            title
+          }
+        }
+      }
+    }
+    ... on Error {
+      message
+    }
+  }
+}
+
+
+

Request variables

+
+
{
+  "request": {
+    "availabilityTimeId": "<available-time-id>",
+    "tickets": [
+      {
+        "quantity": 4,
+        "ticketId": "<ticket-id>"
+      }
+    ]
+  }
+}
+
+
+

And a Response like this

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BookingQuote",
+      "id": "<booking-quote-id>",
+      "priceBreakdown": {
+        "price": {
+          "formatted": "$620.00"
+        },
+        "taxes": {
+          "formatted": "$0.00"
+        },
+        "total": {
+          "formatted": "$620.00"
+        }
+      },
+      "snapshot": {
+        "activity": {
+          "variant": {
+            "id": "<variant-id>",
+            "title": "Solvang Food and Photo Tour"
+          }
+        }
+      }
+    }
+  }
+}
+

CreateBookingQuote Errors

BadRequestError

+

Given the provided activity properties on the side and summarized below, we will show different inputs with values that do not match the activity and/or tickets requirements, with the according error messages for each one:

+ +
+

Activity Response

+
+
{
+  "data": {
+    "activities": {
+      "entries": [
+        {
+          "id": "<activity-id>",
+          "maxTravelersPerBooking": 10,
+          "minTravelersPerBooking": 2,
+          "name": "Solvang Food & Photo Tour: Explore Danish Cuisine & Photography in Santa Ynez Valley",
+          "requiresAdult": true,
+          "tickets": [
+            {
+              "id": "<adult-ticket-id>",
+              "maxQuantity": 10,
+              "minQuantity": 1,
+              "name": "Adult"
+            },
+            {
+              "id": "<youth-ticket-id>",
+              "maxQuantity": 4,
+              "minQuantity": 0,
+              "name": "Youth"
+            }
+          ]
+        }
+      ],
+      "pageNumber": 1,
+      "pageSize": 200,
+      "totalEntries": 1,
+      "totalPages": 1
+    }
+  }
+}
+

Activity

+ + + + + + + + + + + + + + + + + + +
AttributeValue
requiresAdulttrue
minTravelersPerBooking2
maxTravelersPerBooking10
+

Adult Ticket

+ + + + + + + + + + + + + + +
AttributeValue
minQuantity1
maxQuantity10
+

Youth Ticket

+ + + + + + + + + + + + + + +
AttributeValue
minQuantity0
maxQuantity4
+

"Requires at least one adult or senior"

+

When it happens?

+ +

Not providing the ADULT ticket, only the YOUTH ticket.

+ + + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requestfalse
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request2
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request0
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request2
+ +
+

Request input

+
+
{
+  "request": {
+    "availabilityTimeId": "<available-time-id>",
+    "tickets": [
+      {
+        "quantity": 2,
+        "ticketId": "<youth-ticket-id>"
+      }
+    ]
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Requires at least one adult or senior"
+    }
+  }
+}
+

"Minimum # of guests is <num> and requires at least one adult or senior"

+

When it happens?

+ +

Not providing the ADULT ticket and not meeting the minTravelersPerBooking for the activity.

+ + + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requestfalse
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request1
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request0
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request1
+ +
+

Request input

+
+
{
+  "request": {
+    "availabilityTimeId": "<available-time-id>",
+    "tickets": [
+      {
+        "quantity": 1,
+        "ticketId": "<youth-ticket-id>"
+      }
+    ]
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Minimum # of guests is 2 and requires at least one adult or senior"
+    }
+  }
+}
+

"Minimum # of guests for ticket '<ticket-id>' is <num>"

+

When it happens?

+ +

Providing the ADULT ticket, the YOUTH ticket and not meeting the minQuantity for the YOUTH ticket.

+ + + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requesttrue
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking3 - 10
Quantity sent on Request2
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request1
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity2 - 4
Quantity sent on Request1
+ +
+

Request input

+
+
{
+  "request": {
+    "availabilityTimeId": "<available-time-id>",
+    "tickets": [
+      {
+        "quantity": 1,
+        "ticketId": "<adult-ticket-id>"
+      },
+      {
+        "quantity": 1,
+        "ticketId": "<youth-ticket-id>"
+      }
+    ]
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Minimum # of guests for ticket '<youth-ticket-id>' is 2"
+    }
+  }
+}
+

"Maximum # of guests for ticket '<ticket-id>' is <num>"

+

When it happens?

+ +

Providing the ADULT ticket, the YOUTH ticket and not meeting the maxQuantity for the YOUTH ticket.

+ + + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requesttrue
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request10
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request5
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request5
+ +
+

Request input

+
+
{
+  "request": {
+    "availabilityTimeId": "<available-time-id>",
+    "tickets": [
+      {
+        "quantity": 5,
+        "ticketId": "<adult-ticket-id>"
+      },
+      {
+        "quantity": 5,
+        "ticketId": "<youth-ticket-id>"
+      }
+    ]
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Maximum # of guests for ticket '<youth-ticket-id>' is 4"
+    }
+  }
+}
+

"Maximum # of guests is <num>"

+

When it happens?

+ +

Providing the ADULT ticket, the YOUTH ticket and not meeting the maxTravelersPerBooking for the activity.

+ + + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requesttrue
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request11
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request7
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request4
+ +
+

Request input

+
+
{
+  "request": {
+    "availabilityTimeId": "<available-time-id>",
+    "tickets": [
+      {
+        "quantity": 7,
+        "ticketId": "<adult-ticket-id>"
+      },
+      {
+        "quantity": 4,
+        "ticketId": "<youth-ticket-id>"
+      }      
+    ]
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Maximum # of guests is 10"
+    }
+  }
+}
+

UpdateBookingQuote

+

It is useful to update a quote as a customer changes the tickets, switches their desired time, add required booking question answers, etc.

+ + + +

This call is nearly identical to the CreateBookingQuote:

+
mutation EditBookingQuote($request: EditBookingQuoteInput!) {
+  editBookingQuote(input: $request) {
+    __typename
+    ... on BookingQuote {
+      id
+      priceBreakdown {
+        price {
+          formatted
+        }
+        taxes {
+         formatted
+        }
+        fees {
+          formatted
+        }
+        total {
+          formatted
+        }
+      }
+    }
+    ... on Error {
+      message
+    }
+  }
+}
+
+
+

Request variables

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 5,
+          "ticketId": "<ticket-id>"
+        }
+      ]
+    }
+  }
+}
+

Booking Questions

+

Some activities may require questions answers in order to be possible to book.

+ +

The questions may be

+ + + +

Let's consider the example on the side. You have the <available-time-id> with the <activity-variant-id> for which it belongs to. So you can query that specific ActivityVariant and see if there are questions that must be answered. See ActivityVariants do recall the query that produces the json output replicated on the side.

+ +
+

Request variables

+
+
{
+  "id": "<activity-variant-id>"
+}
+
+
+

Response

+
+
{
+  "data": {
+    "activityVariant": {
+      "description": "Skip the tourist traps and head out with a local foodie for a fun-filled, behind-the-scenes cultural food tour in the unique Danish village nestled in the heart of the Santa Ynez Valley (30 miles north of downtown Santa Barbara). \n\nOur Solvang food tour starts along Mission Drive and will walk you through the the downtown neighborhood streets where you will taste traditional Danish and local artisan food and drink unique to Solvang and the Central Coast. Indulge in bites of traditional Danish comfort fare and freshly baked goods as well as craft beer, local wine, & artisan eats. Along the way, you’ll get immersed in the local culture and hear interesting stories about each place you’ll visit.\n\nYou’ll also learn easy-to-shoot food photo tips from your pro tour guide on this foodie photography tour and take your photo skills to the next level using your smartphone’s camera app. By the end of your 3-4 hour tour, you’ll be eating like a local and shooting like a pro!",
+      "questions": [
+        {
+          "__typename": "DateQuestion",
+          "group": "PER_TRAVELER",
+          "hint": null,
+          "id": "<date-of-birth-question-id>",
+          "label": "Date of birth",
+          "required": true
+        },
+        {
+          "__typename": "StringQuestion",
+          "group": "PER_TRAVELER",
+          "hint": null,
+          "id": "<first-name-question-id>",
+          "label": "First name",
+          "maxLength": 50,
+          "required": true
+        },
+        {
+          "__typename": "StringQuestion",
+          "group": "PER_TRAVELER",
+          "hint": null,
+          "id": "<last-name-question-id>",
+          "label": "Last name",
+          "maxLength": 50,
+          "required": true
+        },
+        {
+          "__typename": "StringQuestion",
+          "group": "PER_BOOKING",
+          "hint": null,
+          "id": "<special-requirements-question-id>",
+          "label": "Special requirements",
+          "maxLength": 1000,
+          "required": false
+        },
+        {
+          "__typename": "SingleChoiceQuestion",
+          "group": "PER_BOOKING",
+          "hint": "Select the language you want for this tour",
+          "id": "<tour-language-question-id>",
+          "label": "Tour language",
+          "options": [
+            {
+              "followupQuestions": [],
+              "name": "English (Guide)",
+              "value": "GUIDE|en|en/SERVICE_GUIDE"
+            }
+          ],
+          "required": true
+        }
+      ]
+    }
+  }
+}
+
+

In order to be able to book this activity, i.e., send the quote id to the createBooking mutation and it succeeds, we will need to update the quote with the answers for each type of question.

+ +

As we can see:

+ + + + + +
+

For the updated graphql query below (with the answers fields added for the purpose of this documentation)

+
+
mutation DocExampleEditBookingQuote($request: EditBookingQuoteInput!) {
+  editBookingQuote(input: $request) {
+    __typename
+    ... on BookingQuote {
+      id
+      priceBreakdown {
+        price {
+          formatted
+        }
+        taxes {
+         formatted
+        }
+        fees {
+          formatted
+        }
+        total {
+          formatted
+        }
+      }
+      snapshot {
+        activity {
+          variant {
+            id
+            title
+          }
+          bookingAnswers {
+            question
+            answer
+          }
+        }
+        tickets {
+          id
+          quantity
+          guestsAnswers {
+            guestAnswers {
+              question
+              answer
+            }
+          }
+        }
+      }
+    }
+    ... on Error {
+      message
+    }
+  }
+}
+
+
+
+

The editBooking request variables would be like this:

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 2,
+          "ticketId": "<adult-ticket-id>",
+          "guestsAnswers": [
+            {
+              "guestAnswers": [
+                {
+                  "question": "<date-of-birth-question-id>",
+                  "answer": "Adult1 Date of Birth"
+                },
+                {
+                  "question": "<first-name-question-id>",
+                  "answer": "Adult1 First Name"
+                },
+                {
+                  "question": "<last-name-question-id>",
+                  "answer": "Adult1 Last Name"
+                }
+              ]
+            },
+            {
+              "guestAnswers": [
+                {
+                  "question": "<date-of-birth-question-id>",
+                  "answer": "Adult2 Date of Birth"
+                },
+                {
+                  "question": "<first-name-question-id>",
+                  "answer": "Adult2 First Name"
+                },
+                {
+                  "question": "<last-name-question-id>",
+                  "answer": "Adult2 Last Name"
+                }
+              ]
+            }
+          ]
+        }
+      ],
+      "bookingAnswers": [
+        {
+          "question": "<special-requirements-question-id>",
+          "answer": "No special requirements"
+        },
+        {
+          "question": "<tour-language-question-id>",
+          "answer": "GUIDE|en|en/SERVICE_GUIDE"
+        }
+      ]
+    }
+  }
+}
+
+
+

And the Response would be like

+
+
{
+  "data": {
+    "editBookingQuote": {
+      "__typename": "BookingQuote",
+      "id": "qb098ej",
+      "priceBreakdown": {
+        "fees": {
+          "formatted": "$0.00"
+        },
+        "price": {
+          "formatted": "$310.00"
+        },
+        "taxes": {
+          "formatted": "$0.00"
+        },
+        "total": {
+          "formatted": "$310.00"
+        }
+      },
+      "snapshot": {
+        "activity": {
+          "bookingAnswers": [
+            {
+              "answer": "No special requirements",
+              "question": "<special-requirements-question-id>"
+            },
+            {
+              "answer": "GUIDE|en|en/SERVICE_GUIDE",
+              "question": "<tour-language-question-id>"
+            }
+          ],
+          "variant": {
+            "id": "<activity-variant-id>",
+            "title": "Solvang Food and Photo Tour"
+          }
+        },
+        "tickets": [
+          {
+            "guestsAnswers": [
+              [
+                {
+                  "guestAnswers": [
+                    {
+                      "answer": "Adult1 Date of Birth",
+                      "question": "<date-of-birth-question-id>"
+                    },
+                    {
+                      "answer": "Adult1 First Name",
+                      "question": "<first-name-question-id>"
+                    },
+                    {
+                      "answer": "Adult1 Last Name",
+                      "question": "<last-name-question-id>"
+                    }
+                  ]
+                }
+              ],
+              [
+                {
+                  "guestAnswers": [
+                    {
+                      "answer": "Adult2 Date of Birth",
+                      "question": "<date-of-birth-question-id>"
+                    },
+                    {
+                      "answer": "Adult2 First Name",
+                      "question": "<first-name-question-id>"
+                    },
+                    {
+                      "answer": "Adult2 Last Name",
+                      "question": "<last-name-question-id>"
+                    }
+                  ]
+                }
+              ]
+            ],
+            "id": "<adult-ticket-id>",
+            "quantity": 2
+          }
+        ]
+      }
+    }
+  }
+}
+

UpdateBookingQuote Errors

BadRequestError

+

Given the provided activity properties on the side and summarized below, we will show different inputs with values that do not match the activity and/or tickets requirements, with the according error messages for each one:

+ +
+

Activity Response

+
+
{
+  "data": {
+    "activities": {
+      "entries": [
+        {
+          "id": "<activity-id>",
+          "maxTravelersPerBooking": 10,
+          "minTravelersPerBooking": 2,
+          "name": "Solvang Food & Photo Tour: Explore Danish Cuisine & Photography in Santa Ynez Valley",
+          "requiresAdult": true,
+          "tickets": [
+            {
+              "id": "<adult-ticket-id>",
+              "maxQuantity": 10,
+              "minQuantity": 1,
+              "name": "Adult"
+            },
+            {
+              "id": "<youth-ticket-id>",
+              "maxQuantity": 4,
+              "minQuantity": 0,
+              "name": "Youth"
+            }
+          ]
+        }
+      ],
+      "pageNumber": 1,
+      "pageSize": 200,
+      "totalEntries": 1,
+      "totalPages": 1
+    }
+  }
+}
+

Activity

+ + + + + + + + + + + + + + + + + + +
AttributeValue
requiresAdulttrue
minTravelersPerBooking2
maxTravelersPerBooking10
+

Adult Ticket

+ + + + + + + + + + + + + + +
AttributeValue
minQuantity1
maxQuantity10
+

Youth Ticket

+ + + + + + + + + + + + + + +
AttributeValue
minQuantity0
maxQuantity4
+

"Requires at least one adult or senior"

+

When it happens?

+ +

Not providing the ADULT ticket, only the YOUTH ticket.

+

Activity

+ + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requestfalse
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request2
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request0
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request2
+ +
+

Request input

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 2,
+          "ticketId": "<youth-ticket-id>"
+        }
+      ]
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "editBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Requires at least one adult or senior"
+    }
+  }
+}
+

"Minimum # of guests is <num> and requires at least one adult or senior"

+

When it happens?

+ +

Not providing the ADULT ticket and not meeting the minTravelersPerBooking for the activity.

+

Activity

+ + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requestfalse
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request1
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request0
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request1
+ +
+

Request input

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 1,
+          "ticketId": "<youth-ticket-id>"
+        }
+      ]
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "editBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Minimum # of guests is 2 and requires at least one adult or senior"
+    }
+  }
+}
+

"Minimum # of guests for ticket '<ticket-id>' is <num>"

+

When it happens?

+ +

Providing the ADULT ticket, the YOUTH ticket and not meeting the minQuantity for the YOUTH ticket.

+

Activity

+ + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requesttrue
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking3 - 10
Quantity sent on Request2
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request1
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity2 - 4
Quantity sent on Request1
+ +
+

Request input

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 1,
+          "ticketId": "<adult-ticket-id>"
+        },
+        {
+          "quantity": 1,
+          "ticketId": "<youth-ticket-id>"
+        }
+      ]
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Minimum # of guests for ticket '<youth-ticket-id>' is 2"
+    }
+  }
+}
+

"Maximum # of guests for ticket '<ticket-id>' is <num>"

+

When it happens?

+ +

Providing the ADULT ticket, the YOUTH ticket and not meeting the maxQuantity for the YOUTH ticket

+

Activity

+ + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requesttrue
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request10
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request5
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request5
+ +
+

Request input

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 5,
+          "ticketId": "<adult-ticket-id>"
+        },
+        {
+          "quantity": 5,
+          "ticketId": "<youth-ticket-id>"
+        }
+      ]
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "editBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Maximum # of guests for ticket '<youth-ticket-id>' is 4"
+    }
+  }
+}
+

"Maximum # of guests is <num>"

+

When it happens?

+ +

Providing the ADULT ticket, the YOUTH ticket and not meeting the maxTravelersPerBooking for the activity

+

Activity

+ + + + + + + + + + + + + + +
requiresAdulttrue
Sending ADULT ticket in requesttrue
+ + + + + + + + + + + + + + + +
Range minTravelersPerBooking - maxTravelersPerBooking2 - 10
Quantity sent on Request11
+

Adult Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity1 - 10
Quantity sent on Request7
+

Youth Ticket

+ + + + + + + + + + + + + + +
Range minQuantity - maxQuantity0 - 4
Quantity sent on Request4
+ +
+

Request input

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 7,
+          "ticketId": "<adult-ticket-id>"
+        },
+        {
+          "quantity": 4,
+          "ticketId": "<youth-ticket-id>"
+        }
+      ]
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "editBookingQuote": {
+      "__typename": "BadRequestError",
+      "message": "Maximum # of guests is 10"
+    }
+  }
+}
+

Invalid Questions Error

+

If you forget to provide required questions answers or provide invalid questions answers, you will receive the InvalidQuestionsError with details about the invalid questions detected.

+ + + +
+

Request (no required questions answers provided)

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "quoteInput": {
+      "availabilityTimeId": "<available-time-id>",
+      "tickets": [
+        {
+          "quantity": 2,
+          "ticketId": "<adult-ticket-id>"
+        }
+      ],
+      "bookingAnswers": [
+        {
+          "question": "<special-reqs-question-id>",
+          "answer": "No special requirements"
+        }
+      ]
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBooking": {
+      "__typename": "InvalidQuestionsError",
+      "message": "Missing guest answers for tickets: <ticket-id>. Missing required questions: <question1-id>, <question2-id>, ..., <questionN-id>"
+    }
+  }
+}
+

CreateBooking

+

This will create a booking out of a provided quote. At this point, your booking is submitted and there's nothing left to do on your end.

+
mutation CreateBooking($request: CreateBookingInput!) {
+  createBooking(input: $request) {
+    __typename
+    ... on Booking {
+      id
+    }
+    ... on Error {
+      message
+    }
+    ... on InvalidCustomerError {
+      invalidFields
+    }
+  }
+}
+
+
+

Request variables

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "customer": {
+      "name": "Product Demo",
+      "email": "valid.email.address@peek.com",
+      "phone": "0196488932",
+      "country": "US",
+      "postalCode": "94501"
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBooking": {
+      "__typename": "Booking",
+      "id": "<booking-id>"
+    }
+  }
+}
+

CreateBooking Errors

Invalid Customer

+

If you provide invalid customer details, you will receive the InvalidCustomerError with details about the invalid fields detected.

+ +
+

Request

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "customer": {
+      "name": "Product Demo",
+      "email": "invalid_email_address",
+      "phone": "0196488932",
+      "country": "US",
+      "postalCode": "94501"
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBooking": {
+      "__typename": "InvalidCustomerError",
+      "invalidFields": [
+        "email"
+      ],
+      "message": "Please provide valid customer details. Invalid: email."
+    }
+  }
+}
+

Invalid Questions Error

+

If you forget to provide required questions answers to the quote you want to proceed and make a booking for, you will receive the InvalidQuestionsError with details about the invalid questions detected.

+ +
+

Request

+
+
{
+  "request": {
+    "bookingQuoteId": "<booking-quote-id>",
+    "customer": {
+      "name": "Product Demo",
+      "email": "invalid_email_address",
+      "phone": "0196488932",
+      "country": "US",
+      "postalCode": "94501"
+    }
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "createBooking": {
+      "__typename": "InvalidQuestionsError",
+      "message": "Missing guest answers for tickets: <ticket-id>. Missing required questions: <question1-id>, <question2-id>, ..., <questionN-id>"
+    }
+  }
+}
+

Source Error

+

Sometimes, when creating a booking, the activity provider may have any kind of error while processing the booking request. In this case you will receive an error like this one.

+
{
+  "data": {
+    "createBooking": {
+      "__typename": "SourceError",
+      "message": "Something unexpected happened, please retry your request. Engineers are notified and will report back."
+    }
+  }
+}
+
+
+

Request variables

+
+
{
+  "request": {
+    "bookingQuoteId": "qb0nm9r",
+    "customer": {
+      "name": "Peek Plus Demo",
+      "email": "name@example.com",
+      "phone": "0196488932",
+      "country": "US",
+      "postalCode": "12345"
+    }
+  }
+}
+

CancelBooking

+

This will cancel the booking in our system and notify the provider that the customer will no longer be coming. We are assuming a refund will be issued on your end and update the customer in our system to indicate a refund has been granted.

+
mutation CancelBooking($input: CancelBookingInput!) {
+  cancelBooking(input: $input) {
+    __typename
+    ... on Booking {
+      status
+    }
+    ... on Error {
+      message
+    }
+  }
+}
+
+
+

Request variables

+
+
{
+  "input": {
+    "bookingId": "<booking-id>",
+    "cancellationReason": "WEATHER"
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "cancelBooking": {
+      "__typename": "Booking",
+      "status": "CANCELED"
+    }
+  }
+}
+
+ + +

See CancellationReason

+

CancelBooking Errors

CancellationRejectionError

+

If you do not provide a cancellationReason you will get this error.

+ +
+

Request variables

+
+
{
+  "input": {
+    "bookingId": "<booking-id>"
+  }
+}
+
+
+

Response

+
+
{
+  "data": {
+    "cancelBooking": {
+      "__typename": "CancellationRejectionError",
+      "message": "You must provide a valid cancellation reason when cancelling a booking."
+    }
+  }
+}
+

Webhooks

Booking Cancellation

+

Typically, when you send a booking into PeekPlus and the customer needs to +cancel, they will reach out to your company and your company will cancel the +booking. This cancellation will make its way to the underlying supplier to let +them know the customer will no longer be coming.

+ +

However, there are times when the supplier has to cancel the booking and they +need to let YOU know that it happened so you can do whatever it is you need to +on your end (refund the customer, update any records in your system, etc).

+ +

The first step is to reach out to your contact at PeekPlus and provide the url +to hit (for both sandbox and production) for these webhooks (ex +https://peekplus.example.com/webhooks).

+ +

Once that's been done, anytime we need to notify you of a cancellation, we will POST to [YOUR_URL_PROVIDED_ABOVE]/peek-plus-webhooks/bookings/[BOOKING_ID]/cancel.

+ +

For authentication we will send an auth header w/ a JWT that is signed w/ your +api key + secret; just like you send to us for your requests.

+ +

To test this process, we added the ability to "Trigger" one of these async +webhooks yourself:

+
mutation TriggerCancellationWebHook($bookingId: ID!) {
+  triggerCancellationWebHook(bookingId: $bookingId) {
+    message
+  }
+}
+
+

If you open your GQL Client, make a booking and then use the above mutation, +it'll give you real-time feedback on what your server returned to help you with +debugging.

+

Try It Out

+

Once you have been granted an API Key + API Secret click the button below.

+ +

This will get you an entire working api ready to click through.

+ + + + + +

Run in Insomnia}

+

Go Live Process

+ +

Updates

+ + + + + + + + + + + + + + + + + + + + + + +
DateDescription
Nov 6, 2023Removed section: Mutations. Added new sections: Entities CreateBookingQuote, CreateBookingQuote Errors, UpdateBookingQuote, UpdateBookingQuote Errors, CreateBooking, CreateBooking Errors, CancelBooking, CancelBooking Errors and Updates
Jun 7, 2022Added new sections: Go Live Process and Webhooks
May 13, 2020Added new section: Try It Out
Jan 31, 2020Initial Docs
+ +
+
+
+ graphql +
+
+
+ + diff --git a/javascripts/all-c5541673.js b/javascripts/all-c5541673.js new file mode 100644 index 00000000000..9eca788de26 --- /dev/null +++ b/javascripts/all-c5541673.js @@ -0,0 +1,131 @@ +!function(){if("ontouchstart"in window){var e,t,n,r,i,o,s={};e=function(e,t){return Math.abs(e[0]-t[0])>5||Math.abs(e[1]-t[1])>5},t=function(e){this.startXY=[e.touches[0].clientX,e.touches[0].clientY],this.threshold=!1},n=function(t){if(this.threshold)return!1;this.threshold=e(this.startXY,[t.touches[0].clientX,t.touches[0].clientY])},r=function(t){if(!this.threshold&&!e(this.startXY,[t.changedTouches[0].clientX,t.changedTouches[0].clientY])){var n=t.changedTouches[0],r=document.createEvent("MouseEvents");r.initMouseEvent("click",!0,!0,window,0,n.screenX,n.screenY,n.clientX,n.clientY,!1,!1,!1,!1,0,null),r.simulated=!0,t.target.dispatchEvent(r)}},i=function(e){var t=Date.now(),n=t-s.time,r=e.clientX,i=e.clientY,a=[Math.abs(s.x-r),Math.abs(s.y-i)],u=o(e.target,"A")||e.target,c=u.nodeName,l="A"===c,f=window.navigator.standalone&&l&&e.target.getAttribute("href");if(s.time=t,s.x=r,s.y=i,(!e.simulated&&(n<500||n<1500&&a[0]<50&&a[1]<50)||f)&&(e.preventDefault(),e.stopPropagation(),!f))return!1;f&&(window.location=u.getAttribute("href")),u&&u.classList&&(u.classList.add("energize-focus"),window.setTimeout(function(){u.classList.remove("energize-focus")},150))},o=function(e,t){for(var n=e;n!==document.body;){if(!n||n.nodeName===t)return n;n=n.parentNode}return null},document.addEventListener("touchstart",t,!1),document.addEventListener("touchmove",n,!1),document.addEventListener("touchend",r,!1),document.addEventListener("click",i,!0)}}(),/*! + * jQuery JavaScript Library v3.2.1 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright JS Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2017-03-20T18:59Z + */ +function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){"use strict";function n(e,t){t=t||ne;var n=t.createElement("script");n.text=e,t.head.appendChild(n).parentNode.removeChild(n)}function r(e){var t=!!e&&"length"in e&&e.length,n=ge.type(e);return"function"!==n&&!ge.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function i(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}function o(e,t,n){return ge.isFunction(t)?ge.grep(e,function(e,r){return!!t.call(e,r,e)!==n}):t.nodeType?ge.grep(e,function(e){return e===t!==n}):"string"!=typeof t?ge.grep(e,function(e){return ae.call(t,e)>-1!==n}):Ce.test(t)?ge.filter(t,e,n):(t=ge.filter(t,e),ge.grep(e,function(e){return ae.call(t,e)>-1!==n&&1===e.nodeType}))}function s(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function a(e){var t={};return ge.each(e.match(Le)||[],function(e,n){t[n]=!0}),t}function u(e){return e}function c(e){throw e}function l(e,t,n,r){var i;try{e&&ge.isFunction(i=e.promise)?i.call(e).done(t).fail(n):e&&ge.isFunction(i=e.then)?i.call(e,t,n):t.apply(undefined,[e].slice(r))}catch(e){n.apply(undefined,[e])}}function f(){ne.removeEventListener("DOMContentLoaded",f),e.removeEventListener("load",f),ge.ready()}function d(){this.expando=ge.expando+d.uid++}function p(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:He.test(e)?JSON.parse(e):e)}function h(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(Ie,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n=p(n)}catch(e){}Pe.set(e,t,n)}else n=undefined;return n}function g(e,t,n,r){var i,o=1,s=20,a=r?function(){return r.cur()}:function(){return ge.css(e,t,"")},u=a(),c=n&&n[3]||(ge.cssNumber[t]?"":"px"),l=(ge.cssNumber[t]||"px"!==c&&+u)&&_e.exec(ge.css(e,t));if(l&&l[3]!==c){c=c||l[3],n=n||[],l=+u||1;do{o=o||".5",l/=o,ge.style(e,t,l+c)}while(o!==(o=a()/u)&&1!==o&&--s)}return n&&(l=+l||+u||0,i=n[1]?l+(n[1]+1)*n[2]:+n[2],r&&(r.unit=c,r.start=l,r.end=i)),i}function m(e){var t,n=e.ownerDocument,r=e.nodeName,i=ze[r];return i||(t=n.body.appendChild(n.createElement(r)),i=ge.css(t,"display"),t.parentNode.removeChild(t),"none"===i&&(i="block"),ze[r]=i,i)}function v(e,t){for(var n,r,i=[],o=0,s=e.length;o-1)i&&i.push(o);else if(c=ge.contains(o.ownerDocument,o),s=y(f.appendChild(o),"script"),c&&x(s),n)for(l=0;o=s[l++];)Ue.test(o.type||"")&&n.push(o);return f}function w(){return!0}function T(){return!1}function S(){try{return ne.activeElement}catch(e){}}function E(e,t,n,r,i,o){var s,a;if("object"==typeof t){"string"!=typeof n&&(r=r||n,n=undefined);for(a in t)E(e,a,n,r,t[a],o);return e}if(null==r&&null==i?(i=n,r=n=undefined):null==i&&("string"==typeof n?(i=r,r=undefined):(i=r,r=n,n=undefined)),!1===i)i=T;else if(!i)return e;return 1===o&&(s=i,i=function(e){return ge().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=ge.guid++)),e.each(function(){ge.event.add(this,t,i,r,n)})}function C(e,t){return i(e,"table")&&i(11!==t.nodeType?t:t.firstChild,"tr")?ge(">tbody",e)[0]||e:e}function k(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function N(e){var t=rt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function j(e,t){var n,r,i,o,s,a,u,c;if(1===t.nodeType){if($e.hasData(e)&&(o=$e.access(e),s=$e.set(t,o),c=o.events)){delete s.handle,s.events={};for(i in c)for(n=0,r=c[i].length;n1&&"string"==typeof h&&!pe.checkClone&&nt.test(h))return e.each(function(n){var o=e.eq(n);g&&(t[0]=h.call(this,n,o.html())),L(o,t,r,i)});if(d&&(o=b(t,e[0].ownerDocument,!1,e,i),s=o.firstChild,1===o.childNodes.length&&(o=s),s||i)){for(a=ge.map(y(o,"script"),k),u=a.length;f=0&&nS.cacheLength&&delete e[t.shift()],e[n+" "]=r}var t=[];return e}function r(e){return e[_]=!0,e}function i(e){var t=q.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function o(e,t){for(var n=e.split("|"),r=n.length;r--;)S.attrHandle[n[r]]=t}function s(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function a(e){return function(t){return"input"===t.nodeName.toLowerCase()&&t.type===e}}function u(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function c(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&Ee(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function l(e){return r(function(t){return t=+t,r(function(n,r){for(var i,o=e([],n.length,t),s=o.length;s--;)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}function f(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function d(){}function p(e){for(var t=0,n=e.length,r="";t1?function(t,n,r){for(var i=e.length;i--;)if(!e[i](t,n,r))return!1;return!0}:e[0]}function m(e,n,r){for(var i=0,o=n.length;i-1&&(r[c]=!(s[c]=f))}}else x=v(x===s?x.splice(h,x.length):x),o?o(null,s,x,u):K.apply(s,x)})}function x(e){for(var t,n,r,i=e.length,o=S.relative[e[0].type],s=o||S.relative[" "],a=o?1:0,u=h(function(e){return e===t},s,!0),c=h(function(e){return ee(t,e)>-1},s,!0),l=[function(e,n,r){var i=!o&&(r||n!==A)||((t=n).nodeType?u(e,n,r):c(e,n,r));return t=null,i}];a1&&g(l),a>1&&p(e.slice(0,a-1).concat({value:" "===e[a-2].type?"*":""})).replace(ae,"$1"),n,a0,o=e.length>0,s=function(r,s,a,u,c){var l,f,d,p=0,h="0",g=r&&[],m=[],y=A,x=r||o&&S.find.TAG("*",c),b=W+=null==y?1:Math.random()||.1,w=x.length;for(c&&(A=s===q||s||c);h!==w&&null!=(l=x[h]);h++){if(o&&l){for(f=0,s||l.ownerDocument===q||(O(l),a=!$);d=e[f++];)if(d(l,s||q,a)){u.push(l);break}c&&(W=b)}i&&((l=!d&&l)&&p--,r&&g.push(l))}if(p+=h,i&&h!==p){for(f=0;d=n[f++];)d(g,m,s,a);if(r){if(p>0)for(;h--;)g[h]||m[h]||(m[h]=J.call(u));m=v(m)}K.apply(u,m),c&&!r&&m.length>0&&p+n.length>1&&t.uniqueSort(u)}return c&&(W=b,A=y),g};return i?r(s):s}var w,T,S,E,C,k,N,j,A,L,D,O,q,F,$,P,H,I,R,_="sizzle"+1*new Date,M=e.document,W=0,B=0,z=n(),V=n(),X=n(),U=function(e,t){return e===t&&(D=!0),0},Q={}.hasOwnProperty,Y=[],J=Y.pop,G=Y.push,K=Y.push,Z=Y.slice,ee=function(e,t){for(var n=0,r=e.length;n+~]|"+ne+")"+ne+"*"),le=new RegExp("="+ne+"*([^\\]'\"]*?)"+ne+"*\\]","g"),fe=new RegExp(oe),de=new RegExp("^"+re+"$"),pe={ID:new RegExp("^#("+re+")"),CLASS:new RegExp("^\\.("+re+")"),TAG:new RegExp("^("+re+"|[*])"),ATTR:new RegExp("^"+ie),PSEUDO:new RegExp("^"+oe),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ne+"*(even|odd|(([+-]|)(\\d*)n|)"+ne+"*(?:([+-]|)"+ne+"*(\\d+)|))"+ne+"*\\)|)","i"),bool:new RegExp("^(?:"+te+")$","i"),needsContext:new RegExp("^"+ne+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ne+"*((?:-\\d)?\\d*)"+ne+"*\\)|)(?=[^-]|$)","i")},he=/^(?:input|select|textarea|button)$/i,ge=/^h\d$/i,me=/^[^{]+\{\s*\[native \w/,ve=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ye=/[+~]/,xe=new RegExp("\\\\([\\da-f]{1,6}"+ne+"?|("+ne+")|.)","ig"),be=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:r<0?String.fromCharCode(r+65536):String.fromCharCode(r>>10|55296,1023&r|56320)},we=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,Te=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},Se=function(){O()},Ee=h(function(e){return!0===e.disabled&&("form"in e||"label"in e)},{dir:"parentNode",next:"legend"});try{K.apply(Y=Z.call(M.childNodes),M.childNodes),Y[M.childNodes.length].nodeType}catch(e){K={apply:Y.length?function(e,t){G.apply(e,Z.call(t))}:function(e,t){for(var n=e.length,r=0;e[n++]=t[r++];);e.length=n-1}}}T=t.support={},C=t.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return!!t&&"HTML"!==t.nodeName},O=t.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:M;return r!==q&&9===r.nodeType&&r.documentElement?(q=r,F=q.documentElement,$=!C(q),M!==q&&(n=q.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",Se,!1):n.attachEvent&&n.attachEvent("onunload",Se)),T.attributes=i(function(e){return e.className="i",!e.getAttribute("className")}),T.getElementsByTagName=i(function(e){return e.appendChild(q.createComment("")),!e.getElementsByTagName("*").length}),T.getElementsByClassName=me.test(q.getElementsByClassName),T.getById=i(function(e){return F.appendChild(e).id=_,!q.getElementsByName||!q.getElementsByName(_).length}),T.getById?(S.filter.ID=function(e){var t=e.replace(xe,be);return function(e){return e.getAttribute("id")===t}},S.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&$){var n=t.getElementById(e);return n?[n]:[]}}):(S.filter.ID=function(e){var t=e.replace(xe,be);return function(e){var n="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return n&&n.value===t}},S.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&$){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];for(i=t.getElementsByName(e),r=0;o=i[r++];)if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),S.find.TAG=T.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):T.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){for(;n=o[i++];)1===n.nodeType&&r.push(n);return r}return o},S.find.CLASS=T.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&$)return t.getElementsByClassName(e)},H=[],P=[],(T.qsa=me.test(q.querySelectorAll))&&(i(function(e){F.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&P.push("[*^$]="+ne+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||P.push("\\["+ne+"*(?:value|"+te+")"),e.querySelectorAll("[id~="+_+"-]").length||P.push("~="),e.querySelectorAll(":checked").length||P.push(":checked"),e.querySelectorAll("a#"+_+"+*").length||P.push(".#.+[+~]")}),i(function(e){e.innerHTML="";var t=q.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&P.push("name"+ne+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&P.push(":enabled",":disabled"),F.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&P.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),P.push(",.*:")})),(T.matchesSelector=me.test(I=F.matches||F.webkitMatchesSelector||F.mozMatchesSelector||F.oMatchesSelector||F.msMatchesSelector))&&i(function(e){T.disconnectedMatch=I.call(e,"*"),I.call(e,"[s!='']:x"),H.push("!=",oe)}),P=P.length&&new RegExp(P.join("|")),H=H.length&&new RegExp(H.join("|")),t=me.test(F.compareDocumentPosition),R=t||me.test(F.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)for(;t=t.parentNode;)if(t===e)return!0;return!1},U=t?function(e,t){if(e===t)return D=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(n=(e.ownerDocument||e)===(t.ownerDocument||t)?e.compareDocumentPosition(t):1,1&n||!T.sortDetached&&t.compareDocumentPosition(e)===n?e===q||e.ownerDocument===M&&R(M,e)?-1:t===q||t.ownerDocument===M&&R(M,t)?1:L?ee(L,e)-ee(L,t):0:4&n?-1:1)}:function(e,t){if(e===t)return D=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],u=[t];if(!i||!o)return e===q?-1:t===q?1:i?-1:o?1:L?ee(L,e)-ee(L,t):0;if(i===o)return s(e,t);for(n=e;n=n.parentNode;)a.unshift(n);for(n=t;n=n.parentNode;)u.unshift(n);for(;a[r]===u[r];)r++;return r?s(a[r],u[r]):a[r]===M?-1:u[r]===M?1:0},q):q},t.matches=function(e,n){return t(e,null,null,n)},t.matchesSelector=function(e,n){if((e.ownerDocument||e)!==q&&O(e),n=n.replace(le,"='$1']"),T.matchesSelector&&$&&!X[n+" "]&&(!H||!H.test(n))&&(!P||!P.test(n)))try{var r=I.call(e,n);if(r||T.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(e){}return t(n,q,null,[e]).length>0},t.contains=function(e,t){return(e.ownerDocument||e)!==q&&O(e),R(e,t)},t.attr=function(e,t){(e.ownerDocument||e)!==q&&O(e);var n=S.attrHandle[t.toLowerCase()],r=n&&Q.call(S.attrHandle,t.toLowerCase())?n(e,t,!$):undefined;return r!==undefined?r:T.attributes||!$?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},t.escape=function(e){return(e+"").replace(we,Te)},t.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},t.uniqueSort=function(e){var t,n=[],r=0,i=0;if(D=!T.detectDuplicates,L=!T.sortStable&&e.slice(0),e.sort(U),D){for(;t=e[i++];)t===e[i]&&(r=n.push(i));for(;r--;)e.splice(n[r],1)}return L=null,e},E=t.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=E(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r++];)n+=E(t);return n},S=t.selectors={cacheLength:50,createPseudo:r,match:pe,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(xe,be),e[3]=(e[3]||e[4]||e[5]||"").replace(xe,be),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||t.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&t.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return pe.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&fe.test(n)&&(t=k(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(xe,be).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=z[e+" "];return t||(t=new RegExp("(^|"+ne+")"+e+"("+ne+"|$)"))&&z(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(e,n,r){return function(i){var o=t.attr(i,e);return null==o?"!="===n:!n||(o+="","="===n?o===r:"!="===n?o!==r:"^="===n?r&&0===o.indexOf(r):"*="===n?r&&o.indexOf(r)>-1:"$="===n?r&&o.slice(-r.length)===r:"~="===n?(" "+o.replace(se," ")+" ").indexOf(r)>-1:"|="===n&&(o===r||o.slice(0,r.length+1)===r+"-"))}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var c,l,f,d,p,h,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,v=a&&t.nodeName.toLowerCase(),y=!u&&!a,x=!1;if(m){if(o){for(;g;){for(d=t;d=d[g];)if(a?d.nodeName.toLowerCase()===v:1===d.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[s?m.firstChild:m.lastChild],s&&y){for(d=m,f=d[_]||(d[_]={}),l=f[d.uniqueID]||(f[d.uniqueID]={}),c=l[e]||[],p=c[0]===W&&c[1],x=p&&c[2],d=p&&m.childNodes[p];d=++p&&d&&d[g]||(x=p=0)||h.pop();)if(1===d.nodeType&&++x&&d===t){l[e]=[W,p,x];break}}else if(y&&(d=t,f=d[_]||(d[_]={}),l=f[d.uniqueID]||(f[d.uniqueID]={}),c=l[e]||[],p=c[0]===W&&c[1],x=p),!1===x)for(;(d=++p&&d&&d[g]||(x=p=0)||h.pop())&&((a?d.nodeName.toLowerCase()!==v:1!==d.nodeType)||!++x||(y&&(f=d[_]||(d[_]={}),l=f[d.uniqueID]||(f[d.uniqueID]={}),l[e]=[W,x]),d!==t)););return(x-=i)===r||x%r==0&&x/r>=0}}},PSEUDO:function(e,n){var i,o=S.pseudos[e]||S.setFilters[e.toLowerCase()]||t.error("unsupported pseudo: "+e);return o[_]?o(n):o.length>1?(i=[e,e,"",n],S.setFilters.hasOwnProperty(e.toLowerCase())?r(function(e,t){for(var r,i=o(e,n),s=i.length;s--;)r=ee(e,i[s]),e[r]=!(t[r]=i[s])}):function(e){return o(e,0,i)}):o}},pseudos:{not:r(function(e){var t=[],n=[],i=N(e.replace(ae,"$1"));return i[_]?r(function(e,t,n,r){for(var o,s=i(e,null,r,[]),a=e.length;a--;)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,r,o){return t[0]=e,i(t,null,o,n),t[0]=null,!n.pop()}}),has:r(function(e){return function(n){return t(e,n).length>0}}),contains:r(function(e){return e=e.replace(xe,be),function(t){return(t.textContent||t.innerText||E(t)).indexOf(e)>-1}}),lang:r(function(e){return de.test(e||"")||t.error("unsupported lang: "+e),e=e.replace(xe,be).toLowerCase(),function(t){var n;do{if(n=$?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return(n=n.toLowerCase())===e||0===n.indexOf(e+"-")}while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===F},focus:function(e){return e===q.activeElement&&(!q.hasFocus||q.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:c(!1),disabled:c(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!S.pseudos.empty(e)},header:function(e){return ge.test(e.nodeName)},input:function(e){return he.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:l(function(){return[0]}),last:l(function(e,t){return[t-1]}),eq:l(function(e,t,n){return[n<0?n+t:n]}),even:l(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:l(function(e,t,n){for(var r=n<0?n+t:n;++r2&&"ID"===(s=o[0]).type&&9===t.nodeType&&$&&S.relative[o[1].type]){if(!(t=(S.find.ID(s.matches[0].replace(xe,be),t)||[])[0]))return n;c&&(t=t.parentNode),e=e.slice(o.shift().value.length)}for(i=pe.needsContext.test(e)?0:o.length;i--&&(s=o[i],!S.relative[a=s.type]);)if((u=S.find[a])&&(r=u(s.matches[0].replace(xe,be),ye.test(o[0].type)&&f(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&p(o)))return K.apply(n,r),n;break}}return(c||N(e,l))(r,t,!$,n,!t||ye.test(e)&&f(t.parentNode)||t),n},T.sortStable=_.split("").sort(U).join("")===_,T.detectDuplicates=!!D,O(),T.sortDetached=i(function(e){return 1&e.compareDocumentPosition(q.createElement("fieldset"))}),i(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||o("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),T.attributes&&i(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||o("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),i(function(e){return null==e.getAttribute("disabled")})||o(te,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),t}(e);ge.find=be,ge.expr=be.selectors,ge.expr[":"]=ge.expr.pseudos,ge.uniqueSort=ge.unique=be.uniqueSort,ge.text=be.getText,ge.isXMLDoc=be.isXML,ge.contains=be.contains,ge.escapeSelector=be.escape;var we=function(e,t,n){for(var r=[],i=n!==undefined;(e=e[t])&&9!==e.nodeType;)if(1===e.nodeType){if(i&&ge(e).is(n))break;r.push(e)}return r},Te=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},Se=ge.expr.match.needsContext,Ee=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i,Ce=/^.[^:#\[\.,]*$/;ge.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?ge.find.matchesSelector(r,e)?[r]:[]:ge.find.matches(e,ge.grep(t,function(e){return 1===e.nodeType}))},ge.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(ge(e).filter(function(){for(t=0;t1?ge.uniqueSort(n):n},filter:function(e){return this.pushStack(o(this,e||[],!1))},not:function(e){return this.pushStack(o(this,e||[],!0))},is:function(e){return!!o(this,"string"==typeof e&&Se.test(e)?ge(e):e||[],!1).length}});var ke,Ne=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(ge.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||ke,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&e.length>=3?[null,e,null]:Ne.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ge?t[0]:t,ge.merge(this,ge.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:ne,!0)),Ee.test(r[1])&&ge.isPlainObject(t))for(r in t)ge.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=ne.getElementById(r[2]),i&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):ge.isFunction(e)?n.ready!==undefined?n.ready(e):e(ge):ge.makeArray(e,this)}).prototype=ge.fn,ke=ge(ne);var je=/^(?:parents|prev(?:Until|All))/,Ae={children:!0,contents:!0,next:!0,prev:!0};ge.fn.extend({has:function(e){var t=ge(e,this),n=t.length;return this.filter(function(){for(var e=0;e-1:1===n.nodeType&&ge.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(o.length>1?ge.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?ae.call(ge(e),this[0]):ae.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(ge.uniqueSort(ge.merge(this.get(),ge(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),ge.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return we(e,"parentNode")},parentsUntil:function(e,t,n){return we(e,"parentNode",n)},next:function(e){return s(e,"nextSibling")},prev:function(e){return s(e,"previousSibling")},nextAll:function(e){return we(e,"nextSibling")},prevAll:function(e){return we(e,"previousSibling")},nextUntil:function(e,t,n){return we(e,"nextSibling",n)},prevUntil:function(e,t,n){return we(e,"previousSibling",n)},siblings:function(e){return Te((e.parentNode||{}).firstChild,e)},children:function(e){return Te(e.firstChild)},contents:function(e){return i(e,"iframe")?e.contentDocument:(i(e,"template")&&(e=e.content||e),ge.merge([],e.childNodes))}},function(e,t){ge.fn[e]=function(n,r){var i=ge.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=ge.filter(r,i)),this.length>1&&(Ae[e]||ge.uniqueSort(i),je.test(e)&&i.reverse()),this.pushStack(i)}});var Le=/[^\x20\t\r\n\f]+/g;ge.Callbacks=function(e){e="string"==typeof e?a(e):ge.extend({},e);var t,n,r,i,o=[],s=[],u=-1,c=function(){for(i=i||e.once,r=t=!0;s.length;u=-1)for(n=s.shift();++u-1;)o.splice(n,1),n<=u&&u--}),this},has:function(e){return e?ge.inArray(e,o)>-1:o.length>0},empty:function(){return o&&(o=[]),this},disable:function(){return i=s=[],o=n="",this},disabled:function(){return!o},lock:function(){return i=s=[],n||t||(o=n=""),this},locked:function(){return!!i},fireWith:function(e,n){return i||(n=n||[],n=[e,n.slice?n.slice():n],s.push(n),t||c()),this},fire:function(){return l.fireWith(this,arguments),this},fired:function(){return!!r}};return l},ge.extend({Deferred:function(t){var n=[["notify","progress",ge.Callbacks("memory"),ge.Callbacks("memory"),2],["resolve","done",ge.Callbacks("once memory"),ge.Callbacks("once memory"),0,"resolved"],["reject","fail",ge.Callbacks("once memory"),ge.Callbacks("once memory"),1,"rejected"]],r="pending",i={state:function(){return r},always:function(){return o.done(arguments).fail(arguments),this},"catch":function(e){return i.then(null,e)},pipe:function(){var e=arguments;return ge.Deferred(function(t){ge.each(n,function(n,r){var i=ge.isFunction(e[r[4]])&&e[r[4]];o[r[1]](function(){var e=i&&i.apply(this,arguments);e&&ge.isFunction(e.promise)?e.promise().progress(t.notify).done(t.resolve).fail(t.reject):t[r[0]+"With"](this,i?[e]:arguments)})}),e=null}).promise()},then:function(t,r,i){function o(t,n,r,i){return function(){var a=this,l=arguments,f=function(){var e,f;if(!(t=s&&(r!==c&&(a=undefined,l=[e]),n.rejectWith(a,l))}};t?d():(ge.Deferred.getStackHook&&(d.stackTrace=ge.Deferred.getStackHook()),e.setTimeout(d))}}var s=0;return ge.Deferred(function(e){n[0][3].add(o(0,e,ge.isFunction(i)?i:u,e.notifyWith)),n[1][3].add(o(0,e,ge.isFunction(t)?t:u)),n[2][3].add(o(0,e,ge.isFunction(r)?r:c))}).promise()},promise:function(e){return null!=e?ge.extend(e,i):i}},o={};return ge.each(n,function(e,t){var s=t[2],a=t[5];i[t[1]]=s.add,a&&s.add(function(){r=a},n[3-e][2].disable,n[0][2].lock),s.add(t[3].fire),o[t[0]]=function(){return o[t[0]+"With"](this===o?undefined:this,arguments),this},o[t[0]+"With"]=s.fireWith}),i.promise(o),t&&t.call(o,o),o},when:function(e){var t=arguments.length,n=t,r=Array(n),i=ie.call(arguments),o=ge.Deferred(),s=function(e){return function(n){r[e]=this,i[e]=arguments.length>1?ie.call(arguments):n,--t||o.resolveWith(r,i)}};if(t<=1&&(l(e,o.done(s(n)).resolve,o.reject,!t),"pending"===o.state()||ge.isFunction(i[n]&&i[n].then)))return o.then();for(;n--;)l(i[n],s(n),o.reject);return o.promise()}});var De=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;ge.Deferred.exceptionHook=function(t,n){e.console&&e.console.warn&&t&&De.test(t.name)&&e.console.warn("jQuery.Deferred exception: "+t.message,t.stack,n)},ge.readyException=function(t){e.setTimeout(function(){throw t})};var Oe=ge.Deferred();ge.fn.ready=function(e){return Oe.then(e)["catch"](function(e){ge.readyException(e)}),this},ge.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--ge.readyWait:ge.isReady)||(ge.isReady=!0,!0!==e&&--ge.readyWait>0||Oe.resolveWith(ne,[ge]))}}),ge.ready.then=Oe.then,"complete"===ne.readyState||"loading"!==ne.readyState&&!ne.documentElement.doScroll?e.setTimeout(ge.ready):(ne.addEventListener("DOMContentLoaded",f),e.addEventListener("load",f));var qe=function(e,t,n,r,i,o,s){var a=0,u=e.length,c=null==n;if("object"===ge.type(n)){i=!0;for(a in n)qe(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,ge.isFunction(r)||(s=!0),c&&(s?(t.call(e,r),t=null):(c=t,t=function(e,t,n){return c.call(ge(e),n)})),t))for(;a1,null,!0)},removeData:function(e){return this.each(function(){Pe.remove(this,e)})}}),ge.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=$e.get(e,t),n&&(!r||Array.isArray(n)?r=$e.access(e,t,ge.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=ge.queue(e,t),r=n.length,i=n.shift(),o=ge._queueHooks(e,t),s=function(){ge.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return $e.get(e,n)||$e.access(e,n,{empty:ge.Callbacks("once memory").add(function(){$e.remove(e,[t+"queue",n])})})}}),ge.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),arguments.length\x20\t\r\n\f]+)/i,Ue=/^$|\/(?:java|ecma)script/i,Qe={option:[1,""],thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};Qe.optgroup=Qe.option,Qe.tbody=Qe.tfoot=Qe.colgroup=Qe.caption=Qe.thead,Qe.th=Qe.td;var Ye=/<|&#?\w+;/;!function(){var e=ne.createDocumentFragment(),t=e.appendChild(ne.createElement("div")),n=ne.createElement("input");n.setAttribute("type","radio"),n.setAttribute("checked","checked"),n.setAttribute("name","t"),t.appendChild(n),pe.checkClone=t.cloneNode(!0).cloneNode(!0).lastChild.checked,t.innerHTML="",pe.noCloneChecked=!!t.cloneNode(!0).lastChild.defaultValue}();var Je=ne.documentElement,Ge=/^key/,Ke=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Ze=/^([^.]*)(?:\.(.+)|)/;ge.event={global:{},add:function(e,t,n,r,i){var o,s,a,u,c,l,f,d,p,h,g,m=$e.get(e);if(m)for(n.handler&&(o=n,n=o.handler,i=o.selector),i&&ge.find.matchesSelector(Je,i), +n.guid||(n.guid=ge.guid++),(u=m.events)||(u=m.events={}),(s=m.handle)||(s=m.handle=function(t){return void 0!==ge&&ge.event.triggered!==t.type?ge.event.dispatch.apply(e,arguments):undefined}),t=(t||"").match(Le)||[""],c=t.length;c--;)a=Ze.exec(t[c])||[],p=g=a[1],h=(a[2]||"").split(".").sort(),p&&(f=ge.event.special[p]||{},p=(i?f.delegateType:f.bindType)||p,f=ge.event.special[p]||{},l=ge.extend({type:p,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&ge.expr.match.needsContext.test(i),namespace:h.join(".")},o),(d=u[p])||(d=u[p]=[],d.delegateCount=0,f.setup&&!1!==f.setup.call(e,r,h,s)||e.addEventListener&&e.addEventListener(p,s)),f.add&&(f.add.call(e,l),l.handler.guid||(l.handler.guid=n.guid)),i?d.splice(d.delegateCount++,0,l):d.push(l),ge.event.global[p]=!0)},remove:function(e,t,n,r,i){var o,s,a,u,c,l,f,d,p,h,g,m=$e.hasData(e)&&$e.get(e);if(m&&(u=m.events)){for(t=(t||"").match(Le)||[""],c=t.length;c--;)if(a=Ze.exec(t[c])||[],p=g=a[1],h=(a[2]||"").split(".").sort(),p){for(f=ge.event.special[p]||{},p=(r?f.delegateType:f.bindType)||p,d=u[p]||[],a=a[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=d.length;o--;)l=d[o],!i&&g!==l.origType||n&&n.guid!==l.guid||a&&!a.test(l.namespace)||r&&r!==l.selector&&("**"!==r||!l.selector)||(d.splice(o,1),l.selector&&d.delegateCount--,f.remove&&f.remove.call(e,l));s&&!d.length&&(f.teardown&&!1!==f.teardown.call(e,h,m.handle)||ge.removeEvent(e,p,m.handle),delete u[p])}else for(p in u)ge.event.remove(e,p+t[c],n,r,!0);ge.isEmptyObject(u)&&$e.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,s,a=ge.event.fix(e),u=new Array(arguments.length),c=($e.get(this,"events")||{})[a.type]||[],l=ge.event.special[a.type]||{};for(u[0]=a,t=1;t=1))for(;c!==this;c=c.parentNode||this)if(1===c.nodeType&&("click"!==e.type||!0!==c.disabled)){for(o=[],s={},n=0;n-1:ge.find(i,this,null,[c]).length),s[i]&&o.push(r);o.length&&a.push({elem:c,handlers:o})}return c=this,u\x20\t\r\n\f]*)[^>]*)\/>/gi,tt=/\s*$/g;ge.extend({htmlPrefilter:function(e){return e.replace(et,"<$1>")},clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=ge.contains(e.ownerDocument,e);if(!(pe.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||ge.isXMLDoc(e)))for(s=y(a),o=y(e),r=0,i=o.length;r0&&x(s,!u&&y(e,"script")),a},cleanData:function(e){for(var t,n,r,i=ge.event.special,o=0;(n=e[o])!==undefined;o++)if(Fe(n)){if(t=n[$e.expando]){if(t.events)for(r in t.events)i[r]?ge.event.remove(n,r):ge.removeEvent(n,r,t.handle);n[$e.expando]=undefined}n[Pe.expando]&&(n[Pe.expando]=undefined)}}}),ge.fn.extend({detach:function(e){return D(this,e,!0)},remove:function(e){return D(this,e)},text:function(e){return qe(this,function(e){return e===undefined?ge.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return L(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){C(this,e).appendChild(e)}})},prepend:function(){return L(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=C(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return L(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return L(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(ge.cleanData(y(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return ge.clone(this,e,t)})},html:function(e){return qe(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!tt.test(e)&&!Qe[(Xe.exec(e)||["",""])[1].toLowerCase()]){e=ge.htmlPrefilter(e);try{for(;n1)}}),ge.Tween=R,R.prototype={constructor:R,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||ge.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(ge.cssNumber[n]?"":"px")},cur:function(){var e=R.propHooks[this.prop];return e&&e.get?e.get(this):R.propHooks._default.get(this)},run:function(e){var t,n=R.propHooks[this.prop];return this.options.duration?this.pos=t=ge.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):R.propHooks._default.set(this),this}},R.prototype.init.prototype=R.prototype,R.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=ge.css(e.elem,e.prop,""),t&&"auto"!==t?t:0)},set:function(e){ge.fx.step[e.prop]?ge.fx.step[e.prop](e):1!==e.elem.nodeType||null==e.elem.style[ge.cssProps[e.prop]]&&!ge.cssHooks[e.prop]?e.elem[e.prop]=e.now:ge.style(e.elem,e.prop,e.now+e.unit)}}},R.propHooks.scrollTop=R.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},ge.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},ge.fx=R.prototype.init,ge.fx.step={};var ht,gt,mt=/^(?:toggle|show|hide)$/,vt=/queueHooks$/;ge.Animation=ge.extend(X,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return g(n.elem,e,_e.exec(t),n),n}]},tweener:function(e,t){ge.isFunction(e)?(t=e,e=["*"]):e=e.match(Le);for(var n,r=0,i=e.length;r1)},removeAttr:function(e){return this.each(function(){ge.removeAttr(this,e)})}}),ge.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?ge.prop(e,t,n):(1===o&&ge.isXMLDoc(e)||(i=ge.attrHooks[t.toLowerCase()]||(ge.expr.match.bool.test(t)?yt:undefined)),n!==undefined?null===n?void ge.removeAttr(e,t):i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:(r=ge.find.attr(e,t),null==r?undefined:r))},attrHooks:{type:{set:function(e,t){if(!pe.radioValue&&"radio"===t&&i(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(Le);if(i&&1===e.nodeType)for(;n=i[r++];)e.removeAttribute(n)}}),yt={set:function(e,t,n){return!1===t?ge.removeAttr(e,n):e.setAttribute(n,n),n}},ge.each(ge.expr.match.bool.source.match(/\w+/g),function(e,t){var n=xt[t]||ge.find.attr;xt[t]=function(e,t,r){var i,o,s=t.toLowerCase();return r||(o=xt[s],xt[s]=i,i=null!=n(e,t,r)?s:null,xt[s]=o),i}});var bt=/^(?:input|select|textarea|button)$/i,wt=/^(?:a|area)$/i;ge.fn.extend({prop:function(e,t){return qe(this,ge.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[ge.propFix[e]||e]})}}),ge.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&ge.isXMLDoc(e)||(t=ge.propFix[t]||t,i=ge.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=ge.find.attr(e,"tabindex");return t?parseInt(t,10):bt.test(e.nodeName)||wt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),pe.optSelected||(ge.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),ge.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){ge.propFix[this.toLowerCase()]=this}),ge.fn.extend({addClass:function(e){var t,n,r,i,o,s,a,u=0;if(ge.isFunction(e))return this.each(function(t){ge(this).addClass(e.call(this,t,Q(this)))});if("string"==typeof e&&e)for(t=e.match(Le)||[];n=this[u++];)if(i=Q(n),r=1===n.nodeType&&" "+U(i)+" "){for(s=0;o=t[s++];)r.indexOf(" "+o+" ")<0&&(r+=o+" ");a=U(r),i!==a&&n.setAttribute("class",a)}return this},removeClass:function(e){var t,n,r,i,o,s,a,u=0;if(ge.isFunction(e))return this.each(function(t){ge(this).removeClass(e.call(this,t,Q(this)))});if(!arguments.length)return this.attr("class","");if("string"==typeof e&&e)for(t=e.match(Le)||[];n=this[u++];)if(i=Q(n),r=1===n.nodeType&&" "+U(i)+" "){for(s=0;o=t[s++];)for(;r.indexOf(" "+o+" ")>-1;)r=r.replace(" "+o+" "," ");a=U(r),i!==a&&n.setAttribute("class",a)}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):ge.isFunction(e)?this.each(function(n){ge(this).toggleClass(e.call(this,n,Q(this),t),t)}):this.each(function(){var t,r,i,o;if("string"===n)for(r=0,i=ge(this),o=e.match(Le)||[];t=o[r++];)i.hasClass(t)?i.removeClass(t):i.addClass(t);else e!==undefined&&"boolean"!==n||(t=Q(this),t&&$e.set(this,"__className__",t),this.setAttribute&&this.setAttribute("class",t||!1===e?"":$e.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;for(t=" "+e+" ";n=this[r++];)if(1===n.nodeType&&(" "+U(Q(n))+" ").indexOf(t)>-1)return!0;return!1}});var Tt=/\r/g;ge.fn.extend({val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=ge.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,ge(this).val()):e,null==i?i="":"number"==typeof i?i+="":Array.isArray(i)&&(i=ge.map(i,function(e){return null==e?"":e+""})),(t=ge.valHooks[this.type]||ge.valHooks[this.nodeName.toLowerCase()])&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return(t=ge.valHooks[i.type]||ge.valHooks[i.nodeName.toLowerCase()])&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace(Tt,""):null==n?"":n)}}}),ge.extend({valHooks:{option:{get:function(e){var t=ge.find.attr(e,"value");return null!=t?t:U(ge.text(e))}},select:{get:function(e){var t,n,r,o=e.options,s=e.selectedIndex,a="select-one"===e.type,u=a?null:[],c=a?s+1:o.length;for(r=s<0?c:a?s:0;r-1)&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),ge.each(["radio","checkbox"],function(){ge.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=ge.inArray(ge(e).val(),t)>-1}},pe.checkOn||(ge.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var St=/^(?:focusinfocus|focusoutblur)$/;ge.extend(ge.event,{trigger:function(t,n,r,i){var o,s,a,u,c,l,f,d=[r||ne],p=le.call(t,"type")?t.type:t,h=le.call(t,"namespace")?t.namespace.split("."):[];if(s=a=r=r||ne,3!==r.nodeType&&8!==r.nodeType&&!St.test(p+ge.event.triggered)&&(p.indexOf(".")>-1&&(h=p.split("."),p=h.shift(),h.sort()),c=p.indexOf(":")<0&&"on"+p,t=t[ge.expando]?t:new ge.Event(p,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=h.join("."),t.rnamespace=t.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:ge.makeArray(n,[t]),f=ge.event.special[p]||{},i||!f.trigger||!1!==f.trigger.apply(r,n))){if(!i&&!f.noBubble&&!ge.isWindow(r)){for(u=f.delegateType||p,St.test(u+p)||(s=s.parentNode);s;s=s.parentNode)d.push(s),a=s;a===(r.ownerDocument||ne)&&d.push(a.defaultView||a.parentWindow||e)}for(o=0;(s=d[o++])&&!t.isPropagationStopped();)t.type=o>1?u:f.bindType||p,l=($e.get(s,"events")||{})[t.type]&&$e.get(s,"handle"),l&&l.apply(s,n),(l=c&&s[c])&&l.apply&&Fe(s)&&(t.result=l.apply(s,n),!1===t.result&&t.preventDefault());return t.type=p,i||t.isDefaultPrevented()||f._default&&!1!==f._default.apply(d.pop(),n)||!Fe(r)||c&&ge.isFunction(r[p])&&!ge.isWindow(r)&&(a=r[c],a&&(r[c]=null),ge.event.triggered=p,r[p](),ge.event.triggered=undefined,a&&(r[c]=a)),t.result}},simulate:function(e,t,n){var r=ge.extend(new ge.Event,n,{type:e,isSimulated:!0});ge.event.trigger(r,null,t)}}),ge.fn.extend({trigger:function(e,t){return this.each(function(){ge.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return ge.event.trigger(e,t,n,!0)}}),ge.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,t){ge.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),ge.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),pe.focusin="onfocusin"in e,pe.focusin||ge.each({focus:"focusin",blur:"focusout"},function(e,t){var n=function(e){ge.event.simulate(t,e.target,ge.event.fix(e))};ge.event.special[t]={setup:function(){var r=this.ownerDocument||this,i=$e.access(r,t);i||r.addEventListener(e,n,!0),$e.access(r,t,(i||0)+1)},teardown:function(){var r=this.ownerDocument||this,i=$e.access(r,t)-1;i?$e.access(r,t,i):(r.removeEventListener(e,n,!0),$e.remove(r,t))}}});var Et=e.location,Ct=ge.now(),kt=/\?/;ge.parseXML=function(t){var n;if(!t||"string"!=typeof t)return null;try{n=(new e.DOMParser).parseFromString(t,"text/xml")}catch(e){n=undefined}return n&&!n.getElementsByTagName("parsererror").length||ge.error("Invalid XML: "+t),n};var Nt=/\[\]$/,jt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Lt=/^(?:input|select|textarea|keygen)/i;ge.param=function(e,t){var n,r=[],i=function(e,t){var n=ge.isFunction(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(Array.isArray(e)||e.jquery&&!ge.isPlainObject(e))ge.each(e,function(){i(this.name,this.value)});else for(n in e)Y(n,e[n],t,i);return r.join("&")},ge.fn.extend({serialize:function(){return ge.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=ge.prop(this,"elements");return e?ge.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!ge(this).is(":disabled")&&Lt.test(this.nodeName)&&!At.test(e)&&(this.checked||!Ve.test(e))}).map(function(e,t){var n=ge(this).val();return null==n?null:Array.isArray(n)?ge.map(n,function(e){return{name:t.name,value:e.replace(jt,"\r\n")}}):{name:t.name,value:n.replace(jt,"\r\n")}}).get()}});var Dt=/%20/g,Ot=/#.*$/,qt=/([?&])_=[^&]*/,Ft=/^(.*?):[ \t]*([^\r\n]*)$/gm,$t=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Pt=/^(?:GET|HEAD)$/,Ht=/^\/\//,It={},Rt={},_t="*/".concat("*"),Mt=ne.createElement("a");Mt.href=Et.href,ge.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:$t.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":_t,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":ge.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?K(K(e,ge.ajaxSettings),t):K(ge.ajaxSettings,e)},ajaxPrefilter:J(It),ajaxTransport:J(Rt),ajax:function(t,n){function r(t,n,r,a){var c,d,p,b,w,T=n;l||(l=!0,u&&e.clearTimeout(u),i=undefined,s=a||"",S.readyState=t>0?4:0,c=t>=200&&t<300||304===t,r&&(b=Z(h,S,r)),b=ee(h,b,S,c),c?(h.ifModified&&(w=S.getResponseHeader("Last-Modified"),w&&(ge.lastModified[o]=w),(w=S.getResponseHeader("etag"))&&(ge.etag[o]=w)),204===t||"HEAD"===h.type?T="nocontent":304===t?T="notmodified":(T=b.state,d=b.data,p=b.error,c=!p)):(p=T,!t&&T||(T="error",t<0&&(t=0))),S.status=t,S.statusText=(n||T)+"",c?v.resolveWith(g,[d,T,S]):v.rejectWith(g,[S,T,p]),S.statusCode(x),x=undefined,f&&m.trigger(c?"ajaxSuccess":"ajaxError",[S,h,c?d:p]),y.fireWith(g,[S,T]),f&&(m.trigger("ajaxComplete",[S,h]),--ge.active||ge.event.trigger("ajaxStop")))}"object"==typeof t&&(n=t,t=undefined),n=n||{};var i,o,s,a,u,c,l,f,d,p,h=ge.ajaxSetup({},n),g=h.context||h,m=h.context&&(g.nodeType||g.jquery)?ge(g):ge.event,v=ge.Deferred(),y=ge.Callbacks("once memory"),x=h.statusCode||{},b={},w={},T="canceled",S={readyState:0,getResponseHeader:function(e){var t;if(l){if(!a)for(a={};t=Ft.exec(s);)a[t[1].toLowerCase()]=t[2];t=a[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return l?s:null},setRequestHeader:function(e,t){return null==l&&(e=w[e.toLowerCase()]=w[e.toLowerCase()]||e,b[e]=t),this},overrideMimeType:function(e){return null==l&&(h.mimeType=e),this},statusCode:function(e){var t;if(e)if(l)S.always(e[S.status]);else for(t in e)x[t]=[x[t],e[t]];return this},abort:function(e){var t=e||T;return i&&i.abort(t),r(0,t),this}};if(v.promise(S),h.url=((t||h.url||Et.href)+"").replace(Ht,Et.protocol+"//"),h.type=n.method||n.type||h.method||h.type,h.dataTypes=(h.dataType||"*").toLowerCase().match(Le)||[""],null==h.crossDomain){c=ne.createElement("a");try{c.href=h.url,c.href=c.href,h.crossDomain=Mt.protocol+"//"+Mt.host!=c.protocol+"//"+c.host}catch(e){h.crossDomain=!0}}if(h.data&&h.processData&&"string"!=typeof h.data&&(h.data=ge.param(h.data,h.traditional)),G(It,h,n,S),l)return S;f=ge.event&&h.global,f&&0==ge.active++&&ge.event.trigger("ajaxStart"),h.type=h.type.toUpperCase(),h.hasContent=!Pt.test(h.type),o=h.url.replace(Ot,""),h.hasContent?h.data&&h.processData&&0===(h.contentType||"").indexOf("application/x-www-form-urlencoded")&&(h.data=h.data.replace(Dt,"+")):(p=h.url.slice(o.length),h.data&&(o+=(kt.test(o)?"&":"?")+h.data,delete h.data),!1===h.cache&&(o=o.replace(qt,"$1"),p=(kt.test(o)?"&":"?")+"_="+Ct+++p),h.url=o+p),h.ifModified&&(ge.lastModified[o]&&S.setRequestHeader("If-Modified-Since",ge.lastModified[o]),ge.etag[o]&&S.setRequestHeader("If-None-Match",ge.etag[o])),(h.data&&h.hasContent&&!1!==h.contentType||n.contentType)&&S.setRequestHeader("Content-Type",h.contentType),S.setRequestHeader("Accept",h.dataTypes[0]&&h.accepts[h.dataTypes[0]]?h.accepts[h.dataTypes[0]]+("*"!==h.dataTypes[0]?", "+_t+"; q=0.01":""):h.accepts["*"]);for(d in h.headers)S.setRequestHeader(d,h.headers[d]);if(h.beforeSend&&(!1===h.beforeSend.call(g,S,h)||l))return S.abort();if(T="abort",y.add(h.complete),S.done(h.success),S.fail(h.error),i=G(Rt,h,n,S)){if(S.readyState=1,f&&m.trigger("ajaxSend",[S,h]),l)return S;h.async&&h.timeout>0&&(u=e.setTimeout(function(){S.abort("timeout")},h.timeout));try{l=!1,i.send(b,r)}catch(e){if(l)throw e;r(-1,e)}}else r(-1,"No Transport");return S},getJSON:function(e,t,n){return ge.get(e,t,n,"json")},getScript:function(e,t){return ge.get(e,undefined,t,"script")}}),ge.each(["get","post"],function(e,t){ge[t]=function(e,n,r,i){return ge.isFunction(n)&&(i=i||r,r=n,n=undefined),ge.ajax(ge.extend({url:e,type:t,dataType:i,data:n,success:r},ge.isPlainObject(e)&&e))}}),ge._evalUrl=function(e){return ge.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,"throws":!0})},ge.fn.extend({wrapAll:function(e){var t;return this[0]&&(ge.isFunction(e)&&(e=e.call(this[0])),t=ge(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){for(var e=this;e.firstElementChild;)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(e){return ge.isFunction(e)?this.each(function(t){ge(this).wrapInner(e.call(this,t))}):this.each(function(){var t=ge(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=ge.isFunction(e);return this.each(function(n){ge(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(e){return this.parent(e).not("body").each(function(){ge(this).replaceWith(this.childNodes)}),this}}),ge.expr.pseudos.hidden=function(e){return!ge.expr.pseudos.visible(e)},ge.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},ge.ajaxSettings.xhr=function(){try{return new e.XMLHttpRequest}catch(e){}};var Wt={0:200,1223:204},Bt=ge.ajaxSettings.xhr();pe.cors=!!Bt&&"withCredentials"in Bt,pe.ajax=Bt=!!Bt,ge.ajaxTransport(function(t){var n,r;if(pe.cors||Bt&&!t.crossDomain)return{send:function(i,o){var s,a=t.xhr();if(a.open(t.type,t.url,t.async,t.username,t.password),t.xhrFields)for(s in t.xhrFields)a[s]=t.xhrFields[s];t.mimeType&&a.overrideMimeType&&a.overrideMimeType(t.mimeType),t.crossDomain||i["X-Requested-With"]||(i["X-Requested-With"]="XMLHttpRequest");for(s in i)a.setRequestHeader(s,i[s]);n=function(e){return function(){n&&(n=r=a.onload=a.onerror=a.onabort=a.onreadystatechange=null,"abort"===e?a.abort():"error"===e?"number"!=typeof a.status?o(0,"error"):o(a.status,a.statusText):o(Wt[a.status]||a.status,a.statusText,"text"!==(a.responseType||"text")||"string"!=typeof a.responseText?{binary:a.response}:{text:a.responseText},a.getAllResponseHeaders()))}},a.onload=n(),r=a.onerror=n("error"),a.onabort!==undefined?a.onabort=r:a.onreadystatechange=function(){4===a.readyState&&e.setTimeout(function(){n&&r()})},n=n("abort");try{a.send(t.hasContent&&t.data||null)}catch(e){if(n)throw e}},abort:function(){n&&n()}}}),ge.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),ge.ajaxSetup({accepts:{ +script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return ge.globalEval(e),e}}}),ge.ajaxPrefilter("script",function(e){e.cache===undefined&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),ge.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,i){t=ge("