diff --git a/composer.json b/composer.json index 64f7d89..3bc1bc9 100644 --- a/composer.json +++ b/composer.json @@ -14,12 +14,21 @@ "illuminate/support": "4.1.*@dev" }, "require-dev": { - "orchestra/testbench": "2.1.*@dev" + "orchestra/testbench": "2.1.*@dev", + "phpdocumentor/phpdocumentor": "2.*" }, "autoload": { "psr-0": { "Morphatic\\Qualtrics\\": "src/" } }, + "extra": { + "versions": { + "1": "1.0/master" + }, + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "minimum-stability": "dev" } diff --git a/docs/api/classes/Morphatic.Qualtrics.Exceptions.CurlException.html b/docs/api/classes/Morphatic.Qualtrics.Exceptions.CurlException.html new file mode 100644 index 0000000..6ad25d6 --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Exceptions.CurlException.html @@ -0,0 +1,390 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\ExceptionsCurlException

+

CurlException class

+

This exception is thrown when a curl object encounters +an error while being executed, e.g. request timeout.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Exceptions.CurlNotInstalledException.html b/docs/api/classes/Morphatic.Qualtrics.Exceptions.CurlNotInstalledException.html new file mode 100644 index 0000000..d0e9954 --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Exceptions.CurlNotInstalledException.html @@ -0,0 +1,390 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\ExceptionsCurlNotInstalledException

+

CurlNotInstalledException class

+

This exception is thrown when the curl module has not been +installed and/or enabled within php.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Exceptions.MissingParameterException.html b/docs/api/classes/Morphatic.Qualtrics.Exceptions.MissingParameterException.html new file mode 100644 index 0000000..b998d18 --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Exceptions.MissingParameterException.html @@ -0,0 +1,391 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\ExceptionsMissingParameterException

+

MissingParameterException class

+

This exception is thrown when the user has not submitted +all of the necessary parameters for a successful call to +a particular Qualtrics function.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Exceptions.QualtricsException.html b/docs/api/classes/Morphatic.Qualtrics.Exceptions.QualtricsException.html new file mode 100644 index 0000000..46a0ccd --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Exceptions.QualtricsException.html @@ -0,0 +1,391 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\ExceptionsQualtricsException

+

QualtricsException class

+

This exception is thrown when the Qualtrics API returns +an error, e.g. when a username/token combination lacks +permission to call a particular function.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Exceptions.QualtricsXMLException.html b/docs/api/classes/Morphatic.Qualtrics.Exceptions.QualtricsXMLException.html new file mode 100644 index 0000000..d4823b7 --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Exceptions.QualtricsXMLException.html @@ -0,0 +1,390 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\ExceptionsQualtricsXMLException

+

QualtricsXMLException class

+

This exception is thrown when the XML returned by Qualtrics +cannot be parsed correctly.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Exceptions.UnknownFormatException.html b/docs/api/classes/Morphatic.Qualtrics.Exceptions.UnknownFormatException.html new file mode 100644 index 0000000..def59da --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Exceptions.UnknownFormatException.html @@ -0,0 +1,390 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\ExceptionsUnknownFormatException

+

UnknownFormatException class

+

This exception is thrown when Qualtrics returns a response that +is not among the known types listed by the content-type header.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Facades.Qualtrics.html b/docs/api/classes/Morphatic.Qualtrics.Facades.Qualtrics.html new file mode 100644 index 0000000..04a903a --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Facades.Qualtrics.html @@ -0,0 +1,430 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\Qualtrics\FacadesQualtrics

+

Qualtrics Facade class

+

This class implements a facade that makes it easier to +call Qualtrics API functions from within Laravel 4.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ No public methods found +
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ getFacadeAccessor()
+
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + + +
+

Methods

+ +
+ +
+
+ +
+

getFacadeAccessor()

+ +
getFacadeAccessor() : string
+

Returns the registered name of the package.

+ + + + +

Returns

+ string +
+
+ +
+ +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.Qualtrics.html b/docs/api/classes/Morphatic.Qualtrics.Qualtrics.html new file mode 100644 index 0000000..7d60335 --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.Qualtrics.html @@ -0,0 +1,1688 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\QualtricsQualtrics

+

Qualtrics class

+

This class implements wrapper functions for all of the API +methods available in the Qualtrics 2.2 API. It is meant to +be used from within Laravel 4.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ __construct()
+ getResponseCountsBySurvey()
+ getUserInfo()
+ addRecipient()
+ createDistribution()
+ createPanel()
+ getPanel()
+ deletePanel()
+ getPanelMemberCount()
+ getPanels()
+ getRecipient()
+ importPanel()
+ removeRecipient()
+ sendReminder()
+ sendSurveyToIndividual()
+ sendSurveyToPanel()
+ updateRecipient()
+ getLegacyResponseData()
+ getSurvey()
+ getSurveys()
+
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ No protected properties found +
+
+ N/A +
+
+
+
+ xmlToArray()
+ parse_csv()
+ parseResponse()
+ request()
+
+
+ $username
+ $token
+ $library
+
+
+ N/A +
+
+
+
+ +
+ + + +
+
+

Properties

+
+ +
+ +
+
+ +
+

$username

+
$username : string
+

Qualtrics username

+

This is the email address that serves as the Qualtrics +username that has access to the api

+ +

Type

+ string +
+
+ +
+ +
+
+ +
+

$token

+
$token : string
+

Qualtrics token

+

This is the Qualtrics-generated that gives a user +access to the api

+ +

Type

+ string +
+
+ +
+ +
+
+ +
+

$library

+
$library : string
+

Qualtrics library

+

This is a library ID associated with the +username that has access to the api

+ +

Type

+ string +
+
+ +
+ + + +
+

Methods

+ +
+ +
+
+ +
+

__construct()

+ +
__construct()
+

Creates a new object of type Qualtrics, setting appropriate authentication parameters

+ + + + +
+
+ +
+ +
+
+ +
+

getResponseCountsBySurvey()

+ +
getResponseCountsBySurvey(string[] $params) : object
+

Gets the total number of responses for a survey in a given date range

+
$params = array(
+    'Format'    => 'JSON',               // Must be XML or JSON, defaults to JSON
+    'StartDate' => 'YYYY-MM-DD',         // Start date of responses to include
+    'EndDate'   => 'YYYY-MM-DD',         // (optional) defaults to today's date
+    'SurveyID'  => 'SV_9LC2rrUZT8c2EiF', // the Qualtrics ID of the survey in question.
+);
+ +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

Returns a PHP object with the resulting counts of "Auditable", "Generated" and "Deleted" responses

+
+
+ +
+ +
+
+ +
+

getUserInfo()

+ +
getUserInfo(string[] $params) : object
+

Gets information about a user

+
$params = array(
+    'Format' => 'JSON', // Must be XML or JSON, defaults to JSON
+);
+ +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

Information about the user in question

+
+
+ +
+ +
+
+ +
+

addRecipient()

+ +
addRecipient(string[] $params) : object
+

Add a new recipient to a panel

+
$params = array(
+    'Format'          => 'JSON',               // Must be XML or JSON, defaults to JSON
+    'LibraryID'       => 'GR_6G4LaoiroGxHH12', // Start date of responses to include
+    'PanelID'         => 'ML_5yIfnFP0soZK3GJ', // Start date of responses to include
+    'FirstName'       => 'Douglas',            // Recipient's first name
+    'LastName'        => 'Crockford',          // Recipient's last name
+    'Email'           => 'doug@js.org',        // Recipient's email address
+    'ExternalDataRef' => 'crockdx',            // (optional)
+    'Language'        => 'EN',                 // (optional) language, defaults to EN
+    'ED[***]'         => '@dougcrockford',     // (optional) embedded data, e.g. ED[twitterID]
+                                               // multiple values for ED possible
+);
+ +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

Returns true on success

+
+
+ +
+ +
+
+ +
+

createDistribution()

+ +
createDistribution(string[] $params) : object
+

Creates a distribution for survey and a panel. No emails will be sent. Distribution links can be generated later to take the survey.

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

An object containing the DistributionID

+
+
+ +
+ +
+
+ +
+

createPanel()

+ +
createPanel(string[] $params) : object
+

Creates a new Panel in the Qualtrics System and returns the ID of the new panel

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

Returns the ID of the new panel

+
+
+ +
+ +
+
+ +
+

getPanel()

+ +
getPanel(string[] $params) : object
+

Gets all the panel members for the given panel

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The panel members and any requested data

+
+
+ +
+ +
+
+ +
+

deletePanel()

+ +
deletePanel(string[] $params) : object
+

Deletes a panel

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The results of the deletion process

+
+
+ +
+ +
+
+ +
+

getPanelMemberCount()

+ +
getPanelMemberCount(string[] $params) : object
+

Gets the number of panel members

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The number of members of the panel

+
+
+ +
+ +
+
+ +
+

getPanels()

+ +
getPanels(string[] $params) : object
+

Gets all of the panels in a given library

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The panels in the library

+
+
+ +
+ +
+
+ +
+

getRecipient()

+ +
getRecipient(string[] $params) : object
+

Gets a representation of the recipient and their history

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The representation of the recipient

+
+
+ +
+ +
+
+ +
+

importPanel()

+ +
importPanel(string[] $params) : object
+

Imports a csv file as a new panel

+

Imports a csv file as a new panel (optionally it can append to a previously made panel) +into the database and returns the panel id. The csv file can be posted (there is an +approximate 8 megabytes limit) or a url can be given to retrieve the file from a remote server. +The csv file must be comma separated using " for encapsulation.

+ +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

Contains the new PanelID, a count of imported recipients, and a count of ignored recipients

+
+
+ +
+ +
+
+ +
+

removeRecipient()

+ +
removeRecipient(string[] $params) : object
+

Removes a specified panel member from a specified panel

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The representation of the recipient

+
+
+ +
+ +
+
+ +
+

sendReminder()

+ +
sendReminder(string[] $params) : object
+

Sends a reminder through the Qualtrics mailer to the panel or individual as specified by the parent distribution Id

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The email distribution ID and distribution queue id

+
+
+ +
+ +
+
+ +
+

sendSurveyToIndividual()

+ +
sendSurveyToIndividual(string[] $params) : object
+

Sends a survey through the Qualtrics mailer to the individual specified

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The email distribution ID and distribution queue id

+
+
+ +
+ +
+
+ +
+

sendSurveyToPanel()

+ +
sendSurveyToPanel(string[] $params) : object
+

Sends a survey through the Qualtrics mailer to the panel specified

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

The email distribution ID and distribution queue id

+
+
+ +
+ +
+
+ +
+

updateRecipient()

+ +
updateRecipient(string[] $params) : object
+

Updates the recipient’s data—any value not specified will be left alone and not updated

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

Returns true on success or WP_Error on failure

+
+
+ +
+ +
+
+ +
+

getLegacyResponseData()

+ +
getLegacyResponseData(string[] $params) : object
+

Returns all of the response data for a survey in the original (legacy) data format

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

An object representing the responses for the specified panel members

+
+
+ +
+ +
+
+ +
+

getSurvey()

+ +
getSurvey(string[] $params) : object
+

This request returns an xml export of the survey. NOTE: Custom response format!

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

On object representing the survey.

+
+
+ +
+ +
+
+ +
+

getSurveys()

+ +
getSurveys(string[] $params) : object
+

This request returns a list of all the surveys for the user

+ + +

Parameters

+ + + + + + +
string[]$params

An array of named parameters needed to complete the request (see code above)

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\MissingParameterException
+

Thrown when one of the required parameters does not exist in the $params array

+
+ +

Returns

+ object + —

A list of surveys available to the user

+
+
+ +
+ +
+
+ +
+

xmlToArray()

+ +
xmlToArray(\SimpleXMLElement $xml, object[] $out) : array
+

Converts XML to Array that can then be converted to JSON

+ + +

Parameters

+ + + + + + + + + + + +
\SimpleXMLElement$xml

The XML to be converted

object[]$out

An empty array to be populated by the function

+ + +

Returns

+ array + —

The XML converted to an array

+
+
+ +
+ +
+
+ +
+

parse_csv()

+ +
parse_csv(string $csv_string, string $delimiter, boolean $skip_empty_lines, boolean $trim_fields) : array
+

Converts csv into 2-dimensional array

+ + +

Parameters

+ + + + + + + + + + + + + + + + + + + + + +
string$csv_string

The CSV string to be parsed

string$delimiter

The delimiter to be used for parsing, defaults to comma

boolean$skip_empty_lines

Whether or not to skip empty lines, defaults to true

boolean$trim_fields

Whether or not to trim() fields, defaults to true

+ + +

Returns

+ array + —

The two-dimensional array representing the CSV

+
+
+ +
+ +
+
+ +
+

parseResponse()

+ +
parseResponse(resource $ch, string $result) : array
+

Parses the data returned from a Qualtrics request.

+ + +

Parameters

+ + + + + + + + + + + +
resource$ch

The curl handle associated with the request

string$result

The text returned from the request

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\QualtricsXMLException
+

Thrown when an XML response cannot be parsed correctly

+
\Morphatic\Qualtrics\Exceptions\UnknownFormatException
+

Thrown when Qualtrics returns a response with an unrecognized content-type header

+
+ +

Returns

+ array + —

Returns an array with the headers and parsed response text

+
+
+ +
+ +
+
+ +
+

request()

+ +
request(string $request, string[] $params) : object
+

Private function that makes a generic Qualtrics API request.

+

This function takes an API function name and an array of parameters +and makes an attempt to fetch the data using the Qualtrics API.

+ +

Parameters

+ + + + + + + + + + + +
string$request

The name of the API function to be called

string[]$params

An array which contains any necessary parameters for the API call

+ +

Throws

+
+
\Morphatic\Qualtrics\Exceptions\CurlNotInstalledException
+

Thrown when the curl library is not installed on the server

+
\Morphatic\Qualtrics\Exceptions\QualtricsException
+

Thrown when Qualtrics returns an error with the request

+
\Morphatic\Qualtrics\Exceptions\CurlException
+

Thrown when the curl request is unsuccessful, e.g. request timeout

+
+ +

Returns

+ object + —

Returns an object representing the requested data

+
+
+ +
+ +
+
+ + + + +
+ + + diff --git a/docs/api/classes/Morphatic.Qualtrics.QualtricsServiceProvider.html b/docs/api/classes/Morphatic.Qualtrics.QualtricsServiceProvider.html new file mode 100644 index 0000000..19c1874 --- /dev/null +++ b/docs/api/classes/Morphatic.Qualtrics.QualtricsServiceProvider.html @@ -0,0 +1,531 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

\Morphatic\QualtricsQualtricsServiceProvider

+

QualtricsServiceProvider class

+

This class registers the Qualtrics package and all of its +exceptions with the Laravel 4 framework.

+ +
+

Summary

+
+
+ Methods +
+
+ Properties +
+
+ Constants +
+
+
+
+ boot()
+ register()
+ provides()
+
+
+ No public properties found +
+
+ No constants found +
+
+
+
+ No protected methods found +
+
+ $defer
+
+
+ N/A +
+
+
+
+ No private methods found +
+
+ No private properties found +
+
+ N/A +
+
+
+
+ +
+ + + +
+
+

Properties

+
+ +
+ +
+
+ +
+

$defer

+
$defer : bool
+

Indicates if loading of the provider is deferred.

+ + +

Type

+ bool +
+
+ +
+ + + +
+

Methods

+ +
+ +
+
+ +
+

boot()

+ +
boot() : void
+

Bootstrap the application events.

+ + + + +
+
+ +
+ +
+
+ +
+

register()

+ +
register() : void
+

Register the service provider.

+ + + + +
+
+ +
+ +
+
+ +
+

provides()

+ +
provides() : array
+

Get the services provided by the provider.

+ + + + +

Returns

+ array +
+
+ +
+ +
+
+ + + + +
+ + + diff --git a/docs/api/css/jquery.iviewer.css b/docs/api/css/jquery.iviewer.css new file mode 100644 index 0000000..11f5f09 --- /dev/null +++ b/docs/api/css/jquery.iviewer.css @@ -0,0 +1,65 @@ +.viewer { + -ms-touch-action: none; +} + +.iviewer_common { + position:absolute; + bottom:10px; + border: 1px solid #000; + height: 28px; + z-index: 5000; +} + +.iviewer_cursor { + cursor: url(../images/iviewer/hand.cur) 6 8, pointer; +} + +.iviewer_drag_cursor { + cursor: url(../images/iviewer/grab.cur) 6 8, pointer; +} + +.iviewer_button { + width: 28px; + cursor: pointer; + background-position: center center; + background-repeat: no-repeat; +} + +.iviewer_zoom_in { + left: 20px; + background: url(../images/iviewer/iviewer.zoom_in.png); +} + +.iviewer_zoom_out { + left: 55px; + background: url(../images/iviewer/iviewer.zoom_out.png); +} + +.iviewer_zoom_zero { + left: 90px; + background: url(../images/iviewer/iviewer.zoom_zero.png); +} + +.iviewer_zoom_fit { + left: 125px; + background: url(../images/iviewer/iviewer.zoom_fit.png); +} + +.iviewer_zoom_status { + left: 160px; + font: 1em/28px Sans; + color: #000; + background-color: #fff; + text-align: center; + width: 60px; +} + +.iviewer_rotate_left { + left: 227px; + background: #fff url(../images/iviewer/iviewer.rotate_left.png) center center no-repeat; +} + +.iviewer_rotate_right { + left: 262px; + background: #fff url(../images/iviewer/iviewer.rotate_right.png) center center no-repeat; +} diff --git a/docs/api/css/phpdocumentor-clean-icons/Read Me.txt b/docs/api/css/phpdocumentor-clean-icons/Read Me.txt new file mode 100644 index 0000000..9d2b9e5 --- /dev/null +++ b/docs/api/css/phpdocumentor-clean-icons/Read Me.txt @@ -0,0 +1,3 @@ +To modify your generated font, use the *dev.svg* file, located in the *fonts* folder in this package. You can import this dev.svg file to the IcoMoon app. All the tags (class names) and the Unicode points of your glyphs are saved in this file. + +See the documentation for more info on how to use this package: http://icomoon.io/#docs/font-face \ No newline at end of file diff --git a/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.dev.svg b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.dev.svg new file mode 100644 index 0000000..8b543c1 --- /dev/null +++ b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.dev.svg @@ -0,0 +1,17 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.eot b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.eot new file mode 100644 index 0000000..ef43f26 Binary files /dev/null and b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.eot differ diff --git a/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.svg b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.svg new file mode 100644 index 0000000..cf0548b --- /dev/null +++ b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.svg @@ -0,0 +1,17 @@ + + + + +This is a custom SVG font generated by IcoMoon. + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.ttf b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.ttf new file mode 100644 index 0000000..1937c7a Binary files /dev/null and b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.ttf differ diff --git a/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.woff b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.woff new file mode 100644 index 0000000..32fe30d Binary files /dev/null and b/docs/api/css/phpdocumentor-clean-icons/fonts/phpdocumentor-clean-icons.woff differ diff --git a/docs/api/css/phpdocumentor-clean-icons/lte-ie7.js b/docs/api/css/phpdocumentor-clean-icons/lte-ie7.js new file mode 100644 index 0000000..881c16e --- /dev/null +++ b/docs/api/css/phpdocumentor-clean-icons/lte-ie7.js @@ -0,0 +1,30 @@ +/* Load this script using conditional IE comments if you need to support IE 7 and IE 6. */ + +window.onload = function() { + function addIcon(el, entity) { + var html = el.innerHTML; + el.innerHTML = '' + entity + '' + html; + } + var icons = { + 'icon-trait' : '', + 'icon-interface' : '', + 'icon-class' : '' + }, + els = document.getElementsByTagName('*'), + i, attr, html, c, el; + for (i = 0; ; i += 1) { + el = els[i]; + if(!el) { + break; + } + attr = el.getAttribute('data-icon'); + if (attr) { + addIcon(el, attr); + } + c = el.className; + c = c.match(/icon-[^\s'"]+/); + if (c && icons[c[0]]) { + addIcon(el, icons[c[0]]); + } + } +}; \ No newline at end of file diff --git a/docs/api/css/phpdocumentor-clean-icons/style.css b/docs/api/css/phpdocumentor-clean-icons/style.css new file mode 100644 index 0000000..f069ec1 --- /dev/null +++ b/docs/api/css/phpdocumentor-clean-icons/style.css @@ -0,0 +1,48 @@ +@font-face { + font-family: 'phpdocumentor-clean-icons'; + src:url('fonts/phpdocumentor-clean-icons.eot'); + src:url('fonts/phpdocumentor-clean-icons.eot?#iefix') format('embedded-opentype'), + url('fonts/phpdocumentor-clean-icons.woff') format('woff'), + url('fonts/phpdocumentor-clean-icons.ttf') format('truetype'), + url('fonts/phpdocumentor-clean-icons.svg#phpdocumentor-clean-icons') format('svg'); + font-weight: normal; + font-style: normal; +} + +/* Use the following CSS code if you want to use data attributes for inserting your icons */ +[data-icon]:before { + font-family: 'phpdocumentor-clean-icons'; + content: attr(data-icon); + speak: none; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} + +/* Use the following CSS code if you want to have a class per icon */ +/* +Instead of a list of all class selectors, +you can use the generic selector below, but it's slower: +[class*="icon-"] { +*/ +.icon-trait, .icon-interface, .icon-class { + font-family: 'phpdocumentor-clean-icons'; + speak: none; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + -webkit-font-smoothing: antialiased; +} +.icon-trait:before { + content: "\e000"; +} +.icon-interface:before { + content: "\e001"; +} +.icon-class:before { + content: "\e002"; +} diff --git a/docs/api/css/prism.css b/docs/api/css/prism.css new file mode 100644 index 0000000..17876af --- /dev/null +++ b/docs/api/css/prism.css @@ -0,0 +1,204 @@ +/** + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ + +code[class*="language-"], +pre[class*="language-"] { + color: black; + text-shadow: 0 1px white; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} + +::-moz-selection { + text-shadow: none; + background: #b3d4fc; +} + +::selection { + text-shadow: none; + background: #b3d4fc; +} + +@media print { + code[class*="language-"], + pre[class*="language-"] { + text-shadow: none; + } +} + +/* Code blocks */ +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; +} + +:not(pre) > code[class*="language-"], +pre[class*="language-"] { + background: #f5f2f0; +} + +/* Inline code */ +:not(pre) > code[class*="language-"] { + padding: .1em; + border-radius: .3em; +} + +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: slategray; +} + +.token.punctuation { + color: #999; +} + +.namespace { + opacity: .7; +} + +.token.property, +.token.tag, +.token.boolean, +.token.number { + color: #905; +} + +.token.selector, +.token.attr-name, +.token.string { + color: #690; +} + +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #a67f59; + background: hsla(0,0%,100%,.5); +} + +.token.atrule, +.token.attr-value, +.token.keyword { + color: #07a; +} + + +.token.regex, +.token.important { + color: #e90; +} + +.token.important { + font-weight: bold; +} + +.token.entity { + cursor: help; +} +pre[data-line] { + position: relative; + padding: 1em 0 1em 3em; +} + +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; /* Same as .prism’s padding-top */ + + background: hsla(24, 20%, 50%,.08); + background: -moz-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + background: -webkit-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + background: -o-linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + background: linear-gradient(left, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0)); + + pointer-events: none; + + line-height: inherit; + white-space: pre; +} + + .line-highlight:before, + .line-highlight[data-end]:after { + content: attr(data-start); + position: absolute; + top: .4em; + left: .6em; + min-width: 1em; + padding: 0 .5em; + background-color: hsla(24, 20%, 50%,.4); + color: hsl(24, 20%, 95%); + font: bold 65%/1.5 sans-serif; + text-align: center; + vertical-align: .3em; + border-radius: 999px; + text-shadow: none; + box-shadow: 0 1px white; + } + + .line-highlight[data-end]:after { + content: attr(data-end); + top: auto; + bottom: .4em; + } +pre.line-numbers { + position: relative; + padding-left: 3.8em; + counter-reset: linenumber; +} + +pre.line-numbers > code { + position: relative; +} + +.line-numbers .line-numbers-rows { + position: absolute; + pointer-events: none; + top: 0; + font-size: 100%; + left: -3.8em; + width: 3em; /* works for line-numbers below 1000 lines */ + letter-spacing: -1px; + border-right: 1px solid #999; + + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} + + .line-numbers-rows > span { + pointer-events: none; + display: block; + counter-increment: linenumber; + } + + .line-numbers-rows > span:before { + content: counter(linenumber); + color: #999; + display: block; + padding-right: 0.8em; + text-align: right; + } diff --git a/docs/api/css/template.css b/docs/api/css/template.css new file mode 100644 index 0000000..dbfe8f6 --- /dev/null +++ b/docs/api/css/template.css @@ -0,0 +1,418 @@ +@import url(https://fonts.googleapis.com/css?family=Source+Sans+Pro); +@import url('phpdocumentor-clean-icons/style.css'); + +body { + padding-top: 40px; + background-color: #333333; +} + +a { + color: #6495ed; +} +a.anchor { + height: 40px; + margin-top: -40px; + display: block; +} + +h1, h2, h3, h4, h5, h6, .brand { + font-family: 'Source Sans Pro', sans-serif; + font-weight: normal; + letter-spacing: 0.05em; +} + +h2, h3, .detailsbar h1 { + overflow: hidden; + white-space: nowrap; + margin: 30px 0 20px 0; +} + +h2:after, h3:after, .detailsbar h1:after { + content: ''; + display: inline-block; + vertical-align: middle; + width: 100%; + height: 2px; + margin-left: 1em; + background: silver; +} + +h3 { + margin: 10px 0 20px 0; +} + +h4 { + margin: 20px 0 10px 0; + color: gray; + font-size: 18.5px; +} + +h3.public, h3.protected, h3.private { + padding-left: 10px; + text-overflow: ellipsis; +} + +.table tr:first-of-type th, .table tr:first-of-type td { + border-top: none; +} +.detailsbar { + color: #eeeeee; + background-color: #333333; + font-size: 0.9em; + overflow: hidden; + border-left: 2px solid gray; +} + +.detailsbar h1 { + font-size: 1.5em; + margin-bottom: 20px; + margin-top: 0; +} + +.detailsbar h2 { + font-size: 1.2em; + margin: 0; + padding: 0; +} + +.detailsbar h1:after { + background: gray; +} +.detailsbar h2:after, .detailsbar h3:after { + background: transparent; +} + +.detailsbar dt { + font-variant: small-caps; + text-transform: lowercase; + font-size: 1.1em; + letter-spacing: 0.1em; + color: silver; +} + +.hierarchy div:nth-of-type(2) { margin-left: 11px; } +.hierarchy div:nth-of-type(3) { margin-left: 22px; } +.hierarchy div:nth-of-type(4) { margin-left: 33px; } +.hierarchy div:nth-of-type(5) { margin-left: 44px; } +.hierarchy div:nth-of-type(6) { margin-left: 55px; } +.hierarchy div:nth-of-type(7) { margin-left: 66px; } +.hierarchy div:nth-of-type(8) { margin-left: 77px; } +.hierarchy div:nth-of-type(9) { margin-left: 88px; } +.hierarchy div:before { + content: "\f0da"; + font-family: FontAwesome; + margin-right: 5px; +} + +.row-fluid { + background-color: white; + overflow: hidden; +} + +footer.row-fluid, footer.row-fluid * { + background-color: #333333; + color: white; +} + +footer.row-fluid { + border-top: 2px dashed #555; + margin-top: 2px; +} + +.footer-sections .span4 { + border: 2px solid #555; + text-align: center; + border-radius: 10px; + margin-top: 70px; + margin-bottom: 20px; + background: #373737; +} + +.footer-sections .span4 h1 { + background: transparent; + margin-top: -30px; + margin-bottom: 20px; + font-size: 5em; +} + +.footer-sections .span4 h1 * { + background: transparent; +} + +.footer-sections .span4 div { + border-bottom-right-radius: 6px; + border-bottom-left-radius: 6px; + padding: 10px; + min-height: 40px; +} +.footer-sections .span4 div, .footer-sections .span4 div * { + background-color: #555; +} +.footer-sections .span4 ul { + text-align: left; + list-style: none; + margin: 0; + padding: 0; +} + +.content { + background-color: white; + padding-right: 20px; +} + +.content nav { + text-align: center; + border-bottom: 1px solid silver; + margin: 5px 0 20px 0; + padding-bottom: 5px; +} + +.content > h1 { + padding-bottom: 15px; +} + +.content > h1 small { + display: block; + padding-bottom: 8px; + font-size: 0.6em; +} + +.deprecated { + text-decoration: line-through; +} + +.method { + margin-bottom: 20px; +} + +.method .signature .argument { + color: maroon; + font-weight: bold; +} + +.class #summary section.row-fluid { + overflow: hidden +} + +.class #summary .heading { + font-weight: bold; + text-align: center; +} + +.class #summary section .span4 { + padding: 3px; + overflow: hidden; + margin-bottom: -9999px; + padding-bottom: 9999px; + white-space: nowrap; + text-overflow: ellipsis; + border-left: 5px solid transparent; +} + +.class #summary section.public .span4:first-of-type:before, +.class #summary section.public .span6:first-of-type:before, +h3.public:before { + font-family: FontAwesome; + content: "\f046"; + color: green; + display: inline-block; + width: 1.2em; +} + +.class #summary section .span4:first-of-type, +.class #summary section .span6:first-of-type { + padding-left: 21px; +} +.class #summary section .span4:first-of-type:before, +.class #summary section .span6:first-of-type:before { + margin-left: -21px; +} +.class #summary section.protected .span4:first-of-type:before, +.class #summary section.protected .span6:first-of-type:before, +h3.protected:before { + font-family: FontAwesome; + content: "\f132"; + color: orange; + display: inline-block; + width: 1.2em; +} + +.class #summary section.private .span4:first-of-type:before, +.class #summary section.private .span6:first-of-type:before, +h3.private:before { + font-family: FontAwesome; + content: "\f023"; + color: red; + display: inline-block; + width: 1.2em; +} + +.class #summary section em { + font-size: 0.9em; + color: silver; +} +.class #summary .inherited { + color: gray; + font-style: italic; +} + +.accordion-group { + border: none; +} + +.accordion { + margin-bottom: 0; +} + +.accordion a:hover { + text-decoration: none; + background: #333333; + color: #eeeeee; +} + +.accordion-heading .accordion-toggle:before { + content: "\f078"; + font-family: FontAwesome; + margin-right: 5px; +} + +.accordion-heading .accordion-toggle.collapsed:before { + content: "\f054"; +} +.accordion-heading .accordion-toggle { + float: left; + width: 16px; + height: 16px; + padding: 4px 2px 4px 12px; +} +.accordion-heading a { + display: block; + padding: 4px 12px; +} + +.accordion-inner a { + display: block; + padding: 4px 12px; +} + +.accordion-inner > ul a:before { + font-family: 'phpdocumentor-clean-icons'; + content: "\e001"; + margin-right: 5px; +} + +.accordion-inner li.class a:before { + content: "\e002"; +} + +.accordion-inner li.interface a:before { + content: "\e001"; +} + +.accordion-inner li.trait a:before { + content: "\e000"; +} + +.accordion-inner { + padding: 4px 0 4px 12px; +} +.accordion-inner ul { + list-style: none; + padding: 0; + margin: 0; +} + +.row-fluid .span2 { + width: 16.5%; +} + +body .modal { + width: 90%; /* desired relative width */ + left: 5%; /* (100%-width)/2 */ + /* place center */ + margin-left:auto; + margin-right:auto; +} + +@media (min-width: 767px) { + .sidebar { + position: fixed; + top: 40px; + bottom: 0; + background-color: #f3f3f3; + left: 0; + border-right: 1px solid #e9e9e9; + overflow-y: scroll; + overflow-x: hidden; + padding-top: 10px; + } + + .sidebar::-webkit-scrollbar { + width: 10px; + } + + .sidebar::-webkit-scrollbar-thumb { + background: #cccccc; + background-clip: padding-box; + border: 3px solid #f3f3f3; + border-radius: 5px; + } + + .sidebar::-webkit-scrollbar-button { + display: none; + } + + .sidebar::-webkit-scrollbar-track { + background: #f3f3f3; + } +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } +} + +@media (max-width: 767px) { + .class #summary .heading { + display: none; + } + + .detailsbar h1 { + display: none; + } + + body { + background-color: white; + } + + footer.row-fluid, footer.row-fluid * { + background-color: white; + } + + .footer-sections h1 { + color: #ccccd9; + } + + .detailsbar { + background-color: white; + color: #333; + border: none; + } +} + +@media (min-width: 767px) { + .detailsbar { + min-height: 100%; + margin-bottom: -99999px; + padding-bottom: 99999px; + padding-left: 20px; + padding-top: 10px; + } +} + +@media (min-width: 1200px) { + .row-fluid .span2 { + width: 16.5%; + } +} diff --git a/docs/api/files/Morphatic.Qualtrics.Exceptions.CurlException.php.html b/docs/api/files/Morphatic.Qualtrics.Exceptions.CurlException.php.html new file mode 100644 index 0000000..5b6430f --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Exceptions.CurlException.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/ExceptionsCurlException.php

+

CurlException.php

+ + + + +

Classes

+ + + + + +
CurlExceptionCurlException class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Exceptions.CurlNotInstalledException.php.html b/docs/api/files/Morphatic.Qualtrics.Exceptions.CurlNotInstalledException.php.html new file mode 100644 index 0000000..29249af --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Exceptions.CurlNotInstalledException.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/ExceptionsCurlNotInstalledException.php

+

CurlNotInstalledException.php

+ + + + +

Classes

+ + + + + +
CurlNotInstalledExceptionCurlNotInstalledException class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Exceptions.MissingParameterException.php.html b/docs/api/files/Morphatic.Qualtrics.Exceptions.MissingParameterException.php.html new file mode 100644 index 0000000..ae8879b --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Exceptions.MissingParameterException.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/ExceptionsMissingParameterException.php

+

MissingParameterException.php

+ + + + +

Classes

+ + + + + +
MissingParameterExceptionMissingParameterException class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Exceptions.QualtricsException.php.html b/docs/api/files/Morphatic.Qualtrics.Exceptions.QualtricsException.php.html new file mode 100644 index 0000000..c546151 --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Exceptions.QualtricsException.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/ExceptionsQualtricsException.php

+

QualtricsException.php

+ + + + +

Classes

+ + + + + +
QualtricsExceptionQualtricsException class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Exceptions.QualtricsXMLException.php.html b/docs/api/files/Morphatic.Qualtrics.Exceptions.QualtricsXMLException.php.html new file mode 100644 index 0000000..055f8e5 --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Exceptions.QualtricsXMLException.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/ExceptionsQualtricsXMLException.php

+

QualtricsXMLException.php

+ + + + +

Classes

+ + + + + +
QualtricsXMLExceptionQualtricsXMLException class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Exceptions.UnknownFormatException.php.html b/docs/api/files/Morphatic.Qualtrics.Exceptions.UnknownFormatException.php.html new file mode 100644 index 0000000..a415156 --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Exceptions.UnknownFormatException.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/ExceptionsUnknownFormatException.php

+

UnknownFormatException.php

+ + + + +

Classes

+ + + + + +
UnknownFormatExceptionUnknownFormatException class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Facades.Qualtrics.php.html b/docs/api/files/Morphatic.Qualtrics.Facades.Qualtrics.php.html new file mode 100644 index 0000000..016e11e --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Facades.Qualtrics.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/Qualtrics/FacadesQualtrics.php

+

Qualtrics.php

+ + + + +

Classes

+ + + + + +
QualtricsQualtrics Facade class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.Qualtrics.php.html b/docs/api/files/Morphatic.Qualtrics.Qualtrics.php.html new file mode 100644 index 0000000..8830380 --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.Qualtrics.php.html @@ -0,0 +1,334 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/QualtricsQualtrics.php

+

Qualtrics.php

+

This file contains the implementation of the core functionality +of this package.

+ + + +

Classes

+ + + + + +
QualtricsQualtrics class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic.Qualtrics.QualtricsServiceProvider.php.html b/docs/api/files/Morphatic.Qualtrics.QualtricsServiceProvider.php.html new file mode 100644 index 0000000..6ca97a5 --- /dev/null +++ b/docs/api/files/Morphatic.Qualtrics.QualtricsServiceProvider.php.html @@ -0,0 +1,333 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

Morphatic/QualtricsQualtricsServiceProvider.php

+

QualtricsServiceProvider.php

+ + + + +

Classes

+ + + + + +
QualtricsServiceProviderQualtricsServiceProvider class
+
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/Morphatic/Qualtrics/Exceptions/CurlException.php.txt b/docs/api/files/Morphatic/Qualtrics/Exceptions/CurlException.php.txt new file mode 100644 index 0000000..fff5c26 --- /dev/null +++ b/docs/api/files/Morphatic/Qualtrics/Exceptions/CurlException.php.txt @@ -0,0 +1,14 @@ + + */ +class Qualtrics { + + /** + * Qualtrics username + * + * This is the email address that serves as the Qualtrics + * username that has access to the api + * + * @var string $username + */ + private $username; + + /** + * Qualtrics token + * + * This is the Qualtrics-generated that gives a user + * access to the api + * + * @var string $token + */ + private $token; + + /** + * Qualtrics library + * + * This is a library ID associated with the + * username that has access to the api + * + * @var string $library + */ + private $library; + + /** + * Creates a new object of type Qualtrics, setting appropriate authentication parameters + */ + public function __construct() { + // get the necessary credentials from the config files + $this->username = Config::get( 'qualtrics::username' ); + $this->token = Config::get( 'qualtrics::token' ); + $this->library = Config::get( 'qualtrcis::library' ); + } + + /** + * Converts XML to Array that can then be converted to JSON + * + * @param \SimpleXMLElement $xml The XML to be converted + * @param object[] $out An empty array to be populated by the function + * @return array The XML converted to an array + */ + private function xmlToArray( $xml, $out = array() ) { + foreach ( (array) $xml as $index => $node ) + $out[ $index ] = ( is_object( $node ) || is_array( $node ) ) ? $this->xmlToArray( $node ) : $node; + return $out; + } + + /** + * Converts csv into 2-dimensional array + * + * @param string $csv_string The CSV string to be parsed + * @param string $delimiter The delimiter to be used for parsing, defaults to comma + * @param boolean $skip_empty_lines Whether or not to skip empty lines, defaults to true + * @param boolean $trim_fields Whether or not to trim() fields, defaults to true + * @return array The two-dimensional array representing the CSV + */ + private function parse_csv ( $csv_string, $delimiter = ",", $skip_empty_lines = true, $trim_fields = true) { + $enc = preg_replace('/(? $line ) { + if ( preg_match( '/^http.*?(\d{3}).*?/i', $line, $http_code ) ) { + $headers[ 'http_code' ] = $http_code[ 1 ]; + } elseif ( '' !== trim( $line ) ) { + list( $key, $value ) = explode( ': ', $line ); + $headers[ strtolower( $key ) ] = $value; + } + } + + // determine the content-type and parse the response + switch ( $headers[ 'content-type' ] ) { + // XML + case 'text/xml': + case 'text/xml; charset=utf-8': + libxml_use_internal_errors( true ); + $response = new \SimpleXMLElement( $response, LIBXML_NOCDATA ); + if ( ! $response ) { + $errors = libxml_get_errors(); + throw new Exceptions\QualtricsXMLException( 'Qualtrics XML Parse Error: ' . $errors[ 0 ]->message, $errors[ 0 ]->code ); + } + $response = json_decode( json_encode( $this->xmlToArray( $response ) ) ); + break; + // JSON + case 'application/json': + $response = json_decode( $response ); + break; + // CSV (MS Excel format) + case 'application/vnd.msexcel': + $response = $this->parse_csv( $response ); + break; + // HTML + case 'text/html; charset=UTF-8': + // TODO + break; + // Something other than XML, JSON, HTML, or CSV + default: + throw new Exceptions\UnknownFormatException( 'Qualtrics returned a response in an unknown format: ' . $headers[ 'content-type' ] ); + break; + } + + return array( 'headers' => $headers, 'response' => $response ); + } + + + /** + * Private function that makes a generic Qualtrics API request. + * + * This function takes an API function name and an array of parameters + * and makes an attempt to fetch the data using the Qualtrics API. + * + * @param string $request The name of the API function to be called + * @param string[] $params An array which contains any necessary parameters for the API call + * @throws Exceptions\CurlNotInstalledException Thrown when the curl library is not installed on the server + * @throws Exceptions\QualtricsException Thrown when Qualtrics returns an error with the request + * @throws Exceptions\CurlException Thrown when the curl request is unsuccessful, e.g. request timeout + * @return object Returns an object representing the requested data + */ + private function request( $request, $params = array() ) { + + // throw an exception if curl is not installed + if ( ! function_exists( 'curl_init' ) ) throw new Exceptions\CurlNotInstalledException( 'Curl does not appear to be installed on your server.' ); + + // create a new curl handle + $ch = curl_init( 'https://survey.qualtrics.com/WRAPI/ControlPanel/api.php' ); + + // set the parameters for the request + $params = array_merge( array( + 'Request' => $request, + 'User' => $this->username, + 'Token' => $this->token, + 'Version' => '2.2', + ), $params + ); + + // set curl options + curl_setopt_array( $ch, array( + CURLOPT_RETURNTRANSFER => true, + CURLOPT_HEADER => true, + CURLOPT_POST => true, + CURLOPT_POSTFIELDS => $params, + CURLOPT_CONNECTTIMEOUT => 0 + )); + + // make the request + $result = curl_exec( $ch ); + + // handle the result + if ( false !== $result ) { + // request was successful, parse the result + $result = $this->parseResponse( $ch, $result, $request ); + if ( isset( $result[ 'response' ]->Meta->Status ) ) { + if ( 'Success' == $result[ 'response' ]->Meta->Status ) { + return $result[ 'response' ]->Result; + } else { + // Qualtrics returned an error + throw new Exceptions\QualtricsException( 'Qualtrics error: ' . $result[ 'response' ]->Meta->ErrorMessage, $result[ 'response' ]->Meta->ErrorCode ); + } + } elseif ( '200' == $result[ 'headers' ][ 'http_code' ] ) { + // some responses, e.g. getLegacyResponseData do NOT have a Meta section + return $result[ 'response' ]; + } else { + // some other error + // TODO + } + } else { + // there was an error with the curl request + throw new Exceptions\CurlException( 'Curl error: ' . curl_error( $ch ), curl_errno( $ch ) ); + } + curl_close( $ch ); + } + + /** + * Gets the total number of responses for a survey in a given date range + * + * ``` + * $params = array( + * 'Format' => 'JSON', // Must be XML or JSON, defaults to JSON + * 'StartDate' => 'YYYY-MM-DD', // Start date of responses to include + * 'EndDate' => 'YYYY-MM-DD', // (optional) defaults to today's date + * 'SurveyID' => 'SV_9LC2rrUZT8c2EiF', // the Qualtrics ID of the survey in question. + * ); + * ``` + * + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Returns a PHP object with the resulting counts of "Auditable", "Generated" and "Deleted" responses + */ + function getResponseCountsBySurvey( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'StartDate' => null, + 'EndDate' => date( 'Y-m-d' ), + 'SurveyID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'StartDate' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required StartDate parameter was not specified' ); + if ( ! $params[ 'SurveyID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required SurveyID parameter was not specified' ); + + // try to fetch and return the result + return $this->request( 'getResponseCountsBySurvey', $params ); + } + + /** + * Gets information about a user + * + * ``` + * $params = array( + * 'Format' => 'JSON', // Must be XML or JSON, defaults to JSON + * ); + * ``` + * + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Information about the user in question + */ + function getUserInfo( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( 'Format' => 'JSON' ), $params ); + + // try to fetch and return the results + return $this->request( 'getUserInfo', $params ); + } + + /** + * Add a new recipient to a panel + * + * ``` + * $params = array( + * 'Format' => 'JSON', // Must be XML or JSON, defaults to JSON + * 'LibraryID' => 'GR_6G4LaoiroGxHH12', // Start date of responses to include + * 'PanelID' => 'ML_5yIfnFP0soZK3GJ', // Start date of responses to include + * 'FirstName' => 'Douglas', // Recipient's first name + * 'LastName' => 'Crockford', // Recipient's last name + * 'Email' => 'doug@js.org', // Recipient's email address + * 'ExternalDataRef' => 'crockdx', // (optional) + * 'Language' => 'EN', // (optional) language, defaults to EN + * 'ED[***]' => '@dougcrockford', // (optional) embedded data, e.g. ED[twitterID] + * // multiple values for ED possible + * ); + * ``` + * + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Returns true on success + */ + function addRecipient( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'PanelID' => null, + 'FirstName' => null, + 'LastName' => null, + 'Email' => null, + 'Language' => 'EN', + ), $params + ); + + // check for missing values + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + if ( ! $params[ 'FirstName' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FirstName parameter was not specified' ); + if ( ! $params[ 'LastName' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required LastName parameter was not specified' ); + if ( ! $params[ 'Email' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Email parameter was not specified' ); + + // fetch the response + return $this->request( 'addRecipient', $params ); + } + + /** + * Creates a distribution for survey and a panel. No emails will be sent. Distribution links can be generated later to take the survey. + * + * @param string Format Must be XML or JSON, JSON is default + * @param string SurveyID The ID of the survey to create a distribution for + * @param string PanelID The ID of the panel for the distribution + * @param string Description A description of the distribution + * @param string PanelLibraryID The library ID of the panel + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object An object containing the DistributionID + */ + function createDistribution( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'PanelLibraryID' => $this->library, + 'PanelID' => null, + 'SurveyID' => null, + 'Description' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + if ( ! $params[ 'SurveyID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required SurveyID parameter was not specified' ); + if ( ! $params[ 'Description' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Description parameter was not specified' ); + + // fetch and return the response + return $this->request( 'createDistribution', $params ); + } + + /** + * Creates a new Panel in the Qualtrics System and returns the ID of the new panel + * + * @param string Format Must be JSON or XML, defaults to JSON + * @param string LibraryID The library ID of the user creating the panel + * @param string Name A name for the new panel + * @param string Category (optional) The category the panel is created in + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Returns the ID of the new panel + */ + function createPanel( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'Name' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'Name' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Name parameter was not specified' ); + + // fetch and return the response + return $this->request( 'createPanel', $params ); + } + + /** + * Gets all the panel members for the given panel + * + * @param string Format Must be XML, CSV, or HTML, defaults to CSV + * @param string LibraryID The library ID of the panel + * @param string PanelID The panel ID you want to export + * @param string EmbeddedData A comma-separated list of the embedded data keys you want to export. Only required for CSV export. XML includes all embedded data. + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The panel members and any requested data + */ + function getPanel( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'CSV', + 'LibraryID' => $this->library, + 'PanelID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'getPanel', $params ); + } + + /** + * Deletes a panel + * + * @param string Format Must be XML, CSV, or HTML, defaults to CSV + * @param string LibraryID The library ID of the panel + * @param string PanelID The panel ID you want to export + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The results of the deletion process + */ + function deletePanel( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'PanelID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'deletePanel', $params ); + } + + /** + * Gets the number of panel members + * + * @param string Format Must be XML or JSON, defaults to JSON + * @param string LibraryID The library ID of the panel + * @param string PanelID The panel ID you want to get a count for + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The number of members of the panel + */ + function getPanelMemberCount( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'PanelID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'getPanelMemberCount', $params ); + } + + /** + * Gets all of the panels in a given library + * + * @param string Format Must be XML or JSON, defaults to JSON + * @param string LibraryID The library ID of the panel + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The panels in the library + */ + function getPanels( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + ), $params + ); + + // fetch and return the response + return $this->request( 'getPanels', $params ); + } + + /** + * Gets a representation of the recipient and their history + * + * @param string Format Must be XML or JSON, defaults to JSON + * @param string LibraryID The library ID of the panel + * @param string RecipientID The recipient ID you want to get + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The representation of the recipient + */ + function getRecipient( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'RecipientID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'RecipientID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required RecipientID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'getRecipient', $params ); + } + + /** + * Imports a csv file as a new panel + * + * Imports a csv file as a new panel (optionally it can append to a previously made panel) + * into the database and returns the panel id. The csv file can be posted (there is an + * approximate 8 megabytes limit) or a url can be given to retrieve the file from a remote server. + * The csv file must be comma separated using " for encapsulation. + * + * @param string Format Must be XML or JSON, JSON is default + * @param string LibraryID The library ID into which you want to import the panel + * @param string ColumnHeaders 0:1 If headers exist, these can be used when importing embedded data, defaults to 1 + * @param string Email The number of the column that contains the email address + * @param string URL (optional) If given, then the CSV file will be downloaded into Qualtrics from this URL + * @param string Name (optional) The name of the panel if creating a new one + * @param string PanelID (optional) If given, indicates the ID of the panel to be updated + * @param string FirstName (optional) The number of the column containing recipients' first names + * @param string LastName (optional) The number of the column containing recipients' last names + * @param string ExternalRef (optional) The number of the column containing recipients' external data reference + * @param string Language (optional) The number of the column containing recipients' languages + * @param string AllED (optional) 0:1 If set to 1, will import all non-used columns as embedded data, and you won't have to set the EmbeddedData parameter + * @param string EmbeddedData (optional) Comma-separated list of column numbers to treat as embedded data + * @param string Category (optional) Sets the category for the panel + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Contains the new PanelID, a count of imported recipients, and a count of ignored recipients + */ + function importPanel( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'ColumnHeaders' => 1, + 'Email' => null, + ), $params + ); + + // TODO: Figure out how to handle POST file uploads with this method + + // check for missing values + if ( ! $params[ 'Email' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Email parameter was not specified' ); + + // fetch and return the response + return $this->request( 'importPanel', $params ); + } + + /** + * Removes a specified panel member from a specified panel + * + * @param string Format Must be XML or JSON, defaults to JSON + * @param string LibraryID The library ID of the panel + * @param string PanelID The ID of the panel from which the recipient will be removed + * @param string RecipientID The recipient ID you want to remove + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The representation of the recipient + */ + function removeRecipient( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'PanelID' => null, + 'RecipientID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + if ( ! $params[ 'RecipientID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required RecipientID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'removeRecipient', $params ); + } + + /** + * Sends a reminder through the Qualtrics mailer to the panel or individual as specified by the parent distribution Id + * + * @param string Format Must be XML or JSON, JSON is default + * @param string ParentEmailDistributionID The parent distribution you are reminding + * @param string SendDate YYYY-MM-DD hh:mm:ss when you wan the mailing to go out, defaults to now + * @param string FromEmail The email address from which the email should appear to originate + * @param string FromName The name the message will appear to be from + * @param string Subject The subject for the email + * @param string MessageID The ID of the message from the message library to be sent + * @param string LibraryID The ID of the library that contains the message to be sent + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The email distribution ID and distribution queue id + */ + function sendReminder( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'ParentEmailDistributionID' => null, + 'SendDate' => date( 'Y-m-d H:i:s', time() - ( 60 * 119 ) ), //TODO: investigate if this time shuffling is still necessary... + 'FromEmail' => null, + 'FromName' => null, + 'Subject' => null, + 'MessageID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'ParentEmailDistributionID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required ParentEmailDistributionID parameter was not specified' ); + if ( ! $params[ 'FromEmail' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FromEmail parameter was not specified' ); + if ( ! $params[ 'FromName' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FromName parameter was not specified' ); + if ( ! $params[ 'Subject' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Subject parameter was not specified' ); + if ( ! $params[ 'MessageID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required MessageID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'sendReminder', $params ); + } + + /** + * Sends a survey through the Qualtrics mailer to the individual specified + * + * @param string Format Must be XML or JSON, JSON is default + * @param string SurveyID The ID of the survey to be sent + * @param string SendDate YYYY-MM-DD hh:mm:ss when you wan the mailing to go out, defaults to now + * @param string FromEmail The email address from which the email should appear to originate + * @param string FromName The name the message will appear to be from + * @param string Subject The subject for the email + * @param string MessageID The ID of the message from the message library to be sent + * @param string MessageLibraryID The ID of the library that contains the message to be sent + * @param string PanelID The ID of the message from the message library to be sent + * @param string PanelLibraryID The ID of the library that contains the message to be sent + * @param string RecipientID The recipient ID of the person to whom to send the survey + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The email distribution ID and distribution queue id + */ + function sendSurveyToIndividual( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'MessageLibraryID' => $this->library, + 'PanelLibraryID' => $this->library, + 'SurveyID' => null, + 'SendDate' => date( 'Y-m-d H:i:s', time() - ( 60 * 119 ) ), //TODO: investigate if this time shuffling is still necessary... + 'FromEmail' => null, + 'FromName' => null, + 'Subject' => null, + 'MessageID' => null, + 'PanelID' => null, + 'RecipientID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'SurveyID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required SurveyID parameter was not specified' ); + if ( ! $params[ 'FromEmail' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FromEmail parameter was not specified' ); + if ( ! $params[ 'FromName' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FromName parameter was not specified' ); + if ( ! $params[ 'Subject' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Subject parameter was not specified' ); + if ( ! $params[ 'MessageID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required MessageID parameter was not specified' ); + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + if ( ! $params[ 'RecipientID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required RecipientID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'sendSurveyToIndividual', $params ); + } + + /** + * Sends a survey through the Qualtrics mailer to the panel specified + * + * @param string Format Must be XML or JSON, JSON is default + * @param string SurveyID The ID of the survey to be sent + * @param string SendDate YYYY-MM-DD hh:mm:ss when you wan the mailing to go out, defaults to now + * @param string FromEmail The email address from which the email should appear to originate + * @param string FromName The name the message will appear to be from + * @param string Subject The subject for the email + * @param string MessageID The ID of the message from the message library to be sent + * @param string MessageLibraryID The ID of the library that contains the message to be sent + * @param string PanelID The ID of the message from the message library to be sent + * @param string PanelLibraryID The ID of the library that contains the message to be sent + * @param string ExpirationDate (optional) YYYY-MM-DD hh:mm:ss when the survey invitation expires + * @param string LinkType (optional) {Individual,Multiple,Anonymous} Defaults to Individual + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object The email distribution ID and distribution queue id + */ + function sendSurveyToPanel( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'MessageLibraryID' => $this->library, + 'PanelLibraryID' => $this->library, + 'SurveyID' => null, + 'SendDate' => date( 'Y-m-d H:i:s', time() - ( 60 * 119 ) ), //TODO: investigate if this time shuffling is still necessary... + 'FromEmail' => null, + 'FromName' => null, + 'Subject' => null, + 'MessageID' => null, + 'PanelID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'SurveyID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required SurveyID parameter was not specified' ); + if ( ! $params[ 'FromEmail' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FromEmail parameter was not specified' ); + if ( ! $params[ 'FromName' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required FromName parameter was not specified' ); + if ( ! $params[ 'Subject' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required Subject parameter was not specified' ); + if ( ! $params[ 'MessageID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required MessageID parameter was not specified' ); + if ( ! $params[ 'PanelID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required PanelID parameter was not specified' ); + + // fetch and return the response + return $this->request( 'sendSurveyToPanel', $params ); + } + + /** + * Updates the recipient’s data—any value not specified will be left alone and not updated + * + * @param string Format Must be XML or JSON, defaults to JSON + * @param string LibraryID The LibraryID of the user who owns the panel + * @param string RecipientID The ID of the recipient whose data will be updated + * @param string FirstName First name of the new recipient + * @param string LastName Last name of the new recipient + * @param string Email Email address of the new recipient + * @param string ExternalDataRef (optional) A value to store in the external data ref for the user (should default to the WordPress username) + * @param string Language (optional) The language code for the user, e.g. EN, defaults to EN + * @param string ED[***] (optional) An embedded data value, there can be many, and takes the form e.g. ED[skypeID]=mcbenton + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Returns true on success or WP_Error on failure + **/ + function updateRecipient( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'LibraryID' => $this->library, + 'RecipientID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'RecipientID' ] ) throw new Exceptions\MissingParameterExtension( 'Missing Parameter: The required RecipientID parameter was not specified' ); + if ( ! $params[ 'RecipientID' ] ) throw new Exceptions\MissingParameterException( 'Missing Parameter: The required RecipientID parameter was not specified' ); + + // fetch the response + $response = $this->request( 'updateRecipient', $params ); + return ( ! is_wp_error( $response ) ) ? true : $response; + } + + /** + * Returns all of the response data for a survey in the original (legacy) data format + * + * @param string Format {XML,JSON,CSV,HTML} default is JSON + * @param string SurveyID The ID of the survey you'll be getting responses for + * @param string LastResponseID (optional) When specified it will export all responses after the ID specified + * @param string Limit (optional) Max number of responses to return + * @param string ResponseID (optional) ID of an individual response to be returned + * @param string ResponseSetID (optional) ID of a response set to return, if unspecified returns default response set + * @param string SubgroupID (optional) Subgroup you want to download data for + * @param string StartDate (optional) YYYY-MM-DD hh:mm:ss Date the responses must be after + * @param string EndDate (optional) YYYY-MM-DD hh:mm:ss Date the responses must be before + * @param string Questions (optional) Comma-separated list of question ids + * @param string Labels (optional) If 1 (true) the label for choices and answers will be used, not the ID. Default is 0 + * @param string ExportTags (optional) If 1 (true) the export tags will be used rather than the V labels. Default is 1 + * @param string ExportQuestionIDs (optional) If 1 (true) the internal question IDs will be used rather than export tags or V labels. Default is 0 + * @param string LocalTime (optional) If 1 (true) the StartDate and EndDate will be exported using the specified user's local time zone. Default is 1 + * @param string UnansweredRecode (optional) The recode value for seen but unanswered questions. If not specified a blank value is put in for these questions. + * @param string PanelID (optional) If supplied it will only get the results for the members of the panel specified + * @param string ResponseInProgress (optional) If 1 (true) will retrieve the responses in progress (and only the responses in progress ) + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object An object representing the responses for the specified panel members + */ + public function getLegacyResponseData( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + 'SurveyID' => null, + 'ExportTags' => 1, + ), $params + ); + + // check for missing values + if ( ! $params[ 'SurveyID' ] ) throw new Exceptions\MissingParameterExtension( 'Missing Parameter: The required SurveyID parameter was not specified' ); + + // fetch the response + $response = $this->request( 'getLegacyResponseData', $params ); + // standardize the response format to an array of objects with the same properties + switch ( $params[ 'Format' ] ) { + case 'XML': $response = $response->Response; break; + case 'JSON': + $responses = array(); + foreach ( $response as $rid => $r ) { + $r->ResponseID = $rid; + $responses[] = $r; + } + $response = $responses; + break; + case 'CSV': + $keys = $values = array(); + foreach ( $response as $i => $r ) { + foreach ( $r as $j => $v ) { + if ( $i != 0 ) { + if ( $i == 1 ) { + $keys[ $j ] = preg_match( '/Q\d+/i', $response[ 0 ][ $j ] ) ? $response[ 0 ][ $j ] : $v; + } else { + if ( ! isset( $values[ $i ] ) ) $values[ $i ] = new \stdClass; + if ( '' != $keys[ $j ] ) $values[ $i ]->{$keys[ $j ]} = $v; + } + } + } + } + $response = array_values( $values ); + break; + } + return $response; + } + + /** + * This request returns an xml export of the survey. NOTE: Custom response format! + * + * @param string SurveyID The ID of the survey to be exported + * @param string ExportLogic If 1 (true) it will export the logic. EXPERIMENTAL + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object On object representing the survey. + */ + function getSurvey( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'SurveyID' => null, + ), $params + ); + + // check for missing values + if ( ! $params[ 'SurveyID' ] ) throw new Exceptions\MissingParameterExtension( 'Missing Parameter: The required SurveyID parameter was not specified' ); + + // fetch the response + // TODO: This function returns data in a non-standard format. Needs to be handled specially. + return $this->request( 'getSurvey', $params ); + } + + /** + * This request returns a list of all the surveys for the user + * + * @param string Format {XML,JSON} Default is JSON + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object A list of surveys available to the user + */ + function getSurveys( $params = array() ) { + // set the parameters for this request + $params = array_merge( array( + 'Format' => 'JSON', + ), $params + ); + + // fetch and return the response + $response = $this->request( 'getSurveys', $params ); + return 'XML' === $params[ 'Format' ] ? $response->Surveys->element : $response->Surveys; + } + +} diff --git a/docs/api/files/Morphatic/Qualtrics/QualtricsServiceProvider.php.txt b/docs/api/files/Morphatic/Qualtrics/QualtricsServiceProvider.php.txt new file mode 100644 index 0000000..df93c1c --- /dev/null +++ b/docs/api/files/Morphatic/Qualtrics/QualtricsServiceProvider.php.txt @@ -0,0 +1,76 @@ +package( 'morphatic/qualtrics' ); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + // bind the Qualtrics class for use with a facade + $this->app->bind( 'qualtrics', function() { return new Qualtrics; } ); + + // register exception handlers + $this->app->error( function( Exceptions\QualtricsException $e ) { + return $e->getCode() . ': ' . $e->getMessage(); + }); + $this->app->error( function( Exceptions\QualtricsXMLException $e ) { + return $e->getCode() . ': ' . $e->getMessage(); + }); + $this->app->error( function( Exceptions\CurlException $e ) { + return $e->getCode() . ': ' . $e->getMessage(); + }); + $this->app->error( function( Exceptions\CurlNotInstalledException $e ) { + return $e->getMessage(); + }); + $this->app->error( function( Exceptions\UnknownFormatException $e ) { + return $e->getMessage(); + }); + $this->app->error( function( Exceptions\MissingParameterException $e ) { + return $e->getCode() . ': ' . $e->getMessage(); + }); + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides() + { + return array(); + } + +} diff --git a/docs/api/files/config.config.php.html b/docs/api/files/config.config.php.html new file mode 100644 index 0000000..0d444f3 --- /dev/null +++ b/docs/api/files/config.config.php.html @@ -0,0 +1,327 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ + + +

configconfig.php

+

config.php

+

Users of the package can hard-code Qualtrics authentication +credentials in this file.

+ + + +
+ + +
+ + + +
+
+ + + + +
+ + + diff --git a/docs/api/files/config/config.php.txt b/docs/api/files/config/config.php.txt new file mode 100644 index 0000000..1cfe48c --- /dev/null +++ b/docs/api/files/config/config.php.txt @@ -0,0 +1,28 @@ + '', + 'token' => '', + 'library' => '', +]; diff --git a/docs/api/graphs/class.html b/docs/api/graphs/class.html new file mode 100644 index 0000000..02f9218 --- /dev/null +++ b/docs/api/graphs/class.html @@ -0,0 +1,167 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+ + +
+ + + diff --git a/docs/api/images/apple-touch-icon-114x114.png b/docs/api/images/apple-touch-icon-114x114.png new file mode 100644 index 0000000..1506f6a Binary files /dev/null and b/docs/api/images/apple-touch-icon-114x114.png differ diff --git a/docs/api/images/apple-touch-icon-72x72.png b/docs/api/images/apple-touch-icon-72x72.png new file mode 100644 index 0000000..d813259 Binary files /dev/null and b/docs/api/images/apple-touch-icon-72x72.png differ diff --git a/docs/api/images/apple-touch-icon.png b/docs/api/images/apple-touch-icon.png new file mode 100644 index 0000000..2d320cb Binary files /dev/null and b/docs/api/images/apple-touch-icon.png differ diff --git a/docs/api/images/custom-icons.svg b/docs/api/images/custom-icons.svg new file mode 100644 index 0000000..c6b8037 --- /dev/null +++ b/docs/api/images/custom-icons.svg @@ -0,0 +1,116 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/api/images/favicon.ico b/docs/api/images/favicon.ico new file mode 100644 index 0000000..9575ac8 Binary files /dev/null and b/docs/api/images/favicon.ico differ diff --git a/docs/api/images/hierarchy-item.png b/docs/api/images/hierarchy-item.png new file mode 100644 index 0000000..c7756e7 Binary files /dev/null and b/docs/api/images/hierarchy-item.png differ diff --git a/docs/api/images/icon-class-13x13.png b/docs/api/images/icon-class-13x13.png new file mode 100644 index 0000000..731f0bd Binary files /dev/null and b/docs/api/images/icon-class-13x13.png differ diff --git a/docs/api/images/icon-class.svg b/docs/api/images/icon-class.svg new file mode 100644 index 0000000..7dacd0c --- /dev/null +++ b/docs/api/images/icon-class.svg @@ -0,0 +1,77 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/api/images/icon-interface-13x13.png b/docs/api/images/icon-interface-13x13.png new file mode 100644 index 0000000..aa24fa9 Binary files /dev/null and b/docs/api/images/icon-interface-13x13.png differ diff --git a/docs/api/images/icon-interface.svg b/docs/api/images/icon-interface.svg new file mode 100644 index 0000000..7c6371e --- /dev/null +++ b/docs/api/images/icon-interface.svg @@ -0,0 +1,73 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/api/images/icon-trait-13x13.png b/docs/api/images/icon-trait-13x13.png new file mode 100644 index 0000000..3c2792b Binary files /dev/null and b/docs/api/images/icon-trait-13x13.png differ diff --git a/docs/api/images/icon-trait.svg b/docs/api/images/icon-trait.svg new file mode 100644 index 0000000..03cf08f --- /dev/null +++ b/docs/api/images/icon-trait.svg @@ -0,0 +1,73 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/docs/api/images/iviewer/grab.cur b/docs/api/images/iviewer/grab.cur new file mode 100644 index 0000000..ef540be Binary files /dev/null and b/docs/api/images/iviewer/grab.cur differ diff --git a/docs/api/images/iviewer/hand.cur b/docs/api/images/iviewer/hand.cur new file mode 100644 index 0000000..1a5bafb Binary files /dev/null and b/docs/api/images/iviewer/hand.cur differ diff --git a/docs/api/images/iviewer/iviewer.rotate_left.png b/docs/api/images/iviewer/iviewer.rotate_left.png new file mode 100644 index 0000000..df0956d Binary files /dev/null and b/docs/api/images/iviewer/iviewer.rotate_left.png differ diff --git a/docs/api/images/iviewer/iviewer.rotate_right.png b/docs/api/images/iviewer/iviewer.rotate_right.png new file mode 100644 index 0000000..7a6c829 Binary files /dev/null and b/docs/api/images/iviewer/iviewer.rotate_right.png differ diff --git a/docs/api/images/iviewer/iviewer.zoom_fit.png b/docs/api/images/iviewer/iviewer.zoom_fit.png new file mode 100644 index 0000000..364e01d Binary files /dev/null and b/docs/api/images/iviewer/iviewer.zoom_fit.png differ diff --git a/docs/api/images/iviewer/iviewer.zoom_in.png b/docs/api/images/iviewer/iviewer.zoom_in.png new file mode 100644 index 0000000..7899332 Binary files /dev/null and b/docs/api/images/iviewer/iviewer.zoom_in.png differ diff --git a/docs/api/images/iviewer/iviewer.zoom_out.png b/docs/api/images/iviewer/iviewer.zoom_out.png new file mode 100644 index 0000000..893f350 Binary files /dev/null and b/docs/api/images/iviewer/iviewer.zoom_out.png differ diff --git a/docs/api/images/iviewer/iviewer.zoom_zero.png b/docs/api/images/iviewer/iviewer.zoom_zero.png new file mode 100644 index 0000000..c981db6 Binary files /dev/null and b/docs/api/images/iviewer/iviewer.zoom_zero.png differ diff --git a/docs/api/index.html b/docs/api/index.html new file mode 100644 index 0000000..028c1e9 --- /dev/null +++ b/docs/api/index.html @@ -0,0 +1,267 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +

\

+ +

Namespaces

+ + + + +
Morphatic
+ + + +
+ + +
+ + + +
+
+ + +
+ + + diff --git a/docs/api/js/jquery.dotdotdot-1.5.9.js b/docs/api/js/jquery.dotdotdot-1.5.9.js new file mode 100644 index 0000000..7220bdb --- /dev/null +++ b/docs/api/js/jquery.dotdotdot-1.5.9.js @@ -0,0 +1,602 @@ +/* + * jQuery dotdotdot 1.5.9 + * + * Copyright (c) 2013 Fred Heusschen + * www.frebsite.nl + * + * Plugin website: + * dotdotdot.frebsite.nl + * + * Dual licensed under the MIT and GPL licenses. + * http://en.wikipedia.org/wiki/MIT_License + * http://en.wikipedia.org/wiki/GNU_General_Public_License + */ + +(function( $ ) +{ + if ( $.fn.dotdotdot ) + { + return; + } + + $.fn.dotdotdot = function( o ) + { + if ( this.length == 0 ) + { + if ( !o || o.debug !== false ) + { + debug( true, 'No element found for "' + this.selector + '".' ); + } + return this; + } + if ( this.length > 1 ) + { + return this.each( + function() + { + $(this).dotdotdot( o ); + } + ); + } + + + var $dot = this; + + if ( $dot.data( 'dotdotdot' ) ) + { + $dot.trigger( 'destroy.dot' ); + } + + $dot.data( 'dotdotdot-style', $dot.attr( 'style' ) ); + $dot.css( 'word-wrap', 'break-word' ); + + $dot.bind_events = function() + { + $dot.bind( + 'update.dot', + function( e, c ) + { + e.preventDefault(); + e.stopPropagation(); + + opts.maxHeight = ( typeof opts.height == 'number' ) + ? opts.height + : getTrueInnerHeight( $dot ); + + opts.maxHeight += opts.tolerance; + + if ( typeof c != 'undefined' ) + { + if ( typeof c == 'string' || c instanceof HTMLElement ) + { + c = $('
').append( c ).contents(); + } + if ( c instanceof $ ) + { + orgContent = c; + } + } + + $inr = $dot.wrapInner( '
' ).children(); + $inr.empty() + .append( orgContent.clone( true ) ) + .css({ + 'height' : 'auto', + 'width' : 'auto', + 'border' : 'none', + 'padding' : 0, + 'margin' : 0 + }); + + var after = false, + trunc = false; + + if ( conf.afterElement ) + { + after = conf.afterElement.clone( true ); + conf.afterElement.remove(); + } + if ( test( $inr, opts ) ) + { + if ( opts.wrap == 'children' ) + { + trunc = children( $inr, opts, after ); + } + else + { + trunc = ellipsis( $inr, $dot, $inr, opts, after ); + } + } + $inr.replaceWith( $inr.contents() ); + $inr = null; + + if ( $.isFunction( opts.callback ) ) + { + opts.callback.call( $dot[ 0 ], trunc, orgContent ); + } + + conf.isTruncated = trunc; + return trunc; + } + + ).bind( + 'isTruncated.dot', + function( e, fn ) + { + e.preventDefault(); + e.stopPropagation(); + + if ( typeof fn == 'function' ) + { + fn.call( $dot[ 0 ], conf.isTruncated ); + } + return conf.isTruncated; + } + + ).bind( + 'originalContent.dot', + function( e, fn ) + { + e.preventDefault(); + e.stopPropagation(); + + if ( typeof fn == 'function' ) + { + fn.call( $dot[ 0 ], orgContent ); + } + return orgContent; + } + + ).bind( + 'destroy.dot', + function( e ) + { + e.preventDefault(); + e.stopPropagation(); + + $dot.unwatch() + .unbind_events() + .empty() + .append( orgContent ) + .attr( 'style', $dot.data( 'dotdotdot-style' ) ) + .data( 'dotdotdot', false ); + } + ); + return $dot; + }; // /bind_events + + $dot.unbind_events = function() + { + $dot.unbind('.dot'); + return $dot; + }; // /unbind_events + + $dot.watch = function() + { + $dot.unwatch(); + if ( opts.watch == 'window' ) + { + var $window = $(window), + _wWidth = $window.width(), + _wHeight = $window.height(); + + $window.bind( + 'resize.dot' + conf.dotId, + function() + { + if ( _wWidth != $window.width() || _wHeight != $window.height() || !opts.windowResizeFix ) + { + _wWidth = $window.width(); + _wHeight = $window.height(); + + if ( watchInt ) + { + clearInterval( watchInt ); + } + watchInt = setTimeout( + function() + { + $dot.trigger( 'update.dot' ); + }, 10 + ); + } + } + ); + } + else + { + watchOrg = getSizes( $dot ); + watchInt = setInterval( + function() + { + var watchNew = getSizes( $dot ); + if ( watchOrg.width != watchNew.width || + watchOrg.height != watchNew.height ) + { + $dot.trigger( 'update.dot' ); + watchOrg = getSizes( $dot ); + } + }, 100 + ); + } + return $dot; + }; + $dot.unwatch = function() + { + $(window).unbind( 'resize.dot' + conf.dotId ); + if ( watchInt ) + { + clearInterval( watchInt ); + } + return $dot; + }; + + var orgContent = $dot.contents(), + opts = $.extend( true, {}, $.fn.dotdotdot.defaults, o ), + conf = {}, + watchOrg = {}, + watchInt = null, + $inr = null; + + conf.afterElement = getElement( opts.after, $dot ); + conf.isTruncated = false; + conf.dotId = dotId++; + + + $dot.data( 'dotdotdot', true ) + .bind_events() + .trigger( 'update.dot' ); + + if ( opts.watch ) + { + $dot.watch(); + } + + return $dot; + }; + + + // public + $.fn.dotdotdot.defaults = { + 'ellipsis' : '... ', + 'wrap' : 'word', + 'lastCharacter': { + 'remove' : [ ' ', ',', ';', '.', '!', '?' ], + 'noEllipsis' : [] + }, + 'tolerance' : 0, + 'callback' : null, + 'after' : null, + 'height' : null, + 'watch' : false, + 'windowResizeFix': true, + 'debug' : false + }; + + + // private + var dotId = 1; + + function children( $elem, o, after ) + { + var $elements = $elem.children(), + isTruncated = false; + + $elem.empty(); + + for ( var a = 0, l = $elements.length; a < l; a++ ) + { + var $e = $elements.eq( a ); + $elem.append( $e ); + if ( after ) + { + $elem.append( after ); + } + if ( test( $elem, o ) ) + { + $e.remove(); + isTruncated = true; + break; + } + else + { + if ( after ) + { + after.remove(); + } + } + } + return isTruncated; + } + function ellipsis( $elem, $d, $i, o, after ) + { + var $elements = $elem.contents(), + isTruncated = false; + + $elem.empty(); + + var notx = 'table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, select, optgroup, option, textarea, script, style'; + for ( var a = 0, l = $elements.length; a < l; a++ ) + { + + if ( isTruncated ) + { + break; + } + + var e = $elements[ a ], + $e = $(e); + + if ( typeof e == 'undefined' ) + { + continue; + } + + $elem.append( $e ); + if ( after ) + { + $elem[ ( $elem.is( notx ) ) ? 'after' : 'append' ]( after ); + } + if ( e.nodeType == 3 ) + { + if ( test( $i, o ) ) + { + isTruncated = ellipsisElement( $e, $d, $i, o, after ); + } + } + else + { + isTruncated = ellipsis( $e, $d, $i, o, after ); + } + + if ( !isTruncated ) + { + if ( after ) + { + after.remove(); + } + } + } + return isTruncated; + } + function ellipsisElement( $e, $d, $i, o, after ) + { + var isTruncated = false, + e = $e[ 0 ]; + + if ( typeof e == 'undefined' ) + { + return false; + } + + var seporator = ( o.wrap == 'letter' ) ? '' : ' ', + textArr = getTextContent( e ).split( seporator ), + position = -1, + midPos = -1, + startPos = 0, + endPos = textArr.length - 1; + + while ( startPos <= endPos ) + { + var m = Math.floor( ( startPos + endPos ) / 2 ); + if ( m == midPos ) + { + break; + } + midPos = m; + + setTextContent( e, textArr.slice( 0, midPos + 1 ).join( seporator ) + o.ellipsis ); + + if ( !test( $i, o ) ) + { + position = midPos; + startPos = midPos; + } + else + { + endPos = midPos; + } + } + + if ( position != -1 && !( textArr.length == 1 && textArr[ 0 ].length == 0 ) ) + { + var txt = addEllipsis( textArr.slice( 0, position + 1 ).join( seporator ), o ); + isTruncated = true; + setTextContent( e, txt ); + } + else + { + var $w = $e.parent(); + $e.remove(); + + var afterLength = ( after ) ? after.length : 0 ; + + if ( $w.contents().size() > afterLength ) + { + var $n = $w.contents().eq( -1 - afterLength ); + isTruncated = ellipsisElement( $n, $d, $i, o, after ); + } + else + { + var $p = $w.prev() + var e = $p.contents().eq( -1 )[ 0 ]; + + if ( typeof e != 'undefined' ) + { + var txt = addEllipsis( getTextContent( e ), o ); + setTextContent( e, txt ); + if ( after ) + { + $p.append( after ); + } + $w.remove(); + isTruncated = true; + } + + } + } + + return isTruncated; + } + function test( $i, o ) + { + return $i.innerHeight() > o.maxHeight; + } + function addEllipsis( txt, o ) + { + while( $.inArray( txt.slice( -1 ), o.lastCharacter.remove ) > -1 ) + { + txt = txt.slice( 0, -1 ); + } + if ( $.inArray( txt.slice( -1 ), o.lastCharacter.noEllipsis ) < 0 ) + { + txt += o.ellipsis; + } + return txt; + } + function getSizes( $d ) + { + return { + 'width' : $d.innerWidth(), + 'height': $d.innerHeight() + }; + } + function setTextContent( e, content ) + { + if ( e.innerText ) + { + e.innerText = content; + } + else if ( e.nodeValue ) + { + e.nodeValue = content; + } + else if (e.textContent) + { + e.textContent = content; + } + + } + function getTextContent( e ) + { + if ( e.innerText ) + { + return e.innerText; + } + else if ( e.nodeValue ) + { + return e.nodeValue; + } + else if ( e.textContent ) + { + return e.textContent; + } + else + { + return ""; + } + } + function getElement( e, $i ) + { + if ( typeof e == 'undefined' ) + { + return false; + } + if ( !e ) + { + return false; + } + if ( typeof e == 'string' ) + { + e = $(e, $i); + return ( e.length ) + ? e + : false; + } + if ( typeof e == 'object' ) + { + return ( typeof e.jquery == 'undefined' ) + ? false + : e; + } + return false; + } + function getTrueInnerHeight( $el ) + { + var h = $el.innerHeight(), + a = [ 'paddingTop', 'paddingBottom' ]; + + for ( var z = 0, l = a.length; z < l; z++ ) { + var m = parseInt( $el.css( a[ z ] ), 10 ); + if ( isNaN( m ) ) + { + m = 0; + } + h -= m; + } + return h; + } + function debug( d, m ) + { + if ( !d ) + { + return false; + } + if ( typeof m == 'string' ) + { + m = 'dotdotdot: ' + m; + } + else + { + m = [ 'dotdotdot:', m ]; + } + + if ( typeof window.console != 'undefined' ) + { + if ( typeof window.console.log != 'undefined' ) + { + window.console.log( m ); + } + } + return false; + } + + + // override jQuery.html + var _orgHtml = $.fn.html; + $.fn.html = function( str ) { + if ( typeof str != 'undefined' ) + { + if ( this.data( 'dotdotdot' ) ) + { + if ( typeof str != 'function' ) + { + return this.trigger( 'update', [ str ] ); + } + } + return _orgHtml.call( this, str ); + } + return _orgHtml.call( this ); + }; + + + // override jQuery.text + var _orgText = $.fn.text; + $.fn.text = function( str ) { + if ( typeof str != 'undefined' ) + { + if ( this.data( 'dotdotdot' ) ) + { + var temp = $( '
' ); + temp.text( str ); + str = temp.html(); + temp.remove(); + return this.trigger( 'update', [ str ] ); + } + return _orgText.call( this, str ); + } + return _orgText.call( this ); + }; + + +})( jQuery ); diff --git a/docs/api/js/jquery.dotdotdot-1.5.9.min.js b/docs/api/js/jquery.dotdotdot-1.5.9.min.js new file mode 100644 index 0000000..8147b06 --- /dev/null +++ b/docs/api/js/jquery.dotdotdot-1.5.9.min.js @@ -0,0 +1,15 @@ +/* + * jQuery dotdotdot 1.5.9 + * + * Copyright (c) 2013 Fred Heusschen + * www.frebsite.nl + * + * Plugin website: + * dotdotdot.frebsite.nl + * + * Dual licensed under the MIT and GPL licenses. + * http://en.wikipedia.org/wiki/MIT_License + * http://en.wikipedia.org/wiki/GNU_General_Public_License + */ + +(function(a){function c(a,b,c){var d=a.children(),e=!1;a.empty();for(var g=0,h=d.length;h>g;g++){var i=d.eq(g);if(a.append(i),c&&a.append(c),f(a,b)){i.remove(),e=!0;break}c&&c.remove()}return e}function d(b,c,g,h,i){var j=b.contents(),k=!1;b.empty();for(var l="table, thead, tbody, tfoot, tr, col, colgroup, object, embed, param, ol, ul, dl, select, optgroup, option, textarea, script, style",m=0,n=j.length;n>m&&!k;m++){var o=j[m],p=a(o);void 0!==o&&(b.append(p),i&&b[b.is(l)?"after":"append"](i),3==o.nodeType?f(g,h)&&(k=e(p,c,g,h,i)):k=d(p,c,g,h,i),k||i&&i.remove())}return k}function e(a,b,c,d,h){var k=!1,l=a[0];if(l===void 0)return!1;for(var m="letter"==d.wrap?"":" ",n=j(l).split(m),o=-1,p=-1,q=0,r=n.length-1;r>=q;){var s=Math.floor((q+r)/2);if(s==p)break;p=s,i(l,n.slice(0,p+1).join(m)+d.ellipsis),f(c,d)?r=p:(o=p,q=p)}if(-1==o||1==n.length&&0==n[0].length){var u=a.parent();a.remove();var v=h?h.length:0;if(u.contents().size()>v){var w=u.contents().eq(-1-v);k=e(w,b,c,d,h)}else{var x=u.prev(),l=x.contents().eq(-1)[0];if(l!==void 0){var t=g(j(l),d);i(l,t),h&&x.append(h),u.remove(),k=!0}}}else{var t=g(n.slice(0,o+1).join(m),d);k=!0,i(l,t)}return k}function f(a,b){return a.innerHeight()>b.maxHeight}function g(b,c){for(;a.inArray(b.slice(-1),c.lastCharacter.remove)>-1;)b=b.slice(0,-1);return 0>a.inArray(b.slice(-1),c.lastCharacter.noEllipsis)&&(b+=c.ellipsis),b}function h(a){return{width:a.innerWidth(),height:a.innerHeight()}}function i(a,b){a.innerText?a.innerText=b:a.nodeValue?a.nodeValue=b:a.textContent&&(a.textContent=b)}function j(a){return a.innerText?a.innerText:a.nodeValue?a.nodeValue:a.textContent?a.textContent:""}function k(b,c){return b===void 0?!1:b?"string"==typeof b?(b=a(b,c),b.length?b:!1):"object"==typeof b?b.jquery===void 0?!1:b:!1:!1}function l(a){for(var b=a.innerHeight(),c=["paddingTop","paddingBottom"],d=0,e=c.length;e>d;d++){var f=parseInt(a.css(c[d]),10);isNaN(f)&&(f=0),b-=f}return b}function m(a,b){return a?(b="string"==typeof b?"dotdotdot: "+b:["dotdotdot:",b],window.console!==void 0&&window.console.log!==void 0&&window.console.log(b),!1):!1}if(!a.fn.dotdotdot){a.fn.dotdotdot=function(e){if(0==this.length)return e&&e.debug===!1||m(!0,'No element found for "'+this.selector+'".'),this;if(this.length>1)return this.each(function(){a(this).dotdotdot(e)});var g=this;g.data("dotdotdot")&&g.trigger("destroy.dot"),g.data("dotdotdot-style",g.attr("style")),g.css("word-wrap","break-word"),g.bind_events=function(){return g.bind("update.dot",function(b,e){b.preventDefault(),b.stopPropagation(),j.maxHeight="number"==typeof j.height?j.height:l(g),j.maxHeight+=j.tolerance,e!==void 0&&(("string"==typeof e||e instanceof HTMLElement)&&(e=a("
").append(e).contents()),e instanceof a&&(i=e)),q=g.wrapInner('
').children(),q.empty().append(i.clone(!0)).css({height:"auto",width:"auto",border:"none",padding:0,margin:0});var h=!1,k=!1;return n.afterElement&&(h=n.afterElement.clone(!0),n.afterElement.remove()),f(q,j)&&(k="children"==j.wrap?c(q,j,h):d(q,g,q,j,h)),q.replaceWith(q.contents()),q=null,a.isFunction(j.callback)&&j.callback.call(g[0],k,i),n.isTruncated=k,k}).bind("isTruncated.dot",function(a,b){return a.preventDefault(),a.stopPropagation(),"function"==typeof b&&b.call(g[0],n.isTruncated),n.isTruncated}).bind("originalContent.dot",function(a,b){return a.preventDefault(),a.stopPropagation(),"function"==typeof b&&b.call(g[0],i),i}).bind("destroy.dot",function(a){a.preventDefault(),a.stopPropagation(),g.unwatch().unbind_events().empty().append(i).attr("style",g.data("dotdotdot-style")).data("dotdotdot",!1)}),g},g.unbind_events=function(){return g.unbind(".dot"),g},g.watch=function(){if(g.unwatch(),"window"==j.watch){var b=a(window),c=b.width(),d=b.height();b.bind("resize.dot"+n.dotId,function(){c==b.width()&&d==b.height()&&j.windowResizeFix||(c=b.width(),d=b.height(),p&&clearInterval(p),p=setTimeout(function(){g.trigger("update.dot")},10))})}else o=h(g),p=setInterval(function(){var a=h(g);(o.width!=a.width||o.height!=a.height)&&(g.trigger("update.dot"),o=h(g))},100);return g},g.unwatch=function(){return a(window).unbind("resize.dot"+n.dotId),p&&clearInterval(p),g};var i=g.contents(),j=a.extend(!0,{},a.fn.dotdotdot.defaults,e),n={},o={},p=null,q=null;return n.afterElement=k(j.after,g),n.isTruncated=!1,n.dotId=b++,g.data("dotdotdot",!0).bind_events().trigger("update.dot"),j.watch&&g.watch(),g},a.fn.dotdotdot.defaults={ellipsis:"... ",wrap:"word",lastCharacter:{remove:[" ",",",";",".","!","?"],noEllipsis:[]},tolerance:0,callback:null,after:null,height:null,watch:!1,windowResizeFix:!0,debug:!1};var b=1,n=a.fn.html;a.fn.html=function(a){return a!==void 0?this.data("dotdotdot")&&"function"!=typeof a?this.trigger("update",[a]):n.call(this,a):n.call(this)};var o=a.fn.text;a.fn.text=function(b){if(b!==void 0){if(this.data("dotdotdot")){var c=a("
");return c.text(b),b=c.html(),c.remove(),this.trigger("update",[b])}return o.call(this,b)}return o.call(this)}}})(jQuery); \ No newline at end of file diff --git a/docs/api/js/jquery.iviewer.js b/docs/api/js/jquery.iviewer.js new file mode 100644 index 0000000..ae08665 --- /dev/null +++ b/docs/api/js/jquery.iviewer.js @@ -0,0 +1,1169 @@ +/* + * iviewer Widget for jQuery UI + * https://github.com/can3p/iviewer + * + * Copyright (c) 2009 - 2012 Dmitry Petrov + * Dual licensed under the MIT and GPL licenses. + * - http://www.opensource.org/licenses/mit-license.php + * - http://www.gnu.org/copyleft/gpl.html + * + * Author: Dmitry Petrov + * Version: 0.7.7 + */ + +( function( $, undefined ) { + +//this code was taken from the https://github.com/furf/jquery-ui-touch-punch +var mouseEvents = { + touchstart: 'mousedown', + touchmove: 'mousemove', + touchend: 'mouseup' + }, + gesturesSupport = 'ongesturestart' in document.createElement('div'); + + +/** + * Convert a touch event to a mouse-like + */ +function makeMouseEvent (event) { + var touch = event.originalEvent.changedTouches[0]; + + return $.extend(event, { + type: mouseEvents[event.type], + which: 1, + pageX: touch.pageX, + pageY: touch.pageY, + screenX: touch.screenX, + screenY: touch.screenY, + clientX: touch.clientX, + clientY: touch.clientY, + isTouchEvent: true + }); +} + +var mouseProto = $.ui.mouse.prototype, + _mouseInit = $.ui.mouse.prototype._mouseInit; + +mouseProto._mouseInit = function() { + var self = this; + self._touchActive = false; + + this.element.bind( 'touchstart.' + this.widgetName, function(event) { + if (gesturesSupport && event.originalEvent.touches.length > 1) { return; } + self._touchActive = true; + return self._mouseDown(makeMouseEvent(event)); + }) + + var self = this; + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + if (gesturesSupport && event.originalEvent.touches && event.originalEvent.touches.length > 1) { return; } + if (self._touchActive) { + return self._mouseMove(makeMouseEvent(event)); + } + }; + this._mouseUpDelegate = function(event) { + if (self._touchActive) { + self._touchActive = false; + return self._mouseUp(makeMouseEvent(event)); + } + }; + + $(document) + .bind('touchmove.'+ this.widgetName, this._mouseMoveDelegate) + .bind('touchend.' + this.widgetName, this._mouseUpDelegate); + + _mouseInit.apply(this); +} + +/** + * Simple implementation of jQuery like getters/setters + * var val = something(); + * something(val); + */ +var setter = function(setter, getter) { + return function(val) { + if (arguments.length === 0) { + return getter.apply(this); + } else { + setter.apply(this, arguments); + } + } +}; + +/** + * Internet explorer rotates image relative left top corner, so we should + * shift image when it's rotated. + */ +var ieTransforms = { + '0': { + marginLeft: 0, + marginTop: 0, + filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")' + }, + + '90': { + marginLeft: -1, + marginTop: 1, + filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")' + }, + + '180': { + marginLeft: 0, + marginTop: 0, + filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")' + }, + + '270': { + marginLeft: -1, + marginTop: 1, + filter: 'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")' + } + }, + // this test is the inversion of the css filters test from the modernizr project + useIeTransforms = function() { + var modElem = document.createElement('modernizr'), + mStyle = modElem.style, + omPrefixes = 'Webkit Moz O ms', + domPrefixes = omPrefixes.toLowerCase().split(' '), + props = ("transform" + ' ' + domPrefixes.join("Transform ") + "Transform").split(' '); + for ( var i in props ) { + var prop = props[i]; + if ( !$.contains(prop, "-") && mStyle[prop] !== undefined ) { + return false; + } + } + return true; + }(); + +$.widget( "ui.iviewer", $.ui.mouse, { + widgetEventPrefix: "iviewer", + options : { + /** + * start zoom value for image, not used now + * may be equal to "fit" to fit image into container or scale in % + **/ + zoom: "fit", + /** + * base value to scale image + **/ + zoom_base: 100, + /** + * maximum zoom + **/ + zoom_max: 800, + /** + * minimum zoom + **/ + zoom_min: 25, + /** + * base of rate multiplier. + * zoom is calculated by formula: zoom_base * zoom_delta^rate + **/ + zoom_delta: 1.4, + /** + * whether the zoom should be animated. + */ + zoom_animation: true, + /** + * if true plugin doesn't add its own controls + **/ + ui_disabled: false, + /** + * If false mousewheel will be disabled + */ + mousewheel: true, + /** + * if false, plugin doesn't bind resize event on window and this must + * be handled manually + **/ + update_on_resize: true, + /** + * event is triggered when zoom value is changed + * @param int new zoom value + * @return boolean if false zoom action is aborted + **/ + onZoom: jQuery.noop, + /** + * event is triggered when zoom value is changed after image is set to the new dimensions + * @param int new zoom value + * @return boolean if false zoom action is aborted + **/ + onAfterZoom: jQuery.noop, + /** + * event is fired on drag begin + * @param object coords mouse coordinates on the image + * @return boolean if false is returned, drag action is aborted + **/ + onStartDrag: jQuery.noop, + /** + * event is fired on drag action + * @param object coords mouse coordinates on the image + **/ + onDrag: jQuery.noop, + /** + * event is fired on drag stop + * @param object coords mouse coordinates on the image + **/ + onStopDrag: jQuery.noop, + /** + * event is fired when mouse moves over image + * @param object coords mouse coordinates on the image + **/ + onMouseMove: jQuery.noop, + /** + * mouse click event + * @param object coords mouse coordinates on the image + **/ + onClick: jQuery.noop, + /** + * event is fired when image starts to load + */ + onStartLoad: null, + /** + * event is fired, when image is loaded and initially positioned + */ + onFinishLoad: null, + /** + * event is fired when image load error occurs + */ + onErrorLoad: null + }, + + _create: function() { + var me = this; + + //drag variables + this.dx = 0; + this.dy = 0; + + /* object containing actual information about image + * @img_object.object - jquery img object + * @img_object.orig_{width|height} - original dimensions + * @img_object.display_{width|height} - actual dimensions + */ + this.img_object = {}; + + this.zoom_object = {}; //object to show zoom status + + this._angle = 0; + + this.current_zoom = this.options.zoom; + + if(this.options.src === null){ + return; + } + + this.container = this.element; + + this._updateContainerInfo(); + + //init container + this.container.css("overflow","hidden"); + + if (this.options.update_on_resize == true) { + $(window).resize(function() { + me.update(); + }); + } + + this.img_object = new $.ui.iviewer.ImageObject(this.options.zoom_animation); + + if (this.options.mousewheel) { + this.container.bind('mousewheel.iviewer', function(ev, delta) + { + //this event is there instead of containing div, because + //at opera it triggers many times on div + var zoom = (delta > 0)?1:-1, + container_offset = me.container.offset(), + mouse_pos = { + //jquery.mousewheel 3.1.0 uses strange MozMousePixelScroll event + //which is not being fixed by jQuery.Event + x: (ev.pageX || ev.originalEvent.pageX) - container_offset.left, + y: (ev.pageY || ev.originalEvent.pageX) - container_offset.top + }; + + me.zoom_by(zoom, mouse_pos); + return false; + }); + + if (gesturesSupport) { + var gestureThrottle = +new Date(); + var originalScale, originalCenter; + this.img_object.object() + // .bind('gesturestart', function(ev) { + .bind('touchstart', function(ev) { + originalScale = me.current_zoom; + var touches = ev.originalEvent.touches, + container_offset; + if (touches.length == 2) { + container_offset = me.container.offset(); + originalCenter = { + x: (touches[0].pageX + touches[1].pageX) / 2 - container_offset.left, + y: (touches[0].pageY + touches[1].pageY) / 2 - container_offset.top + }; + } else { + originalCenter = null; + } + }).bind('gesturechange', function(ev) { + //do not want to import throttle function from underscore + var d = +new Date(); + if ((d - gestureThrottle) < 50) { return; } + gestureThrottle = d; + var zoom = originalScale * ev.originalEvent.scale; + me.set_zoom(zoom, originalCenter); + ev.preventDefault(); + }).bind('gestureend', function(ev) { + originalCenter = null; + }); + } + } + + //init object + this.img_object.object() + //bind mouse events + .click(function(e){return me._click(e)}) + .prependTo(this.container); + + this.container.bind('mousemove', function(ev) { me._handleMouseMove(ev); }); + + this.loadImage(this.options.src); + + if(!this.options.ui_disabled) + { + this.createui(); + } + + this._mouseInit(); + }, + + destroy: function() { + $.Widget.prototype.destroy.call( this ); + this._mouseDestroy(); + this.img_object.object().remove(); + this.container.off('.iviewer'); + this.container.css('overflow', ''); //cleanup styles on destroy + }, + + _updateContainerInfo: function() + { + this.options.height = this.container.height(); + this.options.width = this.container.width(); + }, + + update: function() + { + this._updateContainerInfo() + this.setCoords(this.img_object.x(), this.img_object.y()); + }, + + loadImage: function( src ) + { + this.current_zoom = this.options.zoom; + var me = this; + + this._trigger('onStartLoad', 0, src); + + this.container.addClass("iviewer_loading"); + this.img_object.load(src, function() { + me._imageLoaded(src); + }, function() { + me._trigger("onErrorLoad", 0, src); + }); + }, + + _imageLoaded: function(src) { + this.container.removeClass("iviewer_loading"); + this.container.addClass("iviewer_cursor"); + + if(this.options.zoom == "fit"){ + this.fit(true); + } + else { + this.set_zoom(this.options.zoom, true); + } + + this._trigger('onFinishLoad', 0, src); + }, + + /** + * fits image in the container + * + * @param {boolean} skip_animation + **/ + fit: function(skip_animation) + { + var aspect_ratio = this.img_object.orig_width() / this.img_object.orig_height(); + var window_ratio = this.options.width / this.options.height; + var choose_left = (aspect_ratio > window_ratio); + var new_zoom = 0; + + if(choose_left){ + new_zoom = this.options.width / this.img_object.orig_width() * 100; + } + else { + new_zoom = this.options.height / this.img_object.orig_height() * 100; + } + + this.set_zoom(new_zoom, skip_animation); + }, + + /** + * center image in container + **/ + center: function() + { + this.setCoords(-Math.round((this.img_object.display_width() - this.options.width)/2), + -Math.round((this.img_object.display_height() - this.options.height)/2)); + }, + + /** + * move a point in container to the center of display area + * @param x a point in container + * @param y a point in container + **/ + moveTo: function(x, y) + { + var dx = x-Math.round(this.options.width/2); + var dy = y-Math.round(this.options.height/2); + + var new_x = this.img_object.x() - dx; + var new_y = this.img_object.y() - dy; + + this.setCoords(new_x, new_y); + }, + + /** + * Get container offset object. + */ + getContainerOffset: function() { + return jQuery.extend({}, this.container.offset()); + }, + + /** + * set coordinates of upper left corner of image object + **/ + setCoords: function(x,y) + { + //do nothing while image is being loaded + if(!this.img_object.loaded()) { return; } + + var coords = this._correctCoords(x,y); + this.img_object.x(coords.x); + this.img_object.y(coords.y); + }, + + _correctCoords: function( x, y ) + { + x = parseInt(x, 10); + y = parseInt(y, 10); + + //check new coordinates to be correct (to be in rect) + if(y > 0){ + y = 0; + } + if(x > 0){ + x = 0; + } + if(y + this.img_object.display_height() < this.options.height){ + y = this.options.height - this.img_object.display_height(); + } + if(x + this.img_object.display_width() < this.options.width){ + x = this.options.width - this.img_object.display_width(); + } + if(this.img_object.display_width() <= this.options.width){ + x = -(this.img_object.display_width() - this.options.width)/2; + } + if(this.img_object.display_height() <= this.options.height){ + y = -(this.img_object.display_height() - this.options.height)/2; + } + + return { x: x, y:y }; + }, + + + /** + * convert coordinates on the container to the coordinates on the image (in original size) + * + * @return object with fields x,y according to coordinates or false + * if initial coords are not inside image + **/ + containerToImage : function (x,y) + { + var coords = { x : x - this.img_object.x(), + y : y - this.img_object.y() + }; + + coords = this.img_object.toOriginalCoords(coords); + + return { x : util.descaleValue(coords.x, this.current_zoom), + y : util.descaleValue(coords.y, this.current_zoom) + }; + }, + + /** + * convert coordinates on the image (in original size, and zero angle) to the coordinates on the container + * + * @return object with fields x,y according to coordinates + **/ + imageToContainer : function (x,y) + { + var coords = { + x : util.scaleValue(x, this.current_zoom), + y : util.scaleValue(y, this.current_zoom) + }; + + return this.img_object.toRealCoords(coords); + }, + + /** + * get mouse coordinates on the image + * @param e - object containing pageX and pageY fields, e.g. mouse event object + * + * @return object with fields x,y according to coordinates or false + * if initial coords are not inside image + **/ + _getMouseCoords : function(e) + { + var containerOffset = this.container.offset(); + coords = this.containerToImage(e.pageX - containerOffset.left, e.pageY - containerOffset.top); + + return coords; + }, + + /** + * set image scale to the new_zoom + * + * @param {number} new_zoom image scale in % + * @param {boolean} skip_animation + * @param {x: number, y: number} Coordinates of point the should not be moved on zoom. The default is the center of image. + **/ + set_zoom: function(new_zoom, skip_animation, zoom_center) + { + if (this._trigger('onZoom', 0, new_zoom) == false) { + return; + } + + //do nothing while image is being loaded + if(!this.img_object.loaded()) { return; } + + zoom_center = zoom_center || { + x: Math.round(this.options.width/2), + y: Math.round(this.options.height/2) + } + + if(new_zoom < this.options.zoom_min) + { + new_zoom = this.options.zoom_min; + } + else if(new_zoom > this.options.zoom_max) + { + new_zoom = this.options.zoom_max; + } + + /* we fake these values to make fit zoom properly work */ + if(this.current_zoom == "fit") + { + var old_x = zoom_center.x + Math.round(this.img_object.orig_width()/2); + var old_y = zoom_center.y + Math.round(this.img_object.orig_height()/2); + this.current_zoom = 100; + } + else { + var old_x = -this.img_object.x() + zoom_center.x; + var old_y = -this.img_object.y() + zoom_center.y + } + + var new_width = util.scaleValue(this.img_object.orig_width(), new_zoom); + var new_height = util.scaleValue(this.img_object.orig_height(), new_zoom); + var new_x = util.scaleValue( util.descaleValue(old_x, this.current_zoom), new_zoom); + var new_y = util.scaleValue( util.descaleValue(old_y, this.current_zoom), new_zoom); + + new_x = zoom_center.x - new_x; + new_y = zoom_center.y - new_y; + + new_width = Math.floor(new_width); + new_height = Math.floor(new_height); + new_x = Math.floor(new_x); + new_y = Math.floor(new_y); + + this.img_object.display_width(new_width); + this.img_object.display_height(new_height); + + var coords = this._correctCoords( new_x, new_y ), + self = this; + + this.img_object.setImageProps(new_width, new_height, coords.x, coords.y, + skip_animation, function() { + self._trigger('onAfterZoom', 0, new_zoom ); + }); + this.current_zoom = new_zoom; + + this.update_status(); + }, + + /** + * changes zoom scale by delta + * zoom is calculated by formula: zoom_base * zoom_delta^rate + * @param Integer delta number to add to the current multiplier rate number + * @param {x: number, y: number=} Coordinates of point the should not be moved on zoom. + **/ + zoom_by: function(delta, zoom_center) + { + var closest_rate = this.find_closest_zoom_rate(this.current_zoom); + + var next_rate = closest_rate + delta; + var next_zoom = this.options.zoom_base * Math.pow(this.options.zoom_delta, next_rate) + if(delta > 0 && next_zoom < this.current_zoom) + { + next_zoom *= this.options.zoom_delta; + } + + if(delta < 0 && next_zoom > this.current_zoom) + { + next_zoom /= this.options.zoom_delta; + } + + this.set_zoom(next_zoom, undefined, zoom_center); + }, + + /** + * Rotate image + * @param {num} deg Degrees amount to rotate. Positive values rotate image clockwise. + * Currently 0, 90, 180, 270 and -90, -180, -270 values are supported + * + * @param {boolean} abs If the flag is true if, the deg parameter will be considered as + * a absolute value and relative otherwise. + * @return {num|null} Method will return current image angle if called without any arguments. + **/ + angle: function(deg, abs) { + if (arguments.length === 0) { return this.img_object.angle(); } + + if (deg < -270 || deg > 270 || deg % 90 !== 0) { return; } + if (!abs) { deg += this.img_object.angle(); } + if (deg < 0) { deg += 360; } + if (deg >= 360) { deg -= 360; } + + if (deg === this.img_object.angle()) { return; } + + this.img_object.angle(deg); + //the rotate behavior is different in all editors. For now we just center the + //image. However, it will be better to try to keep the position. + this.center(); + this._trigger('angle', 0, { angle: this.img_object.angle() }); + }, + + /** + * finds closest multiplier rate for value + * basing on zoom_base and zoom_delta values from settings + * @param Number value zoom value to examine + **/ + find_closest_zoom_rate: function(value) + { + if(value == this.options.zoom_base) + { + return 0; + } + + function div(val1,val2) { return val1 / val2 }; + function mul(val1,val2) { return val1 * val2 }; + + var func = (value > this.options.zoom_base)?mul:div; + var sgn = (value > this.options.zoom_base)?1:-1; + + var mltplr = this.options.zoom_delta; + var rate = 1; + + while(Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate)) - value) > + Math.abs(func(this.options.zoom_base, Math.pow(mltplr,rate+1)) - value)) + { + rate++; + } + + return sgn * rate; + }, + + /* update scale info in the container */ + update_status: function() + { + if(!this.options.ui_disabled) + { + var percent = Math.round(100*this.img_object.display_height()/this.img_object.orig_height()); + if(percent) + { + this.zoom_object.html(percent + "%"); + } + } + }, + + /** + * Get some information about the image. + * Currently orig_(width|height), display_(width|height), angle, zoom and src params are supported. + * + * @param {string} parameter to check + * @param {boolean} withoutRotation if param is orig_width or orig_height and this flag is set to true, + * method will return original image width without considering rotation. + * + */ + info: function(param, withoutRotation) { + if (!param) { return; } + + switch (param) { + case 'orig_width': + case 'orig_height': + if (withoutRotation) { + return (this.img_object.angle() % 180 === 0 ? this.img_object[param]() : + param === 'orig_width' ? this.img_object.orig_height() : + this.img_object.orig_width()); + } else { + return this.img_object[param](); + } + case 'display_width': + case 'display_height': + case 'angle': + return this.img_object[param](); + case 'zoom': + return this.current_zoom; + case 'src': + return this.img_object.object().attr('src'); + case 'coords': + return { + x: this.img_object.x(), + y: this.img_object.y() + }; + } + }, + + /** + * callback for handling mousdown event to start dragging image + **/ + _mouseStart: function( e ) + { + $.ui.mouse.prototype._mouseStart.call(this, e); + if (this._trigger('onStartDrag', 0, this._getMouseCoords(e)) === false) { + return false; + } + + /* start drag event*/ + this.container.addClass("iviewer_drag_cursor"); + + //#10: fix movement quirks for ipad + this._dragInitialized = !(e.originalEvent.changedTouches && e.originalEvent.changedTouches.length==1); + + this.dx = e.pageX - this.img_object.x(); + this.dy = e.pageY - this.img_object.y(); + return true; + }, + + _mouseCapture: function( e ) { + return true; + }, + + /** + * Handle mouse move if needed. User can avoid using this callback, because + * he can get the same information through public methods. + * @param {jQuery.Event} e + */ + _handleMouseMove: function(e) { + this._trigger('onMouseMove', e, this._getMouseCoords(e)); + }, + + /** + * callback for handling mousemove event to drag image + **/ + _mouseDrag: function(e) + { + $.ui.mouse.prototype._mouseDrag.call(this, e); + + //#10: imitate mouseStart, because we can get here without it on iPad for some reason + if (!this._dragInitialized) { + this.dx = e.pageX - this.img_object.x(); + this.dy = e.pageY - this.img_object.y(); + this._dragInitialized = true; + } + + var ltop = e.pageY - this.dy; + var lleft = e.pageX - this.dx; + + this.setCoords(lleft, ltop); + this._trigger('onDrag', e, this._getMouseCoords(e)); + return false; + }, + + /** + * callback for handling stop drag + **/ + _mouseStop: function(e) + { + $.ui.mouse.prototype._mouseStop.call(this, e); + this.container.removeClass("iviewer_drag_cursor"); + this._trigger('onStopDrag', 0, this._getMouseCoords(e)); + }, + + _click: function(e) + { + this._trigger('onClick', 0, this._getMouseCoords(e)); + }, + + /** + * create zoom buttons info box + **/ + createui: function() + { + var me=this; + + $("
", { 'class': "iviewer_zoom_in iviewer_common iviewer_button"}) + .bind('mousedown touchstart',function(){me.zoom_by(1); return false;}) + .appendTo(this.container); + + $("
", { 'class': "iviewer_zoom_out iviewer_common iviewer_button"}) + .bind('mousedown touchstart',function(){me.zoom_by(- 1); return false;}) + .appendTo(this.container); + + $("
", { 'class': "iviewer_zoom_zero iviewer_common iviewer_button"}) + .bind('mousedown touchstart',function(){me.set_zoom(100); return false;}) + .appendTo(this.container); + + $("
", { 'class': "iviewer_zoom_fit iviewer_common iviewer_button"}) + .bind('mousedown touchstart',function(){me.fit(this); return false;}) + .appendTo(this.container); + + this.zoom_object = $("
").addClass("iviewer_zoom_status iviewer_common") + .appendTo(this.container); + + $("
", { 'class': "iviewer_rotate_left iviewer_common iviewer_button"}) + .bind('mousedown touchstart',function(){me.angle(-90); return false;}) + .appendTo(this.container); + + $("
", { 'class': "iviewer_rotate_right iviewer_common iviewer_button" }) + .bind('mousedown touchstart',function(){me.angle(90); return false;}) + .appendTo(this.container); + + this.update_status(); //initial status update + } + +} ); + +/** + * @class $.ui.iviewer.ImageObject Class represents image and provides public api without + * extending image prototype. + * @constructor + * @param {boolean} do_anim Do we want to animate image on dimension changes? + */ +$.ui.iviewer.ImageObject = function(do_anim) { + this._img = $("") + //this is needed, because chromium sets them auto otherwise + .css({ position: "absolute", top :"0px", left: "0px"}); + + this._loaded = false; + this._swapDimensions = false; + this._do_anim = do_anim || false; + this.x(0, true); + this.y(0, true); + this.angle(0); +}; + + +/** @lends $.ui.iviewer.ImageObject.prototype */ +(function() { + /** + * Restore initial object state. + * + * @param {number} w Image width. + * @param {number} h Image height. + */ + this._reset = function(w, h) { + this._angle = 0; + this._swapDimensions = false; + this.x(0); + this.y(0); + + this.orig_width(w); + this.orig_height(h); + this.display_width(w); + this.display_height(h); + }; + + /** + * Check if image is loaded. + * + * @return {boolean} + */ + this.loaded = function() { return this._loaded; }; + + /** + * Load image. + * + * @param {string} src Image url. + * @param {Function=} loaded Function will be called on image load. + */ + this.load = function(src, loaded, error) { + var self = this; + + loaded = loaded || jQuery.noop; + this._loaded = false; + + //If we assign new image url to the this._img IE9 fires onload event and image width and + //height are set to zero. So, we create another image object and load image through it. + var img = new Image(); + img.onload = function() { + self._loaded = true; + self._reset(this.width, this.height); + + self._img + .removeAttr("width") + .removeAttr("height") + .removeAttr("style") + //max-width is reset, because plugin breaks in the twitter bootstrap otherwise + .css({ position: "absolute", top :"0px", left: "0px", maxWidth: "none"}) + + self._img[0].src = src; + loaded(); + }; + + img.onerror = error; + + //we need this because sometimes internet explorer 8 fires onload event + //right after assignment (synchronously) + setTimeout(function() { + img.src = src; + }, 0); + + this.angle(0); + }; + + this._dimension = function(prefix, name) { + var horiz = '_' + prefix + '_' + name, + vert = '_' + prefix + '_' + (name === 'height' ? 'width' : 'height'); + return setter(function(val) { + this[this._swapDimensions ? horiz: vert] = val; + }, + function() { + return this[this._swapDimensions ? horiz: vert]; + }); + }; + + /** + * Getters and setter for common image dimensions. + * display_ means real image tag dimensions + * orig_ means physical image dimensions. + * Note, that dimensions are swapped if image is rotated. It necessary, + * because as little as possible code should know about rotation. + */ + this.display_width = this._dimension('display', 'width'), + this.display_height = this._dimension('display', 'height'), + this.display_diff = function() { return Math.floor( this.display_width() - this.display_height() ) }; + this.orig_width = this._dimension('orig', 'width'), + this.orig_height = this._dimension('orig', 'height'), + + /** + * Setter for X coordinate. If image is rotated we need to additionaly shift an + * image to map image coordinate to the visual position. + * + * @param {number} val Coordinate value. + * @param {boolean} skipCss If true, we only set the value and do not touch the dom. + */ + this.x = setter(function(val, skipCss) { + this._x = val; + if (!skipCss) { + this._finishAnimation(); + this._img.css("left",this._x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px"); + } + }, + function() { + return this._x; + }); + + /** + * Setter for Y coordinate. If image is rotated we need to additionaly shift an + * image to map image coordinate to the visual position. + * + * @param {number} val Coordinate value. + * @param {boolean} skipCss If true, we only set the value and do not touch the dom. + */ + this.y = setter(function(val, skipCss) { + this._y = val; + if (!skipCss) { + this._finishAnimation(); + this._img.css("top",this._y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px"); + } + }, + function() { + return this._y; + }); + + /** + * Perform image rotation. + * + * @param {number} deg Absolute image angle. The method will work with values 0, 90, 180, 270 degrees. + */ + this.angle = setter(function(deg) { + var prevSwap = this._swapDimensions; + + this._angle = deg; + this._swapDimensions = deg % 180 !== 0; + + if (prevSwap !== this._swapDimensions) { + var verticalMod = this._swapDimensions ? -1 : 1; + this.x(this.x() - verticalMod * this.display_diff() / 2, true); + this.y(this.y() + verticalMod * this.display_diff() / 2, true); + }; + + var cssVal = 'rotate(' + deg + 'deg)', + img = this._img; + + jQuery.each(['', '-webkit-', '-moz-', '-o-', '-ms-'], function(i, prefix) { + img.css(prefix + 'transform', cssVal); + }); + + if (useIeTransforms) { + jQuery.each(['-ms-', ''], function(i, prefix) { + img.css(prefix + 'filter', ieTransforms[deg].filter); + }); + + img.css({ + marginLeft: ieTransforms[deg].marginLeft * this.display_diff() / 2, + marginTop: ieTransforms[deg].marginTop * this.display_diff() / 2 + }); + } + }, + function() { return this._angle; }); + + /** + * Map point in the container coordinates to the point in image coordinates. + * You will get coordinates of point on image with respect to rotation, + * but will be set as if image was not rotated. + * So, if image was rotated 90 degrees, it's (0,0) point will be on the + * top right corner. + * + * @param {{x: number, y: number}} point Point in container coordinates. + * @return {{x: number, y: number}} + */ + this.toOriginalCoords = function(point) { + switch (this.angle()) { + case 0: return { x: point.x, y: point.y } + case 90: return { x: point.y, y: this.display_width() - point.x } + case 180: return { x: this.display_width() - point.x, y: this.display_height() - point.y } + case 270: return { x: this.display_height() - point.y, y: point.x } + } + }; + + /** + * Map point in the image coordinates to the point in container coordinates. + * You will get coordinates of point on container with respect to rotation. + * Note, if image was rotated 90 degrees, it's (0,0) point will be on the + * top right corner. + * + * @param {{x: number, y: number}} point Point in container coordinates. + * @return {{x: number, y: number}} + */ + this.toRealCoords = function(point) { + switch (this.angle()) { + case 0: return { x: this.x() + point.x, y: this.y() + point.y } + case 90: return { x: this.x() + this.display_width() - point.y, y: this.y() + point.x} + case 180: return { x: this.x() + this.display_width() - point.x, y: this.y() + this.display_height() - point.y} + case 270: return { x: this.x() + point.y, y: this.y() + this.display_height() - point.x} + } + }; + + /** + * @return {jQuery} Return image node. this is needed to add event handlers. + */ + this.object = setter(jQuery.noop, + function() { return this._img; }); + + /** + * Change image properties. + * + * @param {number} disp_w Display width; + * @param {number} disp_h Display height; + * @param {number} x + * @param {number} y + * @param {boolean} skip_animation If true, the animation will be skiped despite the + * value set in constructor. + * @param {Function=} complete Call back will be fired when zoom will be complete. + */ + this.setImageProps = function(disp_w, disp_h, x, y, skip_animation, complete) { + complete = complete || jQuery.noop; + + this.display_width(disp_w); + this.display_height(disp_h); + this.x(x, true); + this.y(y, true); + + var w = this._swapDimensions ? disp_h : disp_w; + var h = this._swapDimensions ? disp_w : disp_h; + + var params = { + width: w, + height: h, + top: y - (this._swapDimensions ? this.display_diff() / 2 : 0) + "px", + left: x + (this._swapDimensions ? this.display_diff() / 2 : 0) + "px" + }; + + if (useIeTransforms) { + jQuery.extend(params, { + marginLeft: ieTransforms[this.angle()].marginLeft * this.display_diff() / 2, + marginTop: ieTransforms[this.angle()].marginTop * this.display_diff() / 2 + }); + } + + var swapDims = this._swapDimensions, + img = this._img; + + //here we come: another IE oddness. If image is rotated 90 degrees with a filter, than + //width and height getters return real width and height of rotated image. The bad news + //is that to set height you need to set a width and vice versa. Fuck IE. + //So, in this case we have to animate width and height manually. + if(useIeTransforms && swapDims) { + var ieh = this._img.width(), + iew = this._img.height(), + iedh = params.height - ieh; + iedw = params.width - iew; + + delete params.width; + delete params.height; + } + + if (this._do_anim && !skip_animation) { + this._img.stop(true) + .animate(params, { + duration: 200, + complete: complete, + step: function(now, fx) { + if(useIeTransforms && swapDims && (fx.prop === 'top')) { + var percent = (now - fx.start) / (fx.end - fx.start); + + img.height(ieh + iedh * percent); + img.width(iew + iedw * percent); + img.css('top', now); + } + } + }); + } else { + this._img.css(params); + setTimeout(complete, 0); //both if branches should behave equally. + } + }; + + //if we set image coordinates we need to be sure that no animation is active atm + this._finishAnimation = function() { + this._img.stop(true, true); + } + +}).apply($.ui.iviewer.ImageObject.prototype); + + + +var util = { + scaleValue: function(value, toZoom) + { + return value * toZoom / 100; + }, + + descaleValue: function(value, fromZoom) + { + return value * 100 / fromZoom; + } +}; + + } )( jQuery, undefined ); diff --git a/docs/api/js/jquery.iviewer.min.js b/docs/api/js/jquery.iviewer.min.js new file mode 100644 index 0000000..e118e3c --- /dev/null +++ b/docs/api/js/jquery.iviewer.min.js @@ -0,0 +1,47 @@ +/* + * iviewer Widget for jQuery UI + * https://github.com/can3p/iviewer + * + * Copyright (c) 2009 - 2012 Dmitry Petrov + * Dual licensed under the MIT and GPL licenses. + * - http://www.opensource.org/licenses/mit-license.php + * - http://www.gnu.org/copyleft/gpl.html + * + * Author: Dmitry Petrov + * Version: 0.7.7 + */ +(function($,undefined){var mouseEvents={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup"},gesturesSupport="ongesturestart"in document.createElement("div");function makeMouseEvent(event){var touch=event.originalEvent.changedTouches[0];return $.extend(event,{type:mouseEvents[event.type],which:1,pageX:touch.pageX,pageY:touch.pageY,screenX:touch.screenX,screenY:touch.screenY,clientX:touch.clientX,clientY:touch.clientY,isTouchEvent:true})}var mouseProto=$.ui.mouse.prototype,_mouseInit=$.ui.mouse.prototype._mouseInit; +mouseProto._mouseInit=function(){var self=this;self._touchActive=false;this.element.bind("touchstart."+this.widgetName,function(event){if(gesturesSupport&&event.originalEvent.touches.length>1)return;self._touchActive=true;return self._mouseDown(makeMouseEvent(event))});var self=this;this._mouseMoveDelegate=function(event){if(gesturesSupport&&event.originalEvent.touches&&event.originalEvent.touches.length>1)return;if(self._touchActive)return self._mouseMove(makeMouseEvent(event))};this._mouseUpDelegate= +function(event){if(self._touchActive){self._touchActive=false;return self._mouseUp(makeMouseEvent(event))}};$(document).bind("touchmove."+this.widgetName,this._mouseMoveDelegate).bind("touchend."+this.widgetName,this._mouseUpDelegate);_mouseInit.apply(this)};var setter=function(setter,getter){return function(val){if(arguments.length===0)return getter.apply(this);else setter.apply(this,arguments)}};var ieTransforms={"0":{marginLeft:0,marginTop:0,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=1, M12=0, M21=0, M22=1, SizingMethod="auto expand")'}, +90:{marginLeft:-1,marginTop:1,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=-1, M21=1, M22=0, SizingMethod="auto expand")'},180:{marginLeft:0,marginTop:0,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=-1, M12=0, M21=0, M22=-1, SizingMethod="auto expand")'},270:{marginLeft:-1,marginTop:1,filter:'progid:DXImageTransform.Microsoft.Matrix(M11=0, M12=1, M21=-1, M22=0, SizingMethod="auto expand")'}},useIeTransforms=function(){var el=document.createElement("div");el.style.cssText=["-ms-", +"",""].join("filter:blur(2px); ");return!!el.style.cssText&&document.documentMode<9}();$.widget("ui.iviewer",$.ui.mouse,{widgetEventPrefix:"iviewer",options:{zoom:"fit",zoom_base:100,zoom_max:800,zoom_min:25,zoom_delta:1.4,zoom_animation:true,ui_disabled:false,mousewheel:true,update_on_resize:true,onZoom:jQuery.noop,onAfterZoom:jQuery.noop,onStartDrag:jQuery.noop,onDrag:jQuery.noop,onStopDrag:jQuery.noop,onMouseMove:jQuery.noop,onClick:jQuery.noop,onStartLoad:null,onFinishLoad:null,onErrorLoad:null}, +_create:function(){var me=this;this.dx=0;this.dy=0;this.img_object={};this.zoom_object={};this._angle=0;this.current_zoom=this.options.zoom;if(this.options.src===null)return;this.container=this.element;this._updateContainerInfo();this.container.css("overflow","hidden");if(this.options.update_on_resize==true)$(window).resize(function(){me.update()});this.img_object=new $.ui.iviewer.ImageObject(this.options.zoom_animation);if(this.options.mousewheel){this.container.bind("mousewheel.iviewer",function(ev, +delta){var zoom=delta>0?1:-1,container_offset=me.container.offset(),mouse_pos={x:ev.pageX-container_offset.left,y:ev.pageY-container_offset.top};me.zoom_by(zoom,mouse_pos);return false});if(gesturesSupport){var gestureThrottle=+new Date;var originalScale,originalCenter;this.img_object.object().bind("touchstart",function(ev){originalScale=me.current_zoom;var touches=ev.originalEvent.touches,container_offset;if(touches.length==2){container_offset=me.container.offset();originalCenter={x:(touches[0].pageX+ +touches[1].pageX)/2-container_offset.left,y:(touches[0].pageY+touches[1].pageY)/2-container_offset.top}}else originalCenter=null}).bind("gesturechange",function(ev){var d=+new Date;if(d-gestureThrottle<50)return;gestureThrottle=d;var zoom=originalScale*ev.originalEvent.scale;me.set_zoom(zoom,originalCenter);ev.preventDefault()}).bind("gestureend",function(ev){originalCenter=null})}}this.img_object.object().click(function(e){return me._click(e)}).prependTo(this.container);this.container.bind("mousemove", +function(ev){me._handleMouseMove(ev)});this.loadImage(this.options.src);if(!this.options.ui_disabled)this.createui();this._mouseInit()},destroy:function(){$.Widget.prototype.destroy.call(this);this._mouseDestroy();this.img_object.object().remove();this.container.off(".iviewer");this.container.css("overflow","")},_updateContainerInfo:function(){this.options.height=this.container.height();this.options.width=this.container.width()},update:function(){this._updateContainerInfo();this.setCoords(this.img_object.x(), +this.img_object.y())},loadImage:function(src){this.current_zoom=this.options.zoom;var me=this;this._trigger("onStartLoad",0,src);this.container.addClass("iviewer_loading");this.img_object.load(src,function(){me._imageLoaded(src)},function(){me._trigger("onErrorLoad",0,src)})},_imageLoaded:function(src){this.container.removeClass("iviewer_loading");this.container.addClass("iviewer_cursor");if(this.options.zoom=="fit")this.fit(true);else this.set_zoom(this.options.zoom,true);this._trigger("onFinishLoad", +0,src)},fit:function(skip_animation){var aspect_ratio=this.img_object.orig_width()/this.img_object.orig_height();var window_ratio=this.options.width/this.options.height;var choose_left=aspect_ratio>window_ratio;var new_zoom=0;if(choose_left)new_zoom=this.options.width/this.img_object.orig_width()*100;else new_zoom=this.options.height/this.img_object.orig_height()*100;this.set_zoom(new_zoom,skip_animation)},center:function(){this.setCoords(-Math.round((this.img_object.display_width()-this.options.width)/ +2),-Math.round((this.img_object.display_height()-this.options.height)/2))},moveTo:function(x,y){var dx=x-Math.round(this.options.width/2);var dy=y-Math.round(this.options.height/2);var new_x=this.img_object.x()-dx;var new_y=this.img_object.y()-dy;this.setCoords(new_x,new_y)},getContainerOffset:function(){return jQuery.extend({},this.container.offset())},setCoords:function(x,y){if(!this.img_object.loaded())return;var coords=this._correctCoords(x,y);this.img_object.x(coords.x);this.img_object.y(coords.y)}, +_correctCoords:function(x,y){x=parseInt(x,10);y=parseInt(y,10);if(y>0)y=0;if(x>0)x=0;if(y+this.img_object.display_height()this.options.zoom_max)new_zoom=this.options.zoom_max;if(this.current_zoom=="fit"){var old_x= +zoom_center.x+Math.round(this.img_object.orig_width()/2);var old_y=zoom_center.y+Math.round(this.img_object.orig_height()/2);this.current_zoom=100}else{var old_x=-this.img_object.x()+zoom_center.x;var old_y=-this.img_object.y()+zoom_center.y}var new_width=util.scaleValue(this.img_object.orig_width(),new_zoom);var new_height=util.scaleValue(this.img_object.orig_height(),new_zoom);var new_x=util.scaleValue(util.descaleValue(old_x,this.current_zoom),new_zoom);var new_y=util.scaleValue(util.descaleValue(old_y, +this.current_zoom),new_zoom);new_x=zoom_center.x-new_x;new_y=zoom_center.y-new_y;new_width=Math.floor(new_width);new_height=Math.floor(new_height);new_x=Math.floor(new_x);new_y=Math.floor(new_y);this.img_object.display_width(new_width);this.img_object.display_height(new_height);var coords=this._correctCoords(new_x,new_y),self=this;this.img_object.setImageProps(new_width,new_height,coords.x,coords.y,skip_animation,function(){self._trigger("onAfterZoom",0,new_zoom)});this.current_zoom=new_zoom;this.update_status()}, +zoom_by:function(delta,zoom_center){var closest_rate=this.find_closest_zoom_rate(this.current_zoom);var next_rate=closest_rate+delta;var next_zoom=this.options.zoom_base*Math.pow(this.options.zoom_delta,next_rate);if(delta>0&&next_zoomthis.current_zoom)next_zoom/=this.options.zoom_delta;this.set_zoom(next_zoom,undefined,zoom_center)},angle:function(deg,abs){if(arguments.length===0)return this.img_object.angle();if(deg<-270|| +deg>270||deg%90!==0)return;if(!abs)deg+=this.img_object.angle();if(deg<0)deg+=360;if(deg>=360)deg-=360;if(deg===this.img_object.angle())return;this.img_object.angle(deg);this.center();this._trigger("angle",0,{angle:this.img_object.angle()})},find_closest_zoom_rate:function(value){if(value==this.options.zoom_base)return 0;function div(val1,val2){return val1/val2}function mul(val1,val2){return val1*val2}var func=value>this.options.zoom_base?mul:div;var sgn=value>this.options.zoom_base?1:-1;var mltplr= +this.options.zoom_delta;var rate=1;while(Math.abs(func(this.options.zoom_base,Math.pow(mltplr,rate))-value)>Math.abs(func(this.options.zoom_base,Math.pow(mltplr,rate+1))-value))rate++;return sgn*rate},update_status:function(){if(!this.options.ui_disabled){var percent=Math.round(100*this.img_object.display_height()/this.img_object.orig_height());if(percent)this.zoom_object.html(percent+"%")}},info:function(param,withoutRotation){if(!param)return;switch(param){case "orig_width":case "orig_height":if(withoutRotation)return this.img_object.angle()% +180===0?this.img_object[param]():param==="orig_width"?this.img_object.orig_height():this.img_object.orig_width();else return this.img_object[param]();case "display_width":case "display_height":case "angle":return this.img_object[param]();case "zoom":return this.current_zoom;case "src":return this.img_object.object().attr("src");case "coords":return{x:this.img_object.x(),y:this.img_object.y()}}},_mouseStart:function(e){$.ui.mouse.prototype._mouseStart.call(this,e);if(this._trigger("onStartDrag",0, +this._getMouseCoords(e))===false)return false;this.container.addClass("iviewer_drag_cursor");this._dragInitialized=!(e.originalEvent.changedTouches&&e.originalEvent.changedTouches.length==1);this.dx=e.pageX-this.img_object.x();this.dy=e.pageY-this.img_object.y();return true},_mouseCapture:function(e){return true},_handleMouseMove:function(e){this._trigger("onMouseMove",e,this._getMouseCoords(e))},_mouseDrag:function(e){$.ui.mouse.prototype._mouseDrag.call(this,e);if(!this._dragInitialized){this.dx= +e.pageX-this.img_object.x();this.dy=e.pageY-this.img_object.y();this._dragInitialized=true}var ltop=e.pageY-this.dy;var lleft=e.pageX-this.dx;this.setCoords(lleft,ltop);this._trigger("onDrag",e,this._getMouseCoords(e));return false},_mouseStop:function(e){$.ui.mouse.prototype._mouseStop.call(this,e);this.container.removeClass("iviewer_drag_cursor");this._trigger("onStopDrag",0,this._getMouseCoords(e))},_click:function(e){this._trigger("onClick",0,this._getMouseCoords(e))},createui:function(){var me= +this;$("
",{"class":"iviewer_zoom_in iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.zoom_by(1);return false}).appendTo(this.container);$("
",{"class":"iviewer_zoom_out iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.zoom_by(-1);return false}).appendTo(this.container);$("
",{"class":"iviewer_zoom_zero iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.set_zoom(100);return false}).appendTo(this.container);$("
", +{"class":"iviewer_zoom_fit iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.fit(this);return false}).appendTo(this.container);this.zoom_object=$("
").addClass("iviewer_zoom_status iviewer_common").appendTo(this.container);$("
",{"class":"iviewer_rotate_left iviewer_common iviewer_button"}).bind("mousedown touchstart",function(){me.angle(-90);return false}).appendTo(this.container);$("
",{"class":"iviewer_rotate_right iviewer_common iviewer_button"}).bind("mousedown touchstart", +function(){me.angle(90);return false}).appendTo(this.container);this.update_status()}});$.ui.iviewer.ImageObject=function(do_anim){this._img=$("").css({position:"absolute",top:"0px",left:"0px"});this._loaded=false;this._swapDimensions=false;this._do_anim=do_anim||false;this.x(0,true);this.y(0,true);this.angle(0)};(function(){this._reset=function(w,h){this._angle=0;this._swapDimensions=false;this.x(0);this.y(0);this.orig_width(w);this.orig_height(h);this.display_width(w);this.display_height(h)}; +this.loaded=function(){return this._loaded};this.load=function(src,loaded,error){var self=this;loaded=loaded||jQuery.noop;this._loaded=false;var img=new Image;img.onload=function(){self._loaded=true;self._reset(this.width,this.height);self._img.removeAttr("width").removeAttr("height").removeAttr("style").css({position:"absolute",top:"0px",left:"0px",maxWidth:"none"});self._img[0].src=src;loaded()};img.onerror=error;setTimeout(function(){img.src=src},0);this.angle(0)};this._dimension=function(prefix, +name){var horiz="_"+prefix+"_"+name,vert="_"+prefix+"_"+(name==="height"?"width":"height");return setter(function(val){this[this._swapDimensions?horiz:vert]=val},function(){return this[this._swapDimensions?horiz:vert]})};this.display_width=this._dimension("display","width"),this.display_height=this._dimension("display","height"),this.display_diff=function(){return Math.floor(this.display_width()-this.display_height())};this.orig_width=this._dimension("orig","width"),this.orig_height=this._dimension("orig", +"height"),this.x=setter(function(val,skipCss){this._x=val;if(!skipCss){this._finishAnimation();this._img.css("left",this._x+(this._swapDimensions?this.display_diff()/2:0)+"px")}},function(){return this._x});this.y=setter(function(val,skipCss){this._y=val;if(!skipCss){this._finishAnimation();this._img.css("top",this._y-(this._swapDimensions?this.display_diff()/2:0)+"px")}},function(){return this._y});this.angle=setter(function(deg){var prevSwap=this._swapDimensions;this._angle=deg;this._swapDimensions= +deg%180!==0;if(prevSwap!==this._swapDimensions){var verticalMod=this._swapDimensions?-1:1;this.x(this.x()-verticalMod*this.display_diff()/2,true);this.y(this.y()+verticalMod*this.display_diff()/2,true)}var cssVal="rotate("+deg+"deg)",img=this._img;jQuery.each(["","-webkit-","-moz-","-o-","-ms-"],function(i,prefix){img.css(prefix+"transform",cssVal)});if(useIeTransforms){jQuery.each(["-ms-",""],function(i,prefix){img.css(prefix+"filter",ieTransforms[deg].filter)});img.css({marginLeft:ieTransforms[deg].marginLeft* +this.display_diff()/2,marginTop:ieTransforms[deg].marginTop*this.display_diff()/2})}},function(){return this._angle});this.toOriginalCoords=function(point){switch(this.angle()){case 0:return{x:point.x,y:point.y};case 90:return{x:point.y,y:this.display_width()-point.x};case 180:return{x:this.display_width()-point.x,y:this.display_height()-point.y};case 270:return{x:this.display_height()-point.y,y:point.x}}};this.toRealCoords=function(point){switch(this.angle()){case 0:return{x:this.x()+point.x,y:this.y()+ +point.y};case 90:return{x:this.x()+this.display_width()-point.y,y:this.y()+point.x};case 180:return{x:this.x()+this.display_width()-point.x,y:this.y()+this.display_height()-point.y};case 270:return{x:this.x()+point.y,y:this.y()+this.display_height()-point.x}}};this.object=setter(jQuery.noop,function(){return this._img});this.setImageProps=function(disp_w,disp_h,x,y,skip_animation,complete){complete=complete||jQuery.noop;this.display_width(disp_w);this.display_height(disp_h);this.x(x,true);this.y(y, +true);var w=this._swapDimensions?disp_h:disp_w;var h=this._swapDimensions?disp_w:disp_h;var params={width:w,height:h,top:y-(this._swapDimensions?this.display_diff()/2:0)+"px",left:x+(this._swapDimensions?this.display_diff()/2:0)+"px"};if(useIeTransforms)jQuery.extend(params,{marginLeft:ieTransforms[this.angle()].marginLeft*this.display_diff()/2,marginTop:ieTransforms[this.angle()].marginTop*this.display_diff()/2});var swapDims=this._swapDimensions,img=this._img;if(useIeTransforms&&swapDims){var ieh= +this._img.width(),iew=this._img.height(),iedh=params.height-ieh;iedw=params.width-iew;delete params.width;delete params.height}if(this._do_anim&&!skip_animation)this._img.stop(true).animate(params,{duration:200,complete:complete,step:function(now,fx){if(useIeTransforms&&swapDims&&fx.prop==="top"){var percent=(now-fx.start)/(fx.end-fx.start);img.height(ieh+iedh*percent);img.width(iew+iedw*percent);img.css("top",now)}}});else{this._img.css(params);setTimeout(complete,0)}};this._finishAnimation=function(){this._img.stop(true, +true)}}).apply($.ui.iviewer.ImageObject.prototype);var util={scaleValue:function(value,toZoom){return value*toZoom/100},descaleValue:function(value,fromZoom){return value*100/fromZoom}}})(jQuery,undefined); diff --git a/docs/api/js/jquery.smooth-scroll.js b/docs/api/js/jquery.smooth-scroll.js new file mode 100644 index 0000000..ce1e19b --- /dev/null +++ b/docs/api/js/jquery.smooth-scroll.js @@ -0,0 +1,32 @@ +$(document).ready(function() { + function filterPath(string) { + return string + .replace(/^\//,'') + .replace(/(index|default).[a-zA-Z]{3,4}$/,'') + .replace(/\/$/,''); + } + var locationPath = filterPath(location.pathname); + + $('a[href*=#]').each(function() { + var thisPath = filterPath(this.pathname) || locationPath; + if ( locationPath == thisPath + && (location.hostname == this.hostname || !this.hostname) + && this.hash.replace(/#/,'') ) { + var $target = $(this.hash), target = this.hash; + if (target) { + $(this).click(function(event) { + if (!$(this.hash).offset()) { + return; + } + + event.preventDefault(); + position = $(this.hash).offset().top; + + $('html,body').animate({scrollTop: position}, 400, function() { + location.hash = target; + }); + }); + } + } + }); +}); diff --git a/docs/api/js/prism.min.js b/docs/api/js/prism.min.js new file mode 100644 index 0000000..c69705d --- /dev/null +++ b/docs/api/js/prism.min.js @@ -0,0 +1,16 @@ +/** + * Prism: Lightweight, robust, elegant syntax highlighting + * MIT license http://www.opensource.org/licenses/mit-license.php/ + * @author Lea Verou http://lea.verou.me + */(function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=self.Prism={util:{type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var r={};for(var i in e)e.hasOwnProperty(i)&&(r[i]=t.util.clone(e[i]));return r;case"Array":return e.slice()}return e}},languages:{extend:function(e,n){var r=t.util.clone(t.languages[e]);for(var i in n)r[i]=n[i];return r},insertBefore:function(e,n,r,i){i=i||t.languages;var s=i[e],o={};for(var u in s)if(s.hasOwnProperty(u)){if(u==n)for(var a in r)r.hasOwnProperty(a)&&(o[a]=r[a]);o[u]=s[u]}return i[e]=o},DFS:function(e,n){for(var r in e){n.call(e,r,e[r]);t.util.type(e)==="Object"&&t.languages.DFS(e[r],n)}}},highlightAll:function(e,n){var r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');for(var i=0,s;s=r[i++];)t.highlightElement(s,e===!0,n)},highlightElement:function(r,i,s){var o,u,a=r;while(a&&!e.test(a.className))a=a.parentNode;if(a){o=(a.className.match(e)||[,""])[1];u=t.languages[o]}if(!u)return;r.className=r.className.replace(e,"").replace(/\s+/g," ")+" language-"+o;a=r.parentNode;/pre/i.test(a.nodeName)&&(a.className=a.className.replace(e,"").replace(/\s+/g," ")+" language-"+o);var f=r.textContent;if(!f)return;f=f.replace(/&/g,"&").replace(/e.length)break e;if(p instanceof i)continue;a.lastIndex=0;var d=a.exec(p);if(d){l&&(c=d[1].length);var v=d.index-1+c,d=d[0].slice(c),m=d.length,g=v+m,y=p.slice(0,v+1),b=p.slice(g+1),w=[h,1];y&&w.push(y);var E=new i(u,f?t.tokenize(d,f):d);w.push(E);b&&w.push(b);Array.prototype.splice.apply(s,w)}}}return s},hooks:{all:{},add:function(e,n){var r=t.hooks.all;r[e]=r[e]||[];r[e].push(n)},run:function(e,n){var r=t.hooks.all[e];if(!r||!r.length)return;for(var i=0,s;s=r[i++];)s(n)}}},n=t.Token=function(e,t){this.type=e;this.content=t};n.stringify=function(e,r,i){if(typeof e=="string")return e;if(Object.prototype.toString.call(e)=="[object Array]")return e.map(function(t){return n.stringify(t,r,e)}).join("");var s={type:e.type,content:n.stringify(e.content,r,i),tag:"span",classes:["token",e.type],attributes:{},language:r,parent:i};s.type=="comment"&&(s.attributes.spellcheck="true");t.hooks.run("wrap",s);var o="";for(var u in s.attributes)o+=u+'="'+(s.attributes[u]||"")+'"';return"<"+s.tag+' class="'+s.classes.join(" ")+'" '+o+">"+s.content+""};if(!self.document){self.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,i=n.code;self.postMessage(JSON.stringify(t.tokenize(i,t.languages[r])));self.close()},!1);return}var r=document.getElementsByTagName("script");r=r[r.length-1];if(r){t.filename=r.src;document.addEventListener&&!r.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)}})();; +Prism.languages.markup={comment:/<!--[\w\W]*?-->/g,prolog:/<\?.+?\?>/,doctype:/<!DOCTYPE.+?>/,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|\w+))?\s*)*\/?>/gi,inside:{tag:{pattern:/^<\/?[\w:-]+/i,inside:{punctuation:/^<\/?/,namespace:/^[\w-]+?:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,inside:{punctuation:/=|>|"/g}},punctuation:/\/?>/g,"attr-name":{pattern:/[\w:-]+/g,inside:{namespace:/^[\w-]+?:/}}}},entity:/&#?[\da-z]{1,8};/gi};Prism.hooks.add("wrap",function(e){e.type==="entity"&&(e.attributes.title=e.content.replace(/&/,"&"))});; +Prism.languages.css={comment:/\/\*[\w\W]*?\*\//g,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*{))/gi,inside:{punctuation:/[;:]/g}},url:/url\((["']?).*?\1\)/gi,selector:/[^\{\}\s][^\{\};]*(?=\s*\{)/g,property:/(\b|\B)[\w-]+(?=\s*:)/ig,string:/("|')(\\?.)*?\1/g,important:/\B!important\b/gi,ignore:/&(lt|gt|amp);/gi,punctuation:/[\{\};:]/g};Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig,inside:{tag:{pattern:/(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.css}}});; +Prism.languages.css.selector={pattern:/[^\{\}\s][^\{\}]*(?=\s*\{)/g,inside:{"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/g,"pseudo-class":/:[-\w]+(?:\(.*\))?/g,"class":/\.[-:\.\w]+/g,id:/#[-:\.\w]+/g}};Prism.languages.insertBefore("css","ignore",{hexcode:/#[\da-f]{3,6}/gi,entity:/\\[\da-f]{1,8}/gi,number:/[\d%\.]+/g,"function":/(attr|calc|cross-fade|cycle|element|hsla?|image|lang|linear-gradient|matrix3d|matrix|perspective|radial-gradient|repeating-linear-gradient|repeating-radial-gradient|rgba?|rotatex|rotatey|rotatez|rotate3d|rotate|scalex|scaley|scalez|scale3d|scale|skewx|skewy|skew|steps|translatex|translatey|translatez|translate3d|translate|url|var)/ig});; +Prism.languages.clike={comment:{pattern:/(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,lookbehind:!0},string:/("|')(\\?.)*?\1/g,"class-name":{pattern:/((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|catch|finally|null|break|continue)\b/g,"boolean":/\b(true|false)\b/g,"function":{pattern:/[a-z0-9_]+\(/ig,inside:{punctuation:/\(/}}, number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,operator:/[-+]{1,2}|!|<=?|>=?|={1,3}|(&){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,ignore:/&(lt|gt|amp);/gi,punctuation:/[{}[\];(),.:]/g};; +Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(var|let|if|else|while|do|for|return|in|instanceof|function|new|with|typeof|try|catch|finally|null|break|continue)\b/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?|NaN|-?Infinity)\b/g});Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/g,lookbehind:!0}});Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig,inside:{tag:{pattern:/(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/ig,inside:Prism.languages.markup.tag.inside},rest:Prism.languages.javascript}}});; +Prism.languages.php=Prism.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|extends|private|protected|parent|static|throw|null|echo|print|trait|namespace|use|final|yield|goto|instanceof|finally|try|catch)\b/ig, constant:/\b[A-Z0-9_]{2,}\b/g});Prism.languages.insertBefore("php","keyword",{delimiter:/(\?>|<\?php|<\?)/ig,variable:/(\$\w+)\b/ig,"package":{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/g,lookbehind:!0,inside:{punctuation:/\\/}}});Prism.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/g,lookbehind:!0}}); Prism.languages.markup&&(Prism.hooks.add("before-highlight",function(a){"php"===a.language&&(a.tokenStack=[],a.code=a.code.replace(/(?:<\?php|<\?|<\?php|<\?)[\w\W]*?(?:\?>|\?>)/ig,function(b){a.tokenStack.push(b);return"{{{PHP"+a.tokenStack.length+"}}}"}))}),Prism.hooks.add("after-highlight",function(a){if("php"===a.language){for(var b=0,c;c=a.tokenStack[b];b++)a.highlightedCode=a.highlightedCode.replace("{{{PHP"+(b+1)+"}}}",Prism.highlight(c,a.grammar,"php"));a.element.innerHTML=a.highlightedCode}}), Prism.hooks.add("wrap",function(a){"php"===a.language&&"markup"===a.type&&(a.content=a.content.replace(/(\{\{\{PHP[0-9]+\}\}\})/g,'$1'))}),Prism.languages.insertBefore("php","comment",{markup:{pattern:/(<|<)[^?]\/?(.*?)(>|>)/g,inside:Prism.languages.markup},php:/\{\{\{PHP[0-9]+\}\}\}/g}));; +Prism.languages.insertBefore("php","variable",{"this":/\$this/g,global:/\$_?(GLOBALS|SERVER|GET|POST|FILES|REQUEST|SESSION|ENV|COOKIE|HTTP_RAW_POST_DATA|argc|argv|php_errormsg|http_response_header)/g,scope:{pattern:/\b[\w\\]+::/g,inside:{keyword:/(static|self|parent)/,punctuation:/(::|\\)/}}});; +(function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function n(e,t,n){var r=t.replace(/\s+/g,"").split(","),i=+e.getAttribute("data-line-offset")||0,s=parseFloat(getComputedStyle(e).lineHeight);for(var o=0,u;u=r[o++];){u=u.split("-");var a=+u[0],f=+u[1]||a,l=document.createElement("div");l.textContent=Array(f-a+2).join(" \r\n");l.className=(n||"")+" line-highlight";l.setAttribute("data-start",a);f>a&&l.setAttribute("data-end",f);l.style.top=(a-i-1)*s+"px";(e.querySelector("code")||e).appendChild(l)}}function r(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var r=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(!r||document.getElementById(t))return;var i=t.slice(0,t.lastIndexOf(".")),s=document.getElementById(i);if(!s)return;s.hasAttribute("data-line")||s.setAttribute("data-line","");n(s,r,"temporary ");document.querySelector(".temporary.line-highlight").scrollIntoView()}if(!window.Prism)return;var t=crlf=/\r?\n|\r/g,i=0;Prism.hooks.add("after-highlight",function(t){var s=t.element.parentNode,o=s&&s.getAttribute("data-line");if(!s||!o||!/pre/i.test(s.nodeName))return;clearTimeout(i);e(".line-highlight",s).forEach(function(e){e.parentNode.removeChild(e)});n(s,o);i=setTimeout(r,1)});addEventListener("hashchange",r)})();; +Prism.hooks.add("after-highlight",function(e){var t=e.element.parentNode;if(!t||!/pre/i.test(t.nodeName)||t.className.indexOf("line-numbers")===-1){return}var n=1+e.code.split("\n").length;var r;lines=new Array(n);lines=lines.join("");r=document.createElement("span");r.className="line-numbers-rows";r.innerHTML=lines;if(t.hasAttribute("data-start")){t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)}e.element.appendChild(r)}) +; +(function(){if(!self.Prism||!self.document||!document.querySelector)return;var e={js:"javascript",html:"markup",svg:"markup"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(t){var n=t.getAttribute("data-src"),r=(n.match(/\.(\w+)$/)||[,""])[1],i=e[r]||r,s=document.createElement("code");s.className="language-"+i;t.textContent="";s.textContent="Loading…";t.appendChild(s);var o=new XMLHttpRequest;o.open("GET",n,!0);o.onreadystatechange=function(){if(o.readyState==4)if(o.status<400&&o.responseText){s.textContent=o.responseText;Prism.highlightElement(s)}else o.status>=400?s.textContent="✖ Error "+o.status+" while fetching file: "+o.statusText:s.textContent="✖ Error: File does not exist or is empty"};o.send(null)})})();; diff --git a/docs/api/namespaces/Morphatic.Qualtrics.Exceptions.html b/docs/api/namespaces/Morphatic.Qualtrics.Exceptions.html new file mode 100644 index 0000000..a74aeb1 --- /dev/null +++ b/docs/api/namespaces/Morphatic.Qualtrics.Exceptions.html @@ -0,0 +1,294 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +

\Morphatic\QualtricsExceptions

+ + + + +

Classes

+ + + + + + + + + + + + + + + + + + + + + + + + + +
CurlExceptionCurlException class
CurlNotInstalledExceptionCurlNotInstalledException class
MissingParameterExceptionMissingParameterException class
QualtricsExceptionQualtricsException class
QualtricsXMLExceptionQualtricsXMLException class
UnknownFormatExceptionUnknownFormatException class
+
+ + +
+ + + +
+
+ + +
+ + + diff --git a/docs/api/namespaces/Morphatic.Qualtrics.Facades.html b/docs/api/namespaces/Morphatic.Qualtrics.Facades.html new file mode 100644 index 0000000..fc10a35 --- /dev/null +++ b/docs/api/namespaces/Morphatic.Qualtrics.Facades.html @@ -0,0 +1,274 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +

\Morphatic\QualtricsFacades

+ + + + +

Classes

+ + + + + +
QualtricsQualtrics Facade class
+
+ + +
+ + + +
+
+ + +
+ + + diff --git a/docs/api/namespaces/Morphatic.Qualtrics.html b/docs/api/namespaces/Morphatic.Qualtrics.html new file mode 100644 index 0000000..bfb72d2 --- /dev/null +++ b/docs/api/namespaces/Morphatic.Qualtrics.html @@ -0,0 +1,285 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +

\MorphaticQualtrics

+ +

Namespaces

+ + + + + + + +
Exceptions
Facades
+ + + +

Classes

+ + + + + + + + + +
QualtricsQualtrics class
QualtricsServiceProviderQualtricsServiceProvider class
+
+ + +
+ + + +
+
+ + +
+ + + diff --git a/docs/api/namespaces/Morphatic.html b/docs/api/namespaces/Morphatic.html new file mode 100644 index 0000000..11a1201 --- /dev/null +++ b/docs/api/namespaces/Morphatic.html @@ -0,0 +1,269 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +

\Morphatic

+ +

Namespaces

+ + + + +
Qualtrics
+ + + +
+ + +
+ + + +
+
+ + +
+ + + diff --git a/docs/api/namespaces/default.html b/docs/api/namespaces/default.html new file mode 100644 index 0000000..ad2eeea --- /dev/null +++ b/docs/api/namespaces/default.html @@ -0,0 +1,267 @@ + + + + + + API Documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+ +

\

+ +

Namespaces

+ + + + +
Morphatic
+ + + +
+ + +
+ + + +
+
+ + +
+ + + diff --git a/docs/api/phpdoc-cache-12/phpdoc-cache-file_55bee62f28720e8e0ecea9c34b29e31a.dat b/docs/api/phpdoc-cache-12/phpdoc-cache-file_55bee62f28720e8e0ecea9c34b29e31a.dat new file mode 100644 index 0000000..60f1a9e Binary files /dev/null and b/docs/api/phpdoc-cache-12/phpdoc-cache-file_55bee62f28720e8e0ecea9c34b29e31a.dat differ diff --git a/docs/api/phpdoc-cache-2e/phpdoc-cache-settings.dat b/docs/api/phpdoc-cache-2e/phpdoc-cache-settings.dat new file mode 100644 index 0000000..27a6584 Binary files /dev/null and b/docs/api/phpdoc-cache-2e/phpdoc-cache-settings.dat differ diff --git a/docs/api/phpdoc-cache-3f/phpdoc-cache-file_5fe977692420139aa6c82c3ea49e6feb.dat b/docs/api/phpdoc-cache-3f/phpdoc-cache-file_5fe977692420139aa6c82c3ea49e6feb.dat new file mode 100644 index 0000000..2cdc685 Binary files /dev/null and b/docs/api/phpdoc-cache-3f/phpdoc-cache-file_5fe977692420139aa6c82c3ea49e6feb.dat differ diff --git a/docs/api/phpdoc-cache-4e/phpdoc-cache-file_957e1a6ca76e358d10c48ac8595e1b05.dat b/docs/api/phpdoc-cache-4e/phpdoc-cache-file_957e1a6ca76e358d10c48ac8595e1b05.dat new file mode 100644 index 0000000..99478d7 Binary files /dev/null and b/docs/api/phpdoc-cache-4e/phpdoc-cache-file_957e1a6ca76e358d10c48ac8595e1b05.dat differ diff --git a/docs/api/phpdoc-cache-8d/phpdoc-cache-file_356b0bacb928134a8d78712da5cfcdca.dat b/docs/api/phpdoc-cache-8d/phpdoc-cache-file_356b0bacb928134a8d78712da5cfcdca.dat new file mode 100644 index 0000000..4529a7e Binary files /dev/null and b/docs/api/phpdoc-cache-8d/phpdoc-cache-file_356b0bacb928134a8d78712da5cfcdca.dat differ diff --git a/docs/api/phpdoc-cache-97/phpdoc-cache-file_352efb01ca709034a3ac65e999a3dc4e.dat b/docs/api/phpdoc-cache-97/phpdoc-cache-file_352efb01ca709034a3ac65e999a3dc4e.dat new file mode 100644 index 0000000..2860e72 Binary files /dev/null and b/docs/api/phpdoc-cache-97/phpdoc-cache-file_352efb01ca709034a3ac65e999a3dc4e.dat differ diff --git a/docs/api/phpdoc-cache-a6/phpdoc-cache-file_4313677c65733c98ff23420431eb4b41.dat b/docs/api/phpdoc-cache-a6/phpdoc-cache-file_4313677c65733c98ff23420431eb4b41.dat new file mode 100644 index 0000000..2cd493f Binary files /dev/null and b/docs/api/phpdoc-cache-a6/phpdoc-cache-file_4313677c65733c98ff23420431eb4b41.dat differ diff --git a/docs/api/phpdoc-cache-a7/phpdoc-cache-file_29005756803c5317cb57c82411962b99.dat b/docs/api/phpdoc-cache-a7/phpdoc-cache-file_29005756803c5317cb57c82411962b99.dat new file mode 100644 index 0000000..cf36f25 Binary files /dev/null and b/docs/api/phpdoc-cache-a7/phpdoc-cache-file_29005756803c5317cb57c82411962b99.dat differ diff --git a/docs/api/phpdoc-cache-a9/phpdoc-cache-file_215adb4f17e6c57786bec362c538ccb8.dat b/docs/api/phpdoc-cache-a9/phpdoc-cache-file_215adb4f17e6c57786bec362c538ccb8.dat new file mode 100644 index 0000000..5ffd095 Binary files /dev/null and b/docs/api/phpdoc-cache-a9/phpdoc-cache-file_215adb4f17e6c57786bec362c538ccb8.dat differ diff --git a/docs/api/phpdoc-cache-e1/phpdoc-cache-file_ee2780d0da7bbfa01923159ab3d1c4d5.dat b/docs/api/phpdoc-cache-e1/phpdoc-cache-file_ee2780d0da7bbfa01923159ab3d1c4d5.dat new file mode 100644 index 0000000..da99e77 Binary files /dev/null and b/docs/api/phpdoc-cache-e1/phpdoc-cache-file_ee2780d0da7bbfa01923159ab3d1c4d5.dat differ diff --git a/docs/api/phpdoc-cache-f8/phpdoc-cache-file_798efd946e3ccd69a45dcc805346a404.dat b/docs/api/phpdoc-cache-f8/phpdoc-cache-file_798efd946e3ccd69a45dcc805346a404.dat new file mode 100644 index 0000000..ab1fe1b Binary files /dev/null and b/docs/api/phpdoc-cache-f8/phpdoc-cache-file_798efd946e3ccd69a45dcc805346a404.dat differ diff --git a/docs/api/reports/deprecated.html b/docs/api/reports/deprecated.html new file mode 100644 index 0000000..5eb6696 --- /dev/null +++ b/docs/api/reports/deprecated.html @@ -0,0 +1,155 @@ + + + + + + » Deprecated elements + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+ + +
+
No deprecated elements have been found in this project.
+
+
+
+ + +
+ + + diff --git a/docs/api/reports/errors.html b/docs/api/reports/errors.html new file mode 100644 index 0000000..ec0894f --- /dev/null +++ b/docs/api/reports/errors.html @@ -0,0 +1,174 @@ + + + + + + » Compilation errors + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + +
No errors have been found in this project.
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+ + + diff --git a/docs/api/reports/markers.html b/docs/api/reports/markers.html new file mode 100644 index 0000000..d426119 --- /dev/null +++ b/docs/api/reports/markers.html @@ -0,0 +1,208 @@ + + + + + + » Markers + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ + + + +
+
+ +

+ + Morphatic/Qualtrics/Qualtrics.php + 7 +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeLineDescription
TODO163
TODO233
TODO563Figure out how to handle POST file uploads with this method
TODO622investigate if this time shuffling is still necessary...
TODO666investigate if this time shuffling is still necessary...
TODO715investigate if this time shuffling is still necessary...
TODO859This function returns data in a non-standard format. Needs to be handled specially.
+
+
+
+
+
+ + +
+ + + diff --git a/license.txt b/license.txt index 922ad51..769a5a9 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright (c) 2013 Morgan C. Benton +Copyright (c) 2014 Morgan C. Benton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/readme.md b/readme.md index 69ac8be..c7bd441 100644 --- a/readme.md +++ b/readme.md @@ -1,15 +1,53 @@ ## Qualtrics API wrapper for Laravel 4 -The [Qualtrics REST API](https://survey.qualtrics.com/WRAPI/ControlPanel/docs.php) allows you to query the [Qualtrics](http://www.qualtrics.com) system using a simple URL syntax. All requests are simple GET or POST requests that return XML or JSON. The REST API allows you to interact with any part of the Qualtrics system allowing for full integration with client systems. - -This Qualtrics API wrapper for Laravel 4 provides access to the API via a PHP wrapper. - [![Latest Stable Version](https://poser.pugx.org/morphatic/qualtrics/v/stable.png)](https://packagist.org/packages/morphatic/qualtrics) [![Total Downloads](https://poser.pugx.org/morphatic/qualtrics/downloads.png)](https://packagist.org/packages/morphatic/qualtrics) [![Build Status](https://travis-ci.org/morphatic/qualtrics.png?branch=master)](https://travis-ci.org/morphatic/qualtrics) [![Coverage Status](https://coveralls.io/repos/morphatic/qualtrics/badge.png)](https://coveralls.io/r/morphatic/qualtrics) [![Dependency Status](https://www.versioneye.com/user/projects/52c8b848ec1375078b0000d1/badge.png)](https://www.versioneye.com/user/projects/52c8b848ec1375078b0000d1) +The [Qualtrics REST API](https://survey.qualtrics.com/WRAPI/ControlPanel/docs.php) allows you to query the [Qualtrics](http://www.qualtrics.com) system using a simple URL syntax. All requests are simple GET or POST requests that return XML or JSON. The REST API allows you to interact with any part of the Qualtrics system allowing for full integration with client systems. + +This Qualtrics API wrapper for Laravel 4 provides access to the API via a PHP wrapper. + +### Installation + +To install the Qualtrics API wrapper for Laravel 4, add the following to the `"require"` element of your `composer.json` file: + +``` + "morphatic/qualtrics": "1.0.*@dev" +``` + +Then run `composer update` from the command line. + +In `config.app` under `providers` add: + +``` + 'Morphatic\Qualtrics\QualtricsServiceProvider', +``` + +And under `aliases` add: + +``` + 'Qualtrics' => 'Morphatic\Qualtrics\Facades\Qualtrics', +``` + +Finally, from the command line run: + +``` + php artisan config:publish morphatic/qualtrics +``` + +And in the `app/config/packages/morphatic/qualtrics/config.php` file update your username and API token. Optionally you may also add a library ID to the config file. + +### Basic usage + + + +### Disclaimer + +I am in no way, shape, or form affiliated with [Qualtrics](http://www.qualtrics.com). In order to [gain access to the Qualtrics REST API](http://qualtrics.com/university/researchsuite/developer-tools/api-integration/qualtrics-rest-api/), your organization or institution must subscribe to this service. In my case, it meant contacting an IT administrator at my university and asking them to do so. + ### License Qualtrics API wrapper for Laravel 4 is open-sourced software licensed under the [MIT license](http://opensource.org/licenses/MIT) \ No newline at end of file diff --git a/src/Morphatic/Qualtrics/Exceptions/CurlException.php b/src/Morphatic/Qualtrics/Exceptions/CurlException.php index d6da1fc..9e0624a 100644 --- a/src/Morphatic/Qualtrics/Exceptions/CurlException.php +++ b/src/Morphatic/Qualtrics/Exceptions/CurlException.php @@ -1,4 +1,14 @@ @@ -55,7 +63,8 @@ public function __construct() { /** * Converts XML to Array that can then be converted to JSON * - * @param SimpleXMLElement $xml The XML to be converted + * @param \SimpleXMLElement $xml The XML to be converted + * @param object[] $out An empty array to be populated by the function * @return array The XML converted to an array */ private function xmlToArray( $xml, $out = array() ) { @@ -100,11 +109,13 @@ function ($field) { /** * Parses the data returned from a Qualtrics request. * - * @param resource $ch The curl handle associated with the request - * @param string $result The text returned from the request + * @param resource $ch The curl handle associated with the request + * @param string $result The text returned from the request + * @throws Exceptions\QualtricsXMLException Thrown when an XML response cannot be parsed correctly + * @throws Exceptions\UnknownFormatException Thrown when Qualtrics returns a response with an unrecognized content-type header * @return array Returns an array with the headers and parsed response text */ - private function parseResponse( $ch, $result, $request ) { + private function parseResponse( $ch, $result ) { // determine where the headers end and the response begins $header_length = curl_getinfo( $ch, CURLINFO_HEADER_SIZE ); @@ -165,11 +176,14 @@ private function parseResponse( $ch, $result, $request ) { * Private function that makes a generic Qualtrics API request. * * This function takes an API function name and an array of parameters - * and makes an attempt to fetch th edata using the Qualtrics API. + * and makes an attempt to fetch the data using the Qualtrics API. * - * @param string $request The name of the API function to be called - * @param mixed $params An array which contains any necessary parameters for the API call - * @return object Returns either an object representing the requested data or a WP_Error object + * @param string $request The name of the API function to be called + * @param string[] $params An array which contains any necessary parameters for the API call + * @throws Exceptions\CurlNotInstalledException Thrown when the curl library is not installed on the server + * @throws Exceptions\QualtricsException Thrown when Qualtrics returns an error with the request + * @throws Exceptions\CurlException Thrown when the curl request is unsuccessful, e.g. request timeout + * @return object Returns an object representing the requested data */ private function request( $request, $params = array() ) { @@ -228,10 +242,17 @@ private function request( $request, $params = array() ) { /** * Gets the total number of responses for a survey in a given date range * - * @param string Format Must be XML or JSON, defaults to JSON - * @param string StartDate Start date of responses to include, format is YYYY-MM-DD - * @param string EndDate End date of responses to include, format is YYYY-MM-DD, default is today's date - * @param string SurveyID The Qualtrics ID of the survey in question. The user must have permission to view this survey's responses. + * ``` + * $params = array( + * 'Format' => 'JSON', // Must be XML or JSON, defaults to JSON + * 'StartDate' => 'YYYY-MM-DD', // Start date of responses to include + * 'EndDate' => 'YYYY-MM-DD', // (optional) defaults to today's date + * 'SurveyID' => 'SV_9LC2rrUZT8c2EiF', // the Qualtrics ID of the survey in question. + * ); + * ``` + * + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object Returns a PHP object with the resulting counts of "Auditable", "Generated" and "Deleted" responses */ function getResponseCountsBySurvey( $params = array() ) { @@ -255,7 +276,14 @@ function getResponseCountsBySurvey( $params = array() ) { /** * Gets information about a user * - * @param string Format Must be XML or JSON. Defaults to JSON. + * ``` + * $params = array( + * 'Format' => 'JSON', // Must be XML or JSON, defaults to JSON + * ); + * ``` + * + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object Information about the user in question */ function getUserInfo( $params = array() ) { @@ -269,16 +297,24 @@ function getUserInfo( $params = array() ) { /** * Add a new recipient to a panel * - * @param string Format Must be XML or JSON, defaults to JSON - * @param string LibraryID The LibraryID of the user who owns the panel - * @param string PanelID The ID of the Panel to which the user is to be added - * @param string FirstName First name of the new recipient - * @param string LastName Last name of the new recipient - * @param string Email Email address of the new recipient - * @param string ExternalDataRef (optional) A value to store in the external data ref for the user (should default to the WordPress username) - * @param string Language (optional) The language code for the user, e.g. EN, defaults to EN - * @param string ED[***] (optional) An embedded data value, there can be many, and takes the form e.g. ED[skypeID]=mcbenton - * @return object Returns true on success or WP_Error on failure + * ``` + * $params = array( + * 'Format' => 'JSON', // Must be XML or JSON, defaults to JSON + * 'LibraryID' => 'GR_6G4LaoiroGxHH12', // Start date of responses to include + * 'PanelID' => 'ML_5yIfnFP0soZK3GJ', // Start date of responses to include + * 'FirstName' => 'Douglas', // Recipient's first name + * 'LastName' => 'Crockford', // Recipient's last name + * 'Email' => 'doug@js.org', // Recipient's email address + * 'ExternalDataRef' => 'crockdx', // (optional) + * 'Language' => 'EN', // (optional) language, defaults to EN + * 'ED[***]' => '@dougcrockford', // (optional) embedded data, e.g. ED[twitterID] + * // multiple values for ED possible + * ); + * ``` + * + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array + * @return object Returns true on success */ function addRecipient( $params = array() ) { // set the parameters for this request @@ -311,6 +347,8 @@ function addRecipient( $params = array() ) { * @param string PanelID The ID of the panel for the distribution * @param string Description A description of the distribution * @param string PanelLibraryID The library ID of the panel + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object An object containing the DistributionID */ function createDistribution( $params = array() ) { @@ -340,6 +378,8 @@ function createDistribution( $params = array() ) { * @param string LibraryID The library ID of the user creating the panel * @param string Name A name for the new panel * @param string Category (optional) The category the panel is created in + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object Returns the ID of the new panel */ function createPanel( $params = array() ) { @@ -365,6 +405,8 @@ function createPanel( $params = array() ) { * @param string LibraryID The library ID of the panel * @param string PanelID The panel ID you want to export * @param string EmbeddedData A comma-separated list of the embedded data keys you want to export. Only required for CSV export. XML includes all embedded data. + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The panel members and any requested data */ function getPanel( $params = array() ) { @@ -389,6 +431,8 @@ function getPanel( $params = array() ) { * @param string Format Must be XML, CSV, or HTML, defaults to CSV * @param string LibraryID The library ID of the panel * @param string PanelID The panel ID you want to export + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The results of the deletion process */ function deletePanel( $params = array() ) { @@ -413,6 +457,8 @@ function deletePanel( $params = array() ) { * @param string Format Must be XML or JSON, defaults to JSON * @param string LibraryID The library ID of the panel * @param string PanelID The panel ID you want to get a count for + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The number of members of the panel */ function getPanelMemberCount( $params = array() ) { @@ -436,6 +482,8 @@ function getPanelMemberCount( $params = array() ) { * * @param string Format Must be XML or JSON, defaults to JSON * @param string LibraryID The library ID of the panel + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The panels in the library */ function getPanels( $params = array() ) { @@ -456,6 +504,8 @@ function getPanels( $params = array() ) { * @param string Format Must be XML or JSON, defaults to JSON * @param string LibraryID The library ID of the panel * @param string RecipientID The recipient ID you want to get + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The representation of the recipient */ function getRecipient( $params = array() ) { @@ -496,6 +546,8 @@ function getRecipient( $params = array() ) { * @param string AllED (optional) 0:1 If set to 1, will import all non-used columns as embedded data, and you won't have to set the EmbeddedData parameter * @param string EmbeddedData (optional) Comma-separated list of column numbers to treat as embedded data * @param string Category (optional) Sets the category for the panel + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object Contains the new PanelID, a count of imported recipients, and a count of ignored recipients */ function importPanel( $params = array() ) { @@ -524,6 +576,8 @@ function importPanel( $params = array() ) { * @param string LibraryID The library ID of the panel * @param string PanelID The ID of the panel from which the recipient will be removed * @param string RecipientID The recipient ID you want to remove + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The representation of the recipient */ function removeRecipient( $params = array() ) { @@ -555,6 +609,8 @@ function removeRecipient( $params = array() ) { * @param string Subject The subject for the email * @param string MessageID The ID of the message from the message library to be sent * @param string LibraryID The ID of the library that contains the message to be sent + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The email distribution ID and distribution queue id */ function sendReminder( $params = array() ) { @@ -596,6 +652,8 @@ function sendReminder( $params = array() ) { * @param string PanelID The ID of the message from the message library to be sent * @param string PanelLibraryID The ID of the library that contains the message to be sent * @param string RecipientID The recipient ID of the person to whom to send the survey + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The email distribution ID and distribution queue id */ function sendSurveyToIndividual( $params = array() ) { @@ -643,6 +701,8 @@ function sendSurveyToIndividual( $params = array() ) { * @param string PanelLibraryID The ID of the library that contains the message to be sent * @param string ExpirationDate (optional) YYYY-MM-DD hh:mm:ss when the survey invitation expires * @param string LinkType (optional) {Individual,Multiple,Anonymous} Defaults to Individual + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object The email distribution ID and distribution queue id */ function sendSurveyToPanel( $params = array() ) { @@ -685,6 +745,8 @@ function sendSurveyToPanel( $params = array() ) { * @param string ExternalDataRef (optional) A value to store in the external data ref for the user (should default to the WordPress username) * @param string Language (optional) The language code for the user, e.g. EN, defaults to EN * @param string ED[***] (optional) An embedded data value, there can be many, and takes the form e.g. ED[skypeID]=mcbenton + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object Returns true on success or WP_Error on failure **/ function updateRecipient( $params = array() ) { @@ -725,6 +787,8 @@ function updateRecipient( $params = array() ) { * @param string UnansweredRecode (optional) The recode value for seen but unanswered questions. If not specified a blank value is put in for these questions. * @param string PanelID (optional) If supplied it will only get the results for the members of the panel specified * @param string ResponseInProgress (optional) If 1 (true) will retrieve the responses in progress (and only the responses in progress ) + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object An object representing the responses for the specified panel members */ public function getLegacyResponseData( $params = array() ) { @@ -777,6 +841,8 @@ public function getLegacyResponseData( $params = array() ) { * * @param string SurveyID The ID of the survey to be exported * @param string ExportLogic If 1 (true) it will export the logic. EXPERIMENTAL + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object On object representing the survey. */ function getSurvey( $params = array() ) { @@ -798,6 +864,8 @@ function getSurvey( $params = array() ) { * This request returns a list of all the surveys for the user * * @param string Format {XML,JSON} Default is JSON + * @param string[] $params An array of named parameters needed to complete the request (see code above) + * @throws Exceptions\MissingParameterException Thrown when one of the required parameters does not exist in the $params array * @return object A list of surveys available to the user */ function getSurveys( $params = array() ) { diff --git a/src/Morphatic/Qualtrics/QualtricsServiceProvider.php b/src/Morphatic/Qualtrics/QualtricsServiceProvider.php index 249849c..3a99e36 100644 --- a/src/Morphatic/Qualtrics/QualtricsServiceProvider.php +++ b/src/Morphatic/Qualtrics/QualtricsServiceProvider.php @@ -1,8 +1,18 @@ -