remove wordpress-importer,google-calendar-events, adds gentsentry-client
No files matched your search
@@ -0,0 +1,4 @@
|
||||
wordpress-sentry
|
||||
================
|
||||
|
||||
A WordPress plugin to handle reporting php error to the [Sentry error reporting system](https://getsentry.com/welcome/).
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/raven/lib/Raven/Autoloader.php';
|
||||
Raven_Autoloader::register();
|
||||
|
||||
class WP_Raven_Client extends Raven_Client {
|
||||
|
||||
protected $settings;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $errorLevelMap;
|
||||
|
||||
public function __construct() {
|
||||
|
||||
$this->errorLevelMap = array(
|
||||
'E_NONE' => 0,
|
||||
'E_ERROR' => 1,
|
||||
'E_WARNING' => 2,
|
||||
'E_PARSE' => 4,
|
||||
'E_NOTICE' => 8,
|
||||
'E_USER_ERROR' => 256,
|
||||
'E_USER_WARNING' => 512,
|
||||
'E_USER_NOTICE' => 1024,
|
||||
'E_RECOVERABLE_ERROR' => 4096,
|
||||
'E_ALL' => 8191);
|
||||
|
||||
$this->settings = get_option('sentry-settings');
|
||||
|
||||
if (!isset($this->settings['dsn']))
|
||||
return;
|
||||
|
||||
if ($this->settings['dsn'] == '')
|
||||
return;
|
||||
|
||||
parent::__construct($this->settings['dsn']);
|
||||
|
||||
$this->setErrorReportingLevel(
|
||||
$this->settings['reporting_level']);
|
||||
|
||||
$this->setHandlers();
|
||||
}
|
||||
|
||||
private function setHandlers() {
|
||||
$error_handler = new Raven_ErrorHandler($this);
|
||||
$error_handler->registerErrorHandler();
|
||||
$error_handler->registerExceptionHandler();
|
||||
$error_handler->registerShutdownFunction();
|
||||
}
|
||||
|
||||
private function setErrorReportingLevel($level = 'E_ERROR')
|
||||
{
|
||||
error_reporting($this->errorLevelMap[$level]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "ryanbagwell/wordpress-sentry",
|
||||
"description": "A plugin that sends error messages to the Sentry error logging system.",
|
||||
"license": "GPLv2 or later",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ryan Bagwell",
|
||||
"email": "ryan@ryanbagwell.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"raven/raven": "0.10.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<div class="wrap">
|
||||
<h2>Sentry Error Reporting Settings</h2>
|
||||
|
||||
<form action="" method="post">
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr valign="top">
|
||||
<th scope="row">
|
||||
<label for="sentry_dsn">Sentry DSN</label>
|
||||
</th>
|
||||
<td>
|
||||
<input name="sentry_dsn" type="text" id="sentry-dsn" value="<?php echo $settings['dsn']; ?>" class="regular-text">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr valign="top">
|
||||
<th scope="row">
|
||||
<label for="sentry_dsn">Error Reporting Level</label>
|
||||
</th>
|
||||
<td>
|
||||
<select name="sentry_reporting_level">
|
||||
<?php foreach ($error_levels as $level => $int): ?>
|
||||
<option value="<?php echo $level; ?>" <?php echo ($settings['reporting_level'] == $level) ? 'selected="selected"' : '';?>><?php echo $level; ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
("User Notices" is recommended)
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p class="submit">
|
||||
<input type="submit" name="submit" id="submit" class="button-primary" value="Save Changes">
|
||||
</p>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,4 @@
|
||||
The Sentry PHP SDK was originally written by Michael van Tellingen
|
||||
and is maintained by the Sentry Team.
|
||||
|
||||
http://github.com/getsentry/sentry-php/contributors
|
||||
@@ -0,0 +1,70 @@
|
||||
0.15.0
|
||||
------
|
||||
|
||||
- Fixed some cases where serialization wouldn't happen.
|
||||
- Added sdk attribute.
|
||||
|
||||
0.14.0
|
||||
------
|
||||
|
||||
- Added ``prefixes`` option for stripping absolute paths.
|
||||
- Removed ``abs_path`` from stacktraces.
|
||||
- Added ``app_path`` to specify application root for resolving ``in_app` on frames.
|
||||
- Moved Laravel support to ``sentry-laravel`` project.
|
||||
- Fixed duplicate stack computation.
|
||||
- Added ``dsn`` option to ease configuration.
|
||||
- Fixed an issue with the curl async transport.
|
||||
- Improved serialization of values.
|
||||
|
||||
0.13.0
|
||||
------
|
||||
|
||||
- Updated API to use new style interfaces.
|
||||
- Remove session cookie in default processor.
|
||||
- Expand docs for Laravel, Symfony2, and Monolog.
|
||||
- Default error types can now be set as part of ErrorHandler configuration.
|
||||
|
||||
0.12.1
|
||||
------
|
||||
|
||||
- Dont send empty values for various context.
|
||||
|
||||
0.12.0
|
||||
------
|
||||
|
||||
- Bumped protocol version to 6.
|
||||
- Fixed an issue with the async curl handler (GH-216).
|
||||
- Removed UDP transport.
|
||||
|
||||
0.11.0
|
||||
------
|
||||
|
||||
- New configuration parameter: 'release'
|
||||
- New configuration parameter: 'message_limit'
|
||||
- New configuration parameter: 'curl_ssl_version'
|
||||
- New configuration parameter: 'curl_ipv4'
|
||||
- New configuration parameter: 'verify_ssl'
|
||||
- Updated remote endpoint to use modern project-based path.
|
||||
- Expanded default sanitizer support to include 'auth_pw' attribute.
|
||||
|
||||
0.10.0
|
||||
------
|
||||
|
||||
- Added a default certificate bundle which includes common root CA's
|
||||
as well as getsentry.com's CA.
|
||||
|
||||
0.9.1
|
||||
-----
|
||||
|
||||
- Change default curl connection to 'sync'
|
||||
- Improve CLI reporting
|
||||
|
||||
|
||||
0.9.0
|
||||
-----
|
||||
|
||||
- Protocol version 5
|
||||
- Default to asynchronous HTTP handler using curl_multi.
|
||||
|
||||
|
||||
(For previous versions see the commit history)
|
||||
@@ -0,0 +1,12 @@
|
||||
Copyright (c) 2012 Sentry Team and individual contributors.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the Raven, Sentry, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,21 @@
|
||||
.PHONY: test
|
||||
|
||||
develop: update-submodules
|
||||
composer install --dev
|
||||
make setup-git
|
||||
|
||||
update-submodules:
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
cs:
|
||||
vendor/bin/php-cs-fixer fix --config-file=.php_cs --verbose --diff
|
||||
|
||||
cs-dry-run:
|
||||
vendor/bin/php-cs-fixer fix --config-file=.php_cs --verbose --diff --dry-run
|
||||
|
||||
test: cs-dry-run
|
||||
vendor/bin/phpunit
|
||||
|
||||
setup-git:
|
||||
git config branch.autosetuprebase always
|
||||
@@ -0,0 +1,273 @@
|
||||
sentry-php
|
||||
==========
|
||||
|
||||
.. image:: https://secure.travis-ci.org/getsentry/sentry-php.png?branch=master
|
||||
:target: http://travis-ci.org/getsentry/sentry-php
|
||||
|
||||
|
||||
The official PHP SDK for `Sentry <https://getsentry.com/>`_.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// Instantiate a new client with a compatible DSN
|
||||
$client = new Raven_Client('http://public:secret@example.com/1');
|
||||
|
||||
// Capture a message
|
||||
$event_id = $client->getIdent($client->captureMessage('my log message'));
|
||||
if ($client->getLastError() !== null) {
|
||||
printf('There was an error sending the event to Sentry: %s', $client->getLastError());
|
||||
}
|
||||
|
||||
// Capture an exception
|
||||
$event_id = $client->getIdent($client->captureException($ex));
|
||||
|
||||
// Provide some additional data with an exception
|
||||
$event_id = $client->getIdent($client->captureException($ex, array(
|
||||
'extra' => array(
|
||||
'php_version' => phpversion()
|
||||
),
|
||||
)));
|
||||
|
||||
// Give the user feedback
|
||||
echo "Sorry, there was an error!";
|
||||
echo "Your reference ID is " . $event_id;
|
||||
|
||||
// Install error handlers and shutdown function to catch fatal errors
|
||||
$error_handler = new Raven_ErrorHandler($client);
|
||||
$error_handler->registerExceptionHandler();
|
||||
$error_handler->registerErrorHandler();
|
||||
$error_handler->registerShutdownFunction();
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Install with Composer
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you're using `Composer <https://getcomposer.org/>`_ to manage
|
||||
dependencies, you can add Raven with it.
|
||||
|
||||
::
|
||||
|
||||
$ composer require sentry/sentry:$VERSION
|
||||
|
||||
(replace ``$VERSION`` with one of the available versions on `Packagist <https://packagist.org/packages/sentry/sentry>`_)
|
||||
or to get the latest version off the master branch:
|
||||
|
||||
::
|
||||
|
||||
$ composer require sentry/sentry:dev-master
|
||||
|
||||
Note that using unstable versions is not recommended and should be avoided. Also
|
||||
you should define a maximum version, e.g. by doing ``>=0.6,<1.0`` or ``~0.6``.
|
||||
|
||||
Alternatively, use the ``^`` operator for specifying a version, e.g.,
|
||||
|
||||
::
|
||||
|
||||
$ composer require sentry/sentry:^0.11.0
|
||||
|
||||
Composer will take care of the autoloading for you, so if you require the
|
||||
``vendor/autoload.php``, you're good to go.
|
||||
|
||||
|
||||
Install source from GitHub
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To install the source code:
|
||||
|
||||
::
|
||||
|
||||
$ git clone git://github.com/getsentry/sentry-php.git
|
||||
|
||||
And including it using the autoloader:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
require_once '/path/to/Raven/library/Raven/Autoloader.php';
|
||||
Raven_Autoloader::register();
|
||||
|
||||
Testing Your Connection
|
||||
-----------------------
|
||||
|
||||
The PHP client includes a simple helper script to test your connection and credentials with
|
||||
the Sentry master server:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ bin/sentry test https://public:secret@app.getsentry.com/1
|
||||
Client configuration:
|
||||
-> server: [https://sentry.example.com/api/store/]
|
||||
-> project: 1
|
||||
-> public_key: public
|
||||
-> secret_key: secret
|
||||
|
||||
Sending a test event:
|
||||
-> event ID: f1765c9aed4f4ceebe5a93df9eb2d34f
|
||||
|
||||
Done!
|
||||
|
||||
.. note:: The CLI enforces the synchronous option on HTTP requests whereas the default configuration is asyncrhonous.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Several options exist that allow you to configure the behavior of the ``Raven_Client``. These are passed as the
|
||||
second parameter of the constructor, and is expected to be an array of key value pairs:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client = new Raven_Client($dsn, array(
|
||||
'option_name' => 'value',
|
||||
));
|
||||
|
||||
``name``
|
||||
~~~~~~~~
|
||||
|
||||
A string to override the default value for the server's hostname.
|
||||
|
||||
Defaults to ``Raven_Compat::gethostname()``.
|
||||
|
||||
``tags``
|
||||
~~~~~~~~
|
||||
|
||||
An array of tags to apply to events in this context.
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'tags' => array(
|
||||
'php_version' => phpversion(),
|
||||
)
|
||||
|
||||
|
||||
``curl_method``
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Defaults to 'sync'.
|
||||
|
||||
Available methods:
|
||||
|
||||
- sync (default): send requests immediately when they're made
|
||||
- async: uses a curl_multi handler for best-effort asynchronous submissions
|
||||
- exec: asynchronously send events by forking a curl process for each item
|
||||
|
||||
``curl_path``
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Defaults to 'curl'.
|
||||
|
||||
Specify the path to the curl binary to be used with the 'exec' curl method.
|
||||
|
||||
|
||||
``trace``
|
||||
~~~~~~~~~
|
||||
|
||||
Set this to ``false`` to disable reflection tracing (function calling arguments) in stacktraces.
|
||||
|
||||
|
||||
``logger``
|
||||
~~~~~~~~~~
|
||||
|
||||
Adjust the default logger name for messages.
|
||||
|
||||
Defaults to ``php``.
|
||||
|
||||
``ca_cert``
|
||||
~~~~~~~~~~~
|
||||
|
||||
The path to the CA certificate bundle.
|
||||
|
||||
Defaults to the common bundle which includes getsentry.com: ./data/cacert.pem
|
||||
|
||||
Caveats:
|
||||
|
||||
- The CA bundle is ignored unless curl throws an error suggesting it needs a cert.
|
||||
- The option is only currently used within the synchronous curl transport.
|
||||
|
||||
``curl_ssl_version``
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The SSL version (2 or 3) to use.
|
||||
By default PHP will try to determine this itself, although in some cases this must be set manually.
|
||||
|
||||
``message_limit``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Defaults to 1024 characters.
|
||||
|
||||
This value is used to truncate message and frame variables. However it is not guarantee that length of whole message will be restricted by this value.
|
||||
|
||||
``processors``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
An array of classes to use to process data before it is sent to Sentry. By default, Raven_SanitizeDataProcessor is used
|
||||
|
||||
``processorOptions``
|
||||
~~~~~~~~~~~~~~~~~
|
||||
Options that will be passed on to a setProcessorOptions() function in a Raven_Processor sub-class before that Processor is added to the list of processors used by Raven_Client
|
||||
|
||||
An example of overriding the regular expressions in Raven_SanitizeDataProcessor is below:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
'processorOptions' => array(
|
||||
'Raven_SanitizeDataProcessor' => array(
|
||||
'fields_re' => '/(user_password|user_token|user_secret)/i',
|
||||
'values_re' => '/^(?:\d[ -]*?){15,16}$/'
|
||||
)
|
||||
)
|
||||
|
||||
Providing Request Context
|
||||
-------------------------
|
||||
|
||||
Most of the time you're not actually calling out to Raven directly, but you still want to provide some additional context. This lifecycle generally constists of something like the following:
|
||||
|
||||
- Set some context via a middleware (e.g. the logged in user)
|
||||
- Send all given context with any events during the request lifecycle
|
||||
- Cleanup context
|
||||
|
||||
There are three primary methods for providing request context:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
// bind the logged in user
|
||||
$client->user_context(array('email' => 'foo@example.com'));
|
||||
|
||||
// tag the request with something interesting
|
||||
$client->tags_context(array('interesting' => 'yes'));
|
||||
|
||||
// provide a bit of additional context
|
||||
$client->extra_context(array('happiness' => 'very'));
|
||||
|
||||
|
||||
If you're performing additional requests during the lifecycle, you'll also need to ensure you cleanup the context (to reset its state):
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
$client->context->clear();
|
||||
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
First, make sure you can run the test suite. Install development dependencies :
|
||||
|
||||
::
|
||||
|
||||
$ composer install
|
||||
|
||||
You may now use phpunit :
|
||||
|
||||
::
|
||||
|
||||
$ vendor/bin/phpunit
|
||||
|
||||
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
* `Bug Tracker <http://github.com/getsentry/sentry-php/issues>`_
|
||||
* `Code <http://github.com/getsentry/sentry-php>`_
|
||||
* `Mailing List <https://groups.google.com/group/getsentry>`_
|
||||
* `IRC <irc://irc.freenode.net/sentry>`_ (irc.freenode.net, #sentry)
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/usr/bin/php
|
||||
<?php
|
||||
|
||||
// Maximize error reporting
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
// TODO: if we could get rid of this and have composer figure things out it'd make it
|
||||
// a bit more sane
|
||||
require(dirname(__file__) . '/../lib/Raven/Autoloader.php');
|
||||
Raven_Autoloader::register();
|
||||
|
||||
function raven_cli_test($command, $args)
|
||||
{
|
||||
// Do something silly
|
||||
try {
|
||||
throw new Exception('This is a test exception sent from the Raven CLI.');
|
||||
} catch (Exception $ex) {
|
||||
return $ex;
|
||||
}
|
||||
}
|
||||
|
||||
function cmd_test($dsn)
|
||||
{
|
||||
if (empty($dsn)) {
|
||||
exit('ERROR: Missing DSN value');
|
||||
}
|
||||
|
||||
// Parse DSN as a test
|
||||
try {
|
||||
$parsed = Raven_Client::parseDSN($dsn);
|
||||
} catch (InvalidArgumentException $ex) {
|
||||
exit("ERROR: There was an error parsing your DSN:\n " . $ex->getMessage());
|
||||
}
|
||||
|
||||
$client = new Raven_Client($dsn, array(
|
||||
'trace' => true,
|
||||
'curl_method' => 'sync',
|
||||
));
|
||||
|
||||
$config = get_object_vars($client);
|
||||
$required_keys = array('servers', 'project', 'public_key', 'secret_key');
|
||||
|
||||
echo "Client configuration:\n";
|
||||
foreach ($required_keys as $key) {
|
||||
if (empty($config[$key])) {
|
||||
exit("ERROR: Missing configuration for $key");
|
||||
}
|
||||
if (is_array($config[$key])) {
|
||||
echo "-> $key: [".implode(", ", $config[$key])."]\n";
|
||||
} else {
|
||||
echo "-> $key: $config[$key]\n";
|
||||
}
|
||||
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
echo "Sending a test event:\n";
|
||||
|
||||
$ex = raven_cli_test("command name", array("foo" => "bar"));
|
||||
$event_id = $client->captureException($ex);
|
||||
|
||||
echo "-> event ID: $event_id\n";
|
||||
|
||||
$last_error = $client->getLastError();
|
||||
if (!empty($last_error)) {
|
||||
exit("ERROR: There was an error sending the test event:\n " . $last_error);
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
echo "Done!";
|
||||
}
|
||||
|
||||
|
||||
function main() {
|
||||
global $argv;
|
||||
|
||||
$cmd = $argv[1];
|
||||
|
||||
switch ($cmd) {
|
||||
case 'test':
|
||||
cmd_test(@$argv[2]);
|
||||
break;
|
||||
default:
|
||||
exit('Usage: raven test <dsn>');
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"name": "sentry/sentry",
|
||||
"type": "library",
|
||||
"description": "A PHP client for Sentry (http://getsentry.com)",
|
||||
"keywords": ["log", "logging"],
|
||||
"homepage": "http://getsentry.com",
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Cramer",
|
||||
"email": "dcramer@gmail.com"
|
||||
}
|
||||
],
|
||||
"require-dev": {
|
||||
"fabpot/php-cs-fixer": "^1.8.0",
|
||||
"phpunit/phpunit": "^4.6.6"
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.2.4",
|
||||
"ext-curl": "*",
|
||||
"monolog/monolog": "*"
|
||||
},
|
||||
"bin": [
|
||||
"bin/sentry"
|
||||
],
|
||||
"autoload": {
|
||||
"psr-0" : {
|
||||
"Raven_" : "lib/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.17.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Autoloads Raven classes.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Autoloader
|
||||
{
|
||||
/**
|
||||
* Registers Raven_Autoloader as an SPL autoloader.
|
||||
*/
|
||||
public static function register()
|
||||
{
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
spl_autoload_register(array('Raven_Autoloader', 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles autoloading of classes.
|
||||
*
|
||||
* @param string $class A class name.
|
||||
*/
|
||||
public static function autoload($class)
|
||||
{
|
||||
if (0 !== strpos($class, 'Raven')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) {
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,978 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Raven PHP Client
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
class Raven_Client
|
||||
{
|
||||
const VERSION = '0.17.0';
|
||||
const PROTOCOL = '6';
|
||||
|
||||
const DEBUG = 'debug';
|
||||
const INFO = 'info';
|
||||
const WARN = 'warning';
|
||||
const WARNING = 'warning';
|
||||
const ERROR = 'error';
|
||||
const FATAL = 'fatal';
|
||||
|
||||
const MESSAGE_LIMIT = 1024;
|
||||
|
||||
public $severity_map;
|
||||
public $extra_data;
|
||||
|
||||
public $store_errors_for_bulk_send = false;
|
||||
|
||||
public function __construct($options_or_dsn=null, $options=array())
|
||||
{
|
||||
if (is_array($options_or_dsn)) {
|
||||
$options = array_merge($options_or_dsn, $options);
|
||||
}
|
||||
|
||||
if (!is_array($options_or_dsn) && !empty($options_or_dsn)) {
|
||||
$dsn = $options_or_dsn;
|
||||
} elseif (!empty($_SERVER['SENTRY_DSN'])) {
|
||||
$dsn = @$_SERVER['SENTRY_DSN'];
|
||||
} elseif (!empty($options['dsn'])) {
|
||||
$dsn = $options['dsn'];
|
||||
} else {
|
||||
$dsn = null;
|
||||
}
|
||||
|
||||
if (!empty($dsn)) {
|
||||
$options = array_merge($options, self::parseDSN($dsn));
|
||||
}
|
||||
|
||||
$this->logger = Raven_Util::get($options, 'logger', 'php');
|
||||
$this->server = Raven_Util::get($options, 'server');
|
||||
$this->secret_key = Raven_Util::get($options, 'secret_key');
|
||||
$this->public_key = Raven_Util::get($options, 'public_key');
|
||||
$this->project = Raven_Util::get($options, 'project', 1);
|
||||
$this->auto_log_stacks = (bool) Raven_Util::get($options, 'auto_log_stacks', false);
|
||||
$this->name = Raven_Util::get($options, 'name', Raven_Compat::gethostname());
|
||||
$this->site = Raven_Util::get($options, 'site', $this->_server_variable('SERVER_NAME'));
|
||||
$this->tags = Raven_Util::get($options, 'tags', array());
|
||||
$this->release = Raven_Util::get($options, 'release', null);
|
||||
$this->environment = Raven_Util::get($options, 'environment', null);
|
||||
$this->trace = (bool) Raven_Util::get($options, 'trace', true);
|
||||
$this->timeout = Raven_Util::get($options, 'timeout', 2);
|
||||
$this->message_limit = Raven_Util::get($options, 'message_limit', self::MESSAGE_LIMIT);
|
||||
$this->exclude = Raven_Util::get($options, 'exclude', array());
|
||||
$this->severity_map = null;
|
||||
$this->shift_vars = (bool) Raven_Util::get($options, 'shift_vars', true);
|
||||
$this->http_proxy = Raven_Util::get($options, 'http_proxy');
|
||||
$this->extra_data = Raven_Util::get($options, 'extra', array());
|
||||
$this->send_callback = Raven_Util::get($options, 'send_callback', null);
|
||||
$this->curl_method = Raven_Util::get($options, 'curl_method', 'sync');
|
||||
$this->curl_path = Raven_Util::get($options, 'curl_path', 'curl');
|
||||
$this->curl_ipv4 = Raven_util::get($options, 'curl_ipv4', true);
|
||||
$this->ca_cert = Raven_Util::get($options, 'ca_cert', $this->get_default_ca_cert());
|
||||
$this->verify_ssl = Raven_Util::get($options, 'verify_ssl', true);
|
||||
$this->curl_ssl_version = Raven_Util::get($options, 'curl_ssl_version');
|
||||
$this->trust_x_forwarded_proto = Raven_Util::get($options, 'trust_x_forwarded_proto');
|
||||
// a list of prefixes used to coerce absolute paths into relative
|
||||
$this->prefixes = Raven_Util::get($options, 'prefixes', null);
|
||||
// app path is used to determine if code is part of your application
|
||||
$this->app_path = Raven_Util::get($options, 'app_path', null);
|
||||
|
||||
$this->processors = $this->setProcessorsFromOptions($options);
|
||||
|
||||
$this->_lasterror = null;
|
||||
$this->_last_event_id = null;
|
||||
$this->_user = null;
|
||||
$this->context = new Raven_Context();
|
||||
$this->breadcrumbs = new Raven_Breadcrumbs();
|
||||
$this->sdk = Raven_Util::get($options, 'sdk', array(
|
||||
'name' => 'sentry-php',
|
||||
'version' => self::VERSION,
|
||||
));
|
||||
|
||||
if ($this->curl_method == 'async') {
|
||||
$this->_curl_handler = new Raven_CurlHandler($this->get_curl_options());
|
||||
}
|
||||
}
|
||||
|
||||
public static function getDefaultProcessors()
|
||||
{
|
||||
return array(
|
||||
'Raven_SanitizeDataProcessor',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Raven_Processor sub-classes to be used when data is processed before being
|
||||
* sent to Sentry.
|
||||
*
|
||||
* @param $options
|
||||
* @return array
|
||||
*/
|
||||
public function setProcessorsFromOptions($options)
|
||||
{
|
||||
$processors = array();
|
||||
foreach (Raven_util::get($options, 'processors', self::getDefaultProcessors()) as $processor) {
|
||||
$new_processor = new $processor($this);
|
||||
|
||||
if (isset($options['processorOptions']) && is_array($options['processorOptions'])) {
|
||||
if (isset($options['processorOptions'][$processor]) && method_exists($processor, 'setProcessorOptions')) {
|
||||
$new_processor->setProcessorOptions($options['processorOptions'][$processor]);
|
||||
}
|
||||
}
|
||||
$processors[] = $new_processor;
|
||||
}
|
||||
return $processors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a Raven-compatible DSN and returns an array of its values.
|
||||
*
|
||||
* @param string $dsn Raven compatible DSN: http://raven.readthedocs.org/en/latest/config/#the-sentry-dsn
|
||||
* @return array parsed DSN
|
||||
*/
|
||||
public static function parseDSN($dsn)
|
||||
{
|
||||
$url = parse_url($dsn);
|
||||
$scheme = (isset($url['scheme']) ? $url['scheme'] : '');
|
||||
if (!in_array($scheme, array('http', 'https'))) {
|
||||
throw new InvalidArgumentException('Unsupported Sentry DSN scheme: ' . (!empty($scheme) ? $scheme : '<not set>'));
|
||||
}
|
||||
$netloc = (isset($url['host']) ? $url['host'] : null);
|
||||
$netloc.= (isset($url['port']) ? ':'.$url['port'] : null);
|
||||
$rawpath = (isset($url['path']) ? $url['path'] : null);
|
||||
if ($rawpath) {
|
||||
$pos = strrpos($rawpath, '/', 1);
|
||||
if ($pos !== false) {
|
||||
$path = substr($rawpath, 0, $pos);
|
||||
$project = substr($rawpath, $pos + 1);
|
||||
} else {
|
||||
$path = '';
|
||||
$project = substr($rawpath, 1);
|
||||
}
|
||||
} else {
|
||||
$project = null;
|
||||
$path = '';
|
||||
}
|
||||
$username = (isset($url['user']) ? $url['user'] : null);
|
||||
$password = (isset($url['pass']) ? $url['pass'] : null);
|
||||
if (empty($netloc) || empty($project) || empty($username) || empty($password)) {
|
||||
throw new InvalidArgumentException('Invalid Sentry DSN: ' . $dsn);
|
||||
}
|
||||
|
||||
return array(
|
||||
'server' => sprintf('%s://%s%s/api/%s/store/', $scheme, $netloc, $path, $project),
|
||||
'project' => $project,
|
||||
'public_key' => $username,
|
||||
'secret_key' => $password,
|
||||
);
|
||||
}
|
||||
|
||||
public function getLastError()
|
||||
{
|
||||
return $this->_lasterror;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an identifier, returns a Sentry searchable string.
|
||||
*/
|
||||
public function getIdent($ident)
|
||||
{
|
||||
// XXX: We don't calculate checksums yet, so we only have the ident.
|
||||
return $ident;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
*/
|
||||
public function message($message, $params=array(), $level=self::INFO,
|
||||
$stack=false, $vars = null)
|
||||
{
|
||||
return $this->captureMessage($message, $params, $level, $stack, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated
|
||||
*/
|
||||
public function exception($exception)
|
||||
{
|
||||
return $this->captureException($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to sentry
|
||||
*/
|
||||
public function captureMessage($message, $params=array(), $level_or_options=array(),
|
||||
$stack=false, $vars = null)
|
||||
{
|
||||
// Gracefully handle messages which contain formatting characters, but were not
|
||||
// intended to be used with formatting.
|
||||
if (!empty($params)) {
|
||||
$formatted_message = vsprintf($message, $params);
|
||||
} else {
|
||||
$formatted_message = $message;
|
||||
}
|
||||
|
||||
if ($level_or_options === null) {
|
||||
$data = array();
|
||||
} elseif (!is_array($level_or_options)) {
|
||||
$data = array(
|
||||
'level' => $level_or_options,
|
||||
);
|
||||
} else {
|
||||
$data = $level_or_options;
|
||||
}
|
||||
|
||||
$data['message'] = $formatted_message;
|
||||
$data['sentry.interfaces.Message'] = array(
|
||||
'message' => $message,
|
||||
'params' => $params,
|
||||
);
|
||||
|
||||
return $this->capture($data, $stack, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an exception to sentry
|
||||
*/
|
||||
public function captureException($exception, $culprit_or_options=null, $logger=null, $vars=null)
|
||||
{
|
||||
$has_chained_exceptions = version_compare(PHP_VERSION, '5.3.0', '>=');
|
||||
|
||||
if (in_array(get_class($exception), $this->exclude)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!is_array($culprit_or_options)) {
|
||||
$data = array();
|
||||
if ($culprit_or_options !== null) {
|
||||
$data['culprit'] = $culprit_or_options;
|
||||
}
|
||||
} else {
|
||||
$data = $culprit_or_options;
|
||||
}
|
||||
|
||||
// TODO(dcramer): DRY this up
|
||||
$message = $exception->getMessage();
|
||||
if (empty($message)) {
|
||||
$message = get_class($exception);
|
||||
}
|
||||
|
||||
$exc = $exception;
|
||||
do {
|
||||
$exc_data = array(
|
||||
'value' => $exc->getMessage(),
|
||||
'type' => get_class($exc),
|
||||
'module' => $exc->getFile() .':'. $exc->getLine(),
|
||||
);
|
||||
|
||||
/**'exception'
|
||||
* Exception::getTrace doesn't store the point at where the exception
|
||||
* was thrown, so we have to stuff it in ourselves. Ugh.
|
||||
*/
|
||||
$trace = $exc->getTrace();
|
||||
$frame_where_exception_thrown = array(
|
||||
'file' => $exc->getFile(),
|
||||
'line' => $exc->getLine(),
|
||||
);
|
||||
|
||||
array_unshift($trace, $frame_where_exception_thrown);
|
||||
|
||||
// manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
|
||||
if (!class_exists('Raven_Stacktrace')) {
|
||||
spl_autoload_call('Raven_Stacktrace');
|
||||
}
|
||||
|
||||
$exc_data['stacktrace'] = array(
|
||||
'frames' => Raven_Stacktrace::get_stack_info(
|
||||
$trace, $this->trace, $this->shift_vars, $vars, $this->message_limit, $this->prefixes,
|
||||
$this->app_path
|
||||
),
|
||||
);
|
||||
|
||||
$exceptions[] = $exc_data;
|
||||
} while ($has_chained_exceptions && $exc = $exc->getPrevious());
|
||||
|
||||
$data['message'] = $message;
|
||||
$data['exception'] = array(
|
||||
'values' => array_reverse($exceptions),
|
||||
);
|
||||
if ($logger !== null) {
|
||||
$data['logger'] = $logger;
|
||||
}
|
||||
|
||||
if (empty($data['level'])) {
|
||||
if (method_exists($exception, 'getSeverity')) {
|
||||
$data['level'] = $this->translateSeverity($exception->getSeverity());
|
||||
} else {
|
||||
$data['level'] = self::ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->capture($data, $trace, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an query to sentry
|
||||
*/
|
||||
public function captureQuery($query, $level=self::INFO, $engine = '')
|
||||
{
|
||||
$data = array(
|
||||
'message' => $query,
|
||||
'level' => $level,
|
||||
'sentry.interfaces.Query' => array(
|
||||
'query' => $query
|
||||
)
|
||||
);
|
||||
|
||||
if ($engine !== '') {
|
||||
$data['sentry.interfaces.Query']['engine'] = $engine;
|
||||
}
|
||||
return $this->capture($data, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the last captured event's ID or null if none available.
|
||||
*/
|
||||
public function getLastEventID()
|
||||
{
|
||||
return $this->_last_event_id;
|
||||
}
|
||||
|
||||
protected function is_http_request()
|
||||
{
|
||||
return isset($_SERVER['REQUEST_METHOD']) && PHP_SAPI !== 'cli';
|
||||
}
|
||||
|
||||
protected function get_http_data()
|
||||
{
|
||||
$env = $headers = array();
|
||||
|
||||
foreach ($_SERVER as $key => $value) {
|
||||
if (0 === strpos($key, 'HTTP_')) {
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($key, 5)))))] = $value;
|
||||
} elseif (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH')) && $value !== '') {
|
||||
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key))))] = $value;
|
||||
} else {
|
||||
$env[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'method' => $this->_server_variable('REQUEST_METHOD'),
|
||||
'url' => $this->get_current_url(),
|
||||
'query_string' => $this->_server_variable('QUERY_STRING'),
|
||||
);
|
||||
|
||||
// dont set this as an empty array as PHP will treat it as a numeric array
|
||||
// instead of a mapping which goes against the defined Sentry spec
|
||||
if (!empty($_POST)) {
|
||||
$result['data'] = $_POST;
|
||||
}
|
||||
if (!empty($_COOKIE)) {
|
||||
$result['cookies'] = $_COOKIE;
|
||||
}
|
||||
if (!empty($headers)) {
|
||||
$result['headers'] = $headers;
|
||||
}
|
||||
if (!empty($env)) {
|
||||
$result['env'] = $env;
|
||||
}
|
||||
|
||||
return array(
|
||||
'request' => $result,
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_user_data()
|
||||
{
|
||||
$user = $this->context->user;
|
||||
if ($user === null) {
|
||||
if (!session_id()) {
|
||||
return array();
|
||||
}
|
||||
$user = array(
|
||||
'id' => session_id(),
|
||||
);
|
||||
if (!empty($_SESSION)) {
|
||||
$user['data'] = $_SESSION;
|
||||
}
|
||||
}
|
||||
return array(
|
||||
'user' => $user,
|
||||
);
|
||||
}
|
||||
|
||||
protected function get_extra_data()
|
||||
{
|
||||
return $this->extra_data;
|
||||
}
|
||||
|
||||
public function get_default_data()
|
||||
{
|
||||
return array(
|
||||
'server_name' => $this->name,
|
||||
'project' => $this->project,
|
||||
'site' => $this->site,
|
||||
'logger' => $this->logger,
|
||||
'tags' => $this->tags,
|
||||
'platform' => 'php',
|
||||
'sdk' => $this->sdk,
|
||||
);
|
||||
}
|
||||
|
||||
public function capture($data, $stack = null, $vars = null)
|
||||
{
|
||||
if (!isset($data['timestamp'])) {
|
||||
$data['timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
|
||||
}
|
||||
if (!isset($data['level'])) {
|
||||
$data['level'] = self::ERROR;
|
||||
}
|
||||
if (!isset($data['tags'])) {
|
||||
$data['tags'] = array();
|
||||
}
|
||||
if (!isset($data['extra'])) {
|
||||
$data['extra'] = array();
|
||||
}
|
||||
if (!isset($data['event_id'])) {
|
||||
$data['event_id'] = $this->uuid4();
|
||||
}
|
||||
|
||||
if (isset($data['message'])) {
|
||||
$data['message'] = substr($data['message'], 0, $this->message_limit);
|
||||
}
|
||||
|
||||
$data = array_merge($this->get_default_data(), $data);
|
||||
|
||||
if ($this->is_http_request()) {
|
||||
$data = array_merge($this->get_http_data(), $data);
|
||||
}
|
||||
|
||||
$data = array_merge($this->get_user_data(), $data);
|
||||
|
||||
if ($this->release) {
|
||||
$data['release'] = $this->release;
|
||||
}
|
||||
if ($this->environment) {
|
||||
$data['environment'] = $this->environment;
|
||||
}
|
||||
|
||||
$data['tags'] = array_merge(
|
||||
$this->tags,
|
||||
$this->context->tags,
|
||||
$data['tags']);
|
||||
|
||||
$data['extra'] = array_merge(
|
||||
$this->get_extra_data(),
|
||||
$this->context->extra,
|
||||
$data['extra']);
|
||||
|
||||
if (empty($data['extra'])) {
|
||||
unset($data['extra']);
|
||||
} else {
|
||||
$data['extra'] = $data['extra'];
|
||||
}
|
||||
|
||||
if (empty($data['tags'])) {
|
||||
unset($data['tags']);
|
||||
} else {
|
||||
$data['tags'] = $data['tags'];
|
||||
}
|
||||
if (!empty($data['user'])) {
|
||||
$data['user'] = $data['user'];
|
||||
}
|
||||
if (!empty($data['request'])) {
|
||||
$data['request'] = $data['request'];
|
||||
}
|
||||
|
||||
if (!$this->breadcrumbs->is_empty()) {
|
||||
$data['breadcrumbs'] = $this->breadcrumbs->fetch();
|
||||
}
|
||||
|
||||
if ((!$stack && $this->auto_log_stacks) || $stack === true) {
|
||||
$stack = debug_backtrace();
|
||||
|
||||
// Drop last stack
|
||||
array_shift($stack);
|
||||
}
|
||||
|
||||
if (!empty($stack)) {
|
||||
// manually trigger autoloading, as it's not done in some edge cases due to PHP bugs (see #60149)
|
||||
if (!class_exists('Raven_Stacktrace')) {
|
||||
spl_autoload_call('Raven_Stacktrace');
|
||||
}
|
||||
|
||||
if (!isset($data['stacktrace']) && !isset($data['exception'])) {
|
||||
$data['stacktrace'] = array(
|
||||
'frames' => Raven_Stacktrace::get_stack_info(
|
||||
$stack, $this->trace, $this->shift_vars, $vars, $this->message_limit,
|
||||
$this->prefixes, $this->app_path
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->sanitize($data);
|
||||
$this->process($data);
|
||||
|
||||
if (!$this->store_errors_for_bulk_send) {
|
||||
$this->send($data);
|
||||
} else {
|
||||
if (empty($this->error_data)) {
|
||||
$this->error_data = array();
|
||||
}
|
||||
$this->error_data[] = $data;
|
||||
}
|
||||
|
||||
$this->_last_event_id = $data['event_id'];
|
||||
|
||||
return $data['event_id'];
|
||||
}
|
||||
|
||||
public function sanitize(&$data)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Process data through all defined Raven_Processor sub-classes
|
||||
*
|
||||
* @param array $data Associative array of data to log
|
||||
*/
|
||||
public function process(&$data)
|
||||
{
|
||||
foreach ($this->processors as $processor) {
|
||||
$processor->process($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function sendUnsentErrors()
|
||||
{
|
||||
if (!empty($this->error_data)) {
|
||||
foreach ($this->error_data as $data) {
|
||||
$this->send($data);
|
||||
}
|
||||
unset($this->error_data);
|
||||
}
|
||||
if ($this->store_errors_for_bulk_send) {
|
||||
//in case an error occurs after this is called, on shutdown, send any new errors.
|
||||
$this->store_errors_for_bulk_send = !defined('RAVEN_CLIENT_END_REACHED');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper to handle encoding and sending data to the Sentry API server.
|
||||
*
|
||||
* @param array $data Associative array of data to log
|
||||
*/
|
||||
public function send($data)
|
||||
{
|
||||
if (is_callable($this->send_callback) && !call_user_func($this->send_callback, $data)) {
|
||||
// if send_callback returns falsely, end native send
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->server) {
|
||||
return;
|
||||
}
|
||||
|
||||
$message = Raven_Compat::json_encode($data);
|
||||
|
||||
if (function_exists("gzcompress")) {
|
||||
$message = gzcompress($message);
|
||||
}
|
||||
$message = base64_encode($message); // PHP's builtin curl_* function are happy without this, but the exec method requires it
|
||||
|
||||
$client_string = 'sentry-php/' . self::VERSION;
|
||||
$timestamp = microtime(true);
|
||||
$headers = array(
|
||||
'User-Agent' => $client_string,
|
||||
'X-Sentry-Auth' => $this->get_auth_header(
|
||||
$timestamp, $client_string, $this->public_key,
|
||||
$this->secret_key),
|
||||
'Content-Type' => 'application/octet-stream'
|
||||
);
|
||||
|
||||
$this->send_remote($this->server, $message, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to Sentry
|
||||
*
|
||||
* @param string $url Full URL to Sentry
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
*/
|
||||
private function send_remote($url, $data, $headers=array())
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
$parts['netloc'] = $parts['host'].(isset($parts['port']) ? ':'.$parts['port'] : null);
|
||||
$this->send_http($url, $data, $headers);
|
||||
}
|
||||
|
||||
protected function get_default_ca_cert()
|
||||
{
|
||||
return dirname(__FILE__) . DIRECTORY_SEPARATOR . 'data' . DIRECTORY_SEPARATOR . 'cacert.pem';
|
||||
}
|
||||
|
||||
protected function get_curl_options()
|
||||
{
|
||||
$options = array(
|
||||
CURLOPT_VERBOSE => false,
|
||||
CURLOPT_SSL_VERIFYHOST => 2,
|
||||
CURLOPT_SSL_VERIFYPEER => $this->verify_ssl,
|
||||
CURLOPT_CAINFO => $this->ca_cert,
|
||||
CURLOPT_USERAGENT => 'sentry-php/' . self::VERSION,
|
||||
);
|
||||
if ($this->http_proxy) {
|
||||
$options[CURLOPT_PROXY] = $this->http_proxy;
|
||||
}
|
||||
if ($this->curl_ssl_version) {
|
||||
$options[CURLOPT_SSLVERSION] = $this->curl_ssl_version;
|
||||
}
|
||||
if ($this->curl_ipv4) {
|
||||
$options[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
|
||||
}
|
||||
if (defined('CURLOPT_TIMEOUT_MS')) {
|
||||
// MS is available in curl >= 7.16.2
|
||||
$timeout = max(1, ceil(1000 * $this->timeout));
|
||||
|
||||
// some versions of PHP 5.3 don't have this defined correctly
|
||||
if (!defined('CURLOPT_CONNECTTIMEOUT_MS')) {
|
||||
//see http://stackoverflow.com/questions/9062798/php-curl-timeout-is-not-working/9063006#9063006
|
||||
define('CURLOPT_CONNECTTIMEOUT_MS', 156);
|
||||
}
|
||||
|
||||
$options[CURLOPT_CONNECTTIMEOUT_MS] = $timeout;
|
||||
$options[CURLOPT_TIMEOUT_MS] = $timeout;
|
||||
} else {
|
||||
// fall back to the lower-precision timeout.
|
||||
$timeout = max(1, ceil($this->timeout));
|
||||
$options[CURLOPT_CONNECTTIMEOUT] = $timeout;
|
||||
$options[CURLOPT_TIMEOUT] = $timeout;
|
||||
}
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the message over http to the sentry url given
|
||||
*
|
||||
* @param string $url URL of the Sentry instance to log to
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
*/
|
||||
private function send_http($url, $data, $headers=array())
|
||||
{
|
||||
if ($this->curl_method == 'async') {
|
||||
$this->_curl_handler->enqueue($url, $data, $headers);
|
||||
} elseif ($this->curl_method == 'exec') {
|
||||
$this->send_http_asynchronous_curl_exec($url, $data, $headers);
|
||||
} else {
|
||||
$this->send_http_synchronous($url, $data, $headers);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the cURL to Sentry asynchronously. No errors will be returned from cURL
|
||||
*
|
||||
* @param string $url URL of the Sentry instance to log to
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
* @return bool
|
||||
*/
|
||||
private function send_http_asynchronous_curl_exec($url, $data, $headers)
|
||||
{
|
||||
// TODO(dcramer): support ca_cert
|
||||
$cmd = $this->curl_path.' -X POST ';
|
||||
foreach ($headers as $key => $value) {
|
||||
$cmd .= '-H \''. $key. ': '. $value. '\' ';
|
||||
}
|
||||
$cmd .= '-d \''. $data .'\' ';
|
||||
$cmd .= '\''. $url .'\' ';
|
||||
$cmd .= '-m 5 '; // 5 second timeout for the whole process (connect + send)
|
||||
if (!$this->verify_ssl) {
|
||||
$cmd .= '-k ';
|
||||
}
|
||||
$cmd .= '> /dev/null 2>&1 &'; // ensure exec returns immediately while curl runs in the background
|
||||
|
||||
exec($cmd);
|
||||
|
||||
return true; // The exec method is just fire and forget, so just assume it always works
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a blocking cURL to Sentry and check for errors from cURL
|
||||
*
|
||||
* @param string $url URL of the Sentry instance to log to
|
||||
* @param array $data Associative array of data to log
|
||||
* @param array $headers Associative array of headers
|
||||
* @return bool
|
||||
*/
|
||||
private function send_http_synchronous($url, $data, $headers)
|
||||
{
|
||||
$new_headers = array();
|
||||
foreach ($headers as $key => $value) {
|
||||
array_push($new_headers, $key .': '. $value);
|
||||
}
|
||||
// XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216)
|
||||
$new_headers[] = 'Expect:';
|
||||
|
||||
$curl = curl_init($url);
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER, $new_headers);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$options = $this->get_curl_options();
|
||||
$ca_cert = $options[CURLOPT_CAINFO];
|
||||
unset($options[CURLOPT_CAINFO]);
|
||||
curl_setopt_array($curl, $options);
|
||||
|
||||
curl_exec($curl);
|
||||
|
||||
$errno = curl_errno($curl);
|
||||
// CURLE_SSL_CACERT || CURLE_SSL_CACERT_BADFILE
|
||||
if ($errno == 60 || $errno == 77) {
|
||||
curl_setopt($curl, CURLOPT_CAINFO, $ca_cert);
|
||||
curl_exec($curl);
|
||||
}
|
||||
|
||||
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
|
||||
$success = ($code == 200);
|
||||
if (!$success) {
|
||||
// It'd be nice just to raise an exception here, but it's not very PHP-like
|
||||
$this->_lasterror = curl_error($curl);
|
||||
} else {
|
||||
$this->_lasterror = null;
|
||||
}
|
||||
curl_close($curl);
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a Sentry authorization header string
|
||||
*
|
||||
* @param string $timestamp Timestamp when the event occurred
|
||||
* @param string $client HTTP client name (not Raven_Client object)
|
||||
* @param string $api_key Sentry API key
|
||||
* @param string $secret_key Sentry API key
|
||||
* @return string
|
||||
*/
|
||||
protected function get_auth_header($timestamp, $client, $api_key, $secret_key)
|
||||
{
|
||||
$header = array(
|
||||
sprintf('sentry_timestamp=%F', $timestamp),
|
||||
"sentry_client={$client}",
|
||||
sprintf('sentry_version=%s', self::PROTOCOL),
|
||||
);
|
||||
|
||||
if ($api_key) {
|
||||
$header[] = "sentry_key={$api_key}";
|
||||
}
|
||||
|
||||
if ($secret_key) {
|
||||
$header[] = "sentry_secret={$secret_key}";
|
||||
}
|
||||
|
||||
|
||||
return sprintf('Sentry %s', implode(', ', $header));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an uuid4 value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function uuid4()
|
||||
{
|
||||
$uuid = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
// 32 bits for "time_low"
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||
|
||||
// 16 bits for "time_mid"
|
||||
mt_rand(0, 0xffff),
|
||||
|
||||
// 16 bits for "time_hi_and_version",
|
||||
// four most significant bits holds version number 4
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
|
||||
// 16 bits, 8 bits for "clk_seq_hi_res",
|
||||
// 8 bits for "clk_seq_low",
|
||||
// two most significant bits holds zero and one for variant DCE1.1
|
||||
mt_rand(0, 0x3fff) | 0x8000,
|
||||
|
||||
// 48 bits for "node"
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||
);
|
||||
|
||||
return str_replace('-', '', $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL for the current request
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
protected function get_current_url()
|
||||
{
|
||||
// When running from commandline the REQUEST_URI is missing.
|
||||
if (!isset($_SERVER['REQUEST_URI'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// HTTP_HOST is a client-supplied header that is optional in HTTP 1.0
|
||||
$host = (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST']
|
||||
: (!empty($_SERVER['LOCAL_ADDR']) ? $_SERVER['LOCAL_ADDR']
|
||||
: (!empty($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '')));
|
||||
|
||||
$httpS = $this->isHttps() ? 's' : '';
|
||||
return "http{$httpS}://{$host}{$_SERVER['REQUEST_URI']}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Was the current request made over https?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isHttps()
|
||||
{
|
||||
if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!empty($this->trust_x_forwarded_proto) &&
|
||||
!empty($_SERVER['X-FORWARDED-PROTO']) &&
|
||||
$_SERVER['X-FORWARDED-PROTO'] === 'https') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a key from $_SERVER
|
||||
*
|
||||
* @param string $key Key whose value you wish to obtain
|
||||
* @return string Key's value
|
||||
*/
|
||||
private function _server_variable($key)
|
||||
{
|
||||
if (isset($_SERVER[$key])) {
|
||||
return $_SERVER[$key];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate a PHP Error constant into a Sentry log level group
|
||||
*
|
||||
* @param string $severity PHP E_$x error constant
|
||||
* @return string Sentry log level group
|
||||
*/
|
||||
public function translateSeverity($severity)
|
||||
{
|
||||
if (is_array($this->severity_map) && isset($this->severity_map[$severity])) {
|
||||
return $this->severity_map[$severity];
|
||||
}
|
||||
switch ($severity) {
|
||||
case E_ERROR: return Raven_Client::ERROR;
|
||||
case E_WARNING: return Raven_Client::WARN;
|
||||
case E_PARSE: return Raven_Client::ERROR;
|
||||
case E_NOTICE: return Raven_Client::INFO;
|
||||
case E_CORE_ERROR: return Raven_Client::ERROR;
|
||||
case E_CORE_WARNING: return Raven_Client::WARN;
|
||||
case E_COMPILE_ERROR: return Raven_Client::ERROR;
|
||||
case E_COMPILE_WARNING: return Raven_Client::WARN;
|
||||
case E_USER_ERROR: return Raven_Client::ERROR;
|
||||
case E_USER_WARNING: return Raven_Client::WARN;
|
||||
case E_USER_NOTICE: return Raven_Client::INFO;
|
||||
case E_STRICT: return Raven_Client::INFO;
|
||||
case E_RECOVERABLE_ERROR: return Raven_Client::ERROR;
|
||||
}
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
|
||||
switch ($severity) {
|
||||
case E_DEPRECATED: return Raven_Client::WARN;
|
||||
case E_USER_DEPRECATED: return Raven_Client::WARN;
|
||||
}
|
||||
}
|
||||
return Raven_Client::ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a map of PHP Error constants to Sentry logging groups to use instead
|
||||
* of the defaults in translateSeverity()
|
||||
*
|
||||
* @param array $map
|
||||
*/
|
||||
public function registerSeverityMap($map)
|
||||
{
|
||||
$this->severity_map = $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for setting a user's ID and Email
|
||||
*
|
||||
* @param string $id User's ID
|
||||
* @param string|null $email User's email
|
||||
* @param array $data Additional user data
|
||||
*/
|
||||
public function set_user_data($id, $email=null, $data=array())
|
||||
{
|
||||
$user = array('id' => $id);
|
||||
if (isset($email)) {
|
||||
$user['email'] = $email;
|
||||
}
|
||||
$this->user_context(array_merge($user, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets user context.
|
||||
*
|
||||
* @param array $data Associative array of user data
|
||||
*/
|
||||
public function user_context($data)
|
||||
{
|
||||
$this->context->user = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends tags context.
|
||||
*
|
||||
* @param array $data Associative array of tags
|
||||
*/
|
||||
public function tags_context($data)
|
||||
{
|
||||
$this->context->tags = array_merge($this->context->tags, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends additional context.
|
||||
*
|
||||
* @param array $data Associative array of extra data
|
||||
*/
|
||||
public function extra_context($data)
|
||||
{
|
||||
$this->context->extra = array_merge($this->context->extra, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $processors
|
||||
*/
|
||||
public function setProcessors(array $processors)
|
||||
{
|
||||
$this->processors = $processors;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Compat
|
||||
{
|
||||
public static function gethostname()
|
||||
{
|
||||
if (function_exists('gethostname')) {
|
||||
return gethostname();
|
||||
}
|
||||
|
||||
return self::_gethostname();
|
||||
}
|
||||
|
||||
public static function _gethostname()
|
||||
{
|
||||
return php_uname('n');
|
||||
}
|
||||
|
||||
public static function hash_hmac($algo, $data, $key, $raw_output=false)
|
||||
{
|
||||
if (function_exists('hash_hmac')) {
|
||||
return hash_hmac($algo, $data, $key, $raw_output);
|
||||
}
|
||||
|
||||
return self::_hash_hmac($algo, $data, $key, $raw_output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation from 'KC Cloyd'.
|
||||
* See http://nl2.php.net/manual/en/function.hash-hmac.php
|
||||
*/
|
||||
public static function _hash_hmac($algo, $data, $key, $raw_output=false)
|
||||
{
|
||||
$algo = strtolower($algo);
|
||||
$pack = 'H'.strlen($algo('test'));
|
||||
$size = 64;
|
||||
$opad = str_repeat(chr(0x5C), $size);
|
||||
$ipad = str_repeat(chr(0x36), $size);
|
||||
|
||||
if (strlen($key) > $size) {
|
||||
$key = str_pad(pack($pack, $algo($key)), $size, chr(0x00));
|
||||
} else {
|
||||
$key = str_pad($key, $size, chr(0x00));
|
||||
}
|
||||
|
||||
$keyLastPos = strlen($key) - 1;
|
||||
for ($i = 0; $i < $keyLastPos; $i++) {
|
||||
$opad[$i] = $opad[$i] ^ $key[$i];
|
||||
$ipad[$i] = $ipad[$i] ^ $key[$i];
|
||||
}
|
||||
|
||||
$output = $algo($opad.pack($pack, $algo($ipad.$data)));
|
||||
|
||||
return ($raw_output) ? pack($pack, $output) : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note that we discard the options given to be compatible
|
||||
* with PHP < 5.3
|
||||
*/
|
||||
public static function json_encode($value, $options=0)
|
||||
{
|
||||
if (function_exists('json_encode')) {
|
||||
return json_encode($value);
|
||||
}
|
||||
|
||||
return self::_json_encode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation taken from
|
||||
* http://www.mike-griffiths.co.uk/php-json_encode-alternative/
|
||||
*/
|
||||
public static function _json_encode($value)
|
||||
{
|
||||
static $jsonReplaces = array(
|
||||
array('\\', '/', "\n", "\t", "\r", "\b", "\f", '"'),
|
||||
array('\\\\', '\\/', '\\n', '\\t', '\\r', '\\b', '\\f', '\"'));
|
||||
|
||||
if (is_null($value)) {
|
||||
return 'null';
|
||||
}
|
||||
if ($value === false) {
|
||||
return 'false';
|
||||
}
|
||||
if ($value === true) {
|
||||
return 'true';
|
||||
}
|
||||
|
||||
if (is_scalar($value)) {
|
||||
|
||||
// Always use '.' for floats.
|
||||
if (is_float($value)) {
|
||||
return floatval(str_replace(',', '.', strval($value)));
|
||||
}
|
||||
if (is_string($value)) {
|
||||
return sprintf('"%s"',
|
||||
str_replace($jsonReplaces[0], $jsonReplaces[1], $value));
|
||||
} else {
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
$isList = true;
|
||||
for ($i = 0, reset($value); $i<count($value); $i++, next($value)) {
|
||||
if (key($value) !== $i) {
|
||||
$isList = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$result = array();
|
||||
if ($isList) {
|
||||
foreach ($value as $v) {
|
||||
$result[] = self::_json_encode($v);
|
||||
}
|
||||
|
||||
return '[' . join(',', $result) . ']';
|
||||
} else {
|
||||
foreach ($value as $k => $v) {
|
||||
$result[] = self::_json_encode($k) . ':' . self::_json_encode($v);
|
||||
}
|
||||
|
||||
return '{' . join(',', $result) . '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Storage for additional client context.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Context
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up existing context.
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->tags = array();
|
||||
$this->extra = array();
|
||||
$this->user = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Asynchronous Curl connection manager.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
// TODO(dcramer): handle ca_cert
|
||||
class Raven_CurlHandler
|
||||
{
|
||||
private $join_timeout;
|
||||
private $multi_handle;
|
||||
private $options;
|
||||
private $requests;
|
||||
|
||||
public function __construct($options, $join_timeout=5)
|
||||
{
|
||||
$this->options = $options;
|
||||
$this->multi_handle = curl_multi_init();
|
||||
$this->requests = array();
|
||||
$this->join_timeout = 5;
|
||||
|
||||
register_shutdown_function(array($this, 'join'));
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->join();
|
||||
}
|
||||
|
||||
public function enqueue($url, $data=null, $headers=array())
|
||||
{
|
||||
$ch = curl_init();
|
||||
|
||||
$new_headers = array();
|
||||
foreach ($headers as $key => $value) {
|
||||
array_push($new_headers, $key .': '. $value);
|
||||
}
|
||||
// XXX(dcramer): Prevent 100-continue response form server (Fixes GH-216)
|
||||
$new_headers[] = 'Expect:';
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $new_headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
curl_setopt_array($ch, $this->options);
|
||||
|
||||
if (isset($data)) {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
|
||||
}
|
||||
|
||||
curl_multi_add_handle($this->multi_handle, $ch);
|
||||
|
||||
$fd = (int)$ch;
|
||||
$this->requests[$fd] = 1;
|
||||
|
||||
$this->select();
|
||||
|
||||
return $fd;
|
||||
}
|
||||
|
||||
public function join($timeout=null)
|
||||
{
|
||||
if (!isset($timeout)) {
|
||||
$timeout = $this->join_timeout;
|
||||
}
|
||||
$start = time();
|
||||
do {
|
||||
$this->select();
|
||||
if (count($this->requests) === 0) {
|
||||
break;
|
||||
}
|
||||
usleep(10000);
|
||||
} while ($timeout !== 0 && time() - $start < $timeout);
|
||||
}
|
||||
|
||||
// http://se2.php.net/manual/en/function.curl-multi-exec.php
|
||||
private function select()
|
||||
{
|
||||
do {
|
||||
$mrc = curl_multi_exec($this->multi_handle, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
|
||||
while ($active && $mrc == CURLM_OK) {
|
||||
if (curl_multi_select($this->multi_handle) !== -1) {
|
||||
do {
|
||||
$mrc = curl_multi_exec($this->multi_handle, $active);
|
||||
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while ($info = curl_multi_info_read($this->multi_handle)) {
|
||||
$ch = $info['handle'];
|
||||
$fd = (int)$ch;
|
||||
|
||||
curl_multi_remove_handle($this->multi_handle, $ch);
|
||||
|
||||
if (!isset($this->requests[$fd])) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->requests[$fd]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event handlers for exceptions and errors
|
||||
*
|
||||
* $client = new Raven_Client('http://public:secret/example.com/1');
|
||||
* $error_handler = new Raven_ErrorHandler($client);
|
||||
* $error_handler->registerExceptionHandler();
|
||||
* $error_handler->registerErrorHandler();
|
||||
* $error_handler->registerShutdownFunction();
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
// TODO(dcramer): deprecate default error types in favor of runtime configuration
|
||||
// unless a reason can be determined that making them dynamic is better. They
|
||||
// currently are not used outside of the fatal handler.
|
||||
class Raven_ErrorHandler
|
||||
{
|
||||
private $old_exception_handler;
|
||||
private $call_existing_exception_handler = false;
|
||||
private $old_error_handler;
|
||||
private $call_existing_error_handler = false;
|
||||
private $reservedMemory;
|
||||
private $send_errors_last = false;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* Error types which should be processed by the handler.
|
||||
* A 'null' value implies "whatever error_reporting is at time of error".
|
||||
*/
|
||||
private $error_types = null;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @var array
|
||||
* Error types that can be processed by the handler
|
||||
*/
|
||||
private $validErrorTypes = array(
|
||||
E_ERROR,
|
||||
E_WARNING,
|
||||
E_PARSE,
|
||||
E_NOTICE,
|
||||
E_CORE_ERROR,
|
||||
E_CORE_WARNING,
|
||||
E_COMPILE_ERROR,
|
||||
E_COMPILE_WARNING,
|
||||
E_USER_ERROR,
|
||||
E_USER_WARNING,
|
||||
E_USER_NOTICE,
|
||||
E_STRICT,
|
||||
E_RECOVERABLE_ERROR,
|
||||
E_DEPRECATED,
|
||||
E_USER_DEPRECATED,
|
||||
);
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @var array
|
||||
* The default Error types that are always processed by the handler. Can be set during construction.
|
||||
*/
|
||||
private $defaultErrorTypes = array(
|
||||
E_ERROR,
|
||||
E_PARSE,
|
||||
E_CORE_ERROR,
|
||||
E_CORE_WARNING,
|
||||
E_COMPILE_ERROR,
|
||||
E_COMPILE_WARNING,
|
||||
E_STRICT,
|
||||
);
|
||||
|
||||
public function __construct($client, $send_errors_last = false, $default_error_types = null,
|
||||
$error_types = null)
|
||||
{
|
||||
$this->client = $client;
|
||||
if ($default_error_types !== null) {
|
||||
$this->defaultErrorTypes = $default_error_types;
|
||||
}
|
||||
$this->error_types = $error_types;
|
||||
register_shutdown_function(array($this, 'detectShutdown'));
|
||||
if ($send_errors_last) {
|
||||
$this->send_errors_last = true;
|
||||
$this->client->store_errors_for_bulk_send = true;
|
||||
register_shutdown_function(array($this->client, 'sendUnsentErrors'));
|
||||
}
|
||||
}
|
||||
|
||||
public function handleException($e, $isError = false, $vars = null)
|
||||
{
|
||||
$e->event_id = $this->client->getIdent($this->client->captureException($e, null, null, $vars));
|
||||
|
||||
if (!$isError && $this->call_existing_exception_handler && $this->old_exception_handler) {
|
||||
call_user_func($this->old_exception_handler, $e);
|
||||
}
|
||||
}
|
||||
|
||||
public function handleError($code, $message, $file = '', $line = 0, $context=array())
|
||||
{
|
||||
if (error_reporting() !== 0) {
|
||||
$error_types = $this->error_types;
|
||||
if ($error_types === null) {
|
||||
$error_types = error_reporting();
|
||||
}
|
||||
if ($error_types & $code) {
|
||||
$e = new ErrorException($message, 0, $code, $file, $line);
|
||||
$this->handleException($e, true, $context);
|
||||
}
|
||||
}
|
||||
if ($this->call_existing_error_handler) {
|
||||
if ($this->old_error_handler !== null) {
|
||||
return call_user_func($this->old_error_handler, $code, $message, $file, $line, $context);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nothing by default, use it in child classes for catching other types of errors
|
||||
* Only constants from $this->validErrorTypes can be used
|
||||
*
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
|
||||
protected function getAdditionalErrorTypesToProcess()
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @return array
|
||||
*/
|
||||
private function getErrorTypesToProcess()
|
||||
{
|
||||
$additionalErrorTypes = array_intersect($this->getAdditionalErrorTypesToProcess(), $this->validErrorTypes);
|
||||
// array_unique so bitwise "or" operation wouldn't fail if some error type gets repeated
|
||||
return array_unique(array_merge($this->defaultErrorTypes, $additionalErrorTypes));
|
||||
}
|
||||
|
||||
public function handleFatalError()
|
||||
{
|
||||
if (null === $lastError = error_get_last()) {
|
||||
return;
|
||||
}
|
||||
|
||||
unset($this->reservedMemory);
|
||||
|
||||
$errors = 0;
|
||||
foreach ($this->getErrorTypesToProcess() as $errorType) {
|
||||
$errors |= $errorType;
|
||||
}
|
||||
|
||||
if ($lastError['type'] & $errors) {
|
||||
$e = new ErrorException(
|
||||
@$lastError['message'], @$lastError['type'], @$lastError['type'],
|
||||
@$lastError['file'], @$lastError['line']
|
||||
);
|
||||
$this->handleException($e, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function registerExceptionHandler($call_existing_exception_handler = true)
|
||||
{
|
||||
$this->old_exception_handler = set_exception_handler(array($this, 'handleException'));
|
||||
$this->call_existing_exception_handler = $call_existing_exception_handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler which will intercept standard PHP errors and report them to the
|
||||
* associated Sentry client.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
//
|
||||
public function registerErrorHandler($call_existing_error_handler = true, $error_types = null)
|
||||
{
|
||||
if ($error_types !== null) {
|
||||
$this->error_types = $error_types;
|
||||
}
|
||||
$this->old_error_handler = set_error_handler(array($this, 'handleError'), E_ALL);
|
||||
$this->call_existing_error_handler = $call_existing_error_handler;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function registerShutdownFunction($reservedMemorySize = 10)
|
||||
{
|
||||
register_shutdown_function(array($this, 'handleFatalError'));
|
||||
|
||||
$this->reservedMemory = str_repeat('x', 1024 * $reservedMemorySize);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function detectShutdown()
|
||||
{
|
||||
if (!defined('RAVEN_CLIENT_END_REACHED')) {
|
||||
define('RAVEN_CLIENT_END_REACHED', true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Base class for data processing.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
abstract class Raven_Processor
|
||||
{
|
||||
public function __construct(Raven_Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process and sanitize data, modifying the existing value if necessary.
|
||||
*
|
||||
* @param array $data Array of log data
|
||||
*/
|
||||
abstract public function process(&$data);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* Asterisk out passwords from password fields in frames, http,
|
||||
* and basic extra data.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_SanitizeDataProcessor extends Raven_Processor
|
||||
{
|
||||
const MASK = '********';
|
||||
const FIELDS_RE = '/(authorization|password|passwd|secret|password_confirmation|card_number|auth_pw)/i';
|
||||
const VALUES_RE = '/^(?:\d[ -]*?){13,16}$/';
|
||||
|
||||
private $client;
|
||||
private $fields_re;
|
||||
private $values_re;
|
||||
|
||||
public function __construct(Raven_Client $client)
|
||||
{
|
||||
$this->client = $client;
|
||||
$this->fields_re = self::FIELDS_RE;
|
||||
$this->values_re = self::VALUES_RE;
|
||||
$this->session_cookie_name = ini_get('session.name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the default processor options
|
||||
*
|
||||
* @param array $options Associative array of processor options
|
||||
*/
|
||||
public function setProcessorOptions(array $options)
|
||||
{
|
||||
if (isset($options['fields_re'])) {
|
||||
$this->fields_re = $options['fields_re'];
|
||||
}
|
||||
|
||||
if (isset($options['values_re'])) {
|
||||
$this->values_re = $options['values_re'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace any array values with our mask if the field name or the value matches a respective regex
|
||||
*
|
||||
* @param mixed $item Associative array value
|
||||
* @param string $key Associative array key
|
||||
*/
|
||||
public function sanitize(&$item, $key)
|
||||
{
|
||||
if (empty($item)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match($this->values_re, $item)) {
|
||||
$item = self::MASK;
|
||||
}
|
||||
|
||||
if (empty($key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (preg_match($this->fields_re, $key)) {
|
||||
$item = self::MASK;
|
||||
}
|
||||
}
|
||||
|
||||
public function sanitizeHttp(&$data)
|
||||
{
|
||||
if (empty($data['request'])) {
|
||||
return;
|
||||
}
|
||||
$http = &$data['request'];
|
||||
if (empty($http['cookies'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cookies = &$http['cookies'];
|
||||
if (!empty($cookies[$this->session_cookie_name])) {
|
||||
$cookies[$this->session_cookie_name] = self::MASK;
|
||||
}
|
||||
}
|
||||
|
||||
public function process(&$data)
|
||||
{
|
||||
array_walk_recursive($data, array($this, 'sanitize'));
|
||||
$this->sanitizeHttp($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFieldsRe()
|
||||
{
|
||||
return $this->fields_re;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $fields_re
|
||||
*/
|
||||
public function setFieldsRe($fields_re)
|
||||
{
|
||||
$this->fields_re = $fields_re;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getValuesRe()
|
||||
{
|
||||
return $this->values_re;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $values_re
|
||||
*/
|
||||
public function setValuesRe($values_re)
|
||||
{
|
||||
$this->values_re = $values_re;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2012 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This helper is based on code from Facebook's Phabricator project
|
||||
*
|
||||
* https://github.com/facebook/phabricator
|
||||
*
|
||||
* Specifically, it is an adaptation of the PhutilReadableSerializer class.
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Serializer
|
||||
{
|
||||
/**
|
||||
* Serialize an object (recursively) into something safe for data
|
||||
* sanitization and encoding.
|
||||
*/
|
||||
public function serialize($value, $max_depth=3, $_depth=0)
|
||||
{
|
||||
if (is_object($value) || is_resource($value)) {
|
||||
return $this->serializeValue($value);
|
||||
} elseif ($_depth < $max_depth && is_array($value)) {
|
||||
$new = array();
|
||||
foreach ($value as $k => $v) {
|
||||
$new[$this->serializeValue($k)] = $this->serialize($v, $max_depth, $_depth + 1);
|
||||
}
|
||||
|
||||
return $new;
|
||||
} else {
|
||||
return $this->serializeValue($value);
|
||||
}
|
||||
}
|
||||
|
||||
protected function serializeValue($value)
|
||||
{
|
||||
if (is_null($value) || is_bool($value) || is_float($value) || is_integer($value)) {
|
||||
return $value;
|
||||
} elseif (is_object($value) || gettype($value) == 'object') {
|
||||
return 'Object '.get_class($value);
|
||||
} elseif (is_resource($value)) {
|
||||
return 'Resource '.get_resource_type($value);
|
||||
} elseif (is_array($value)) {
|
||||
return 'Array of length ' . count($value);
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
|
||||
if (function_exists('mb_convert_encoding')) {
|
||||
$value = mb_convert_encoding($value, 'UTF-8', 'auto');
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
/**
|
||||
* Small helper class to inspect the stacktrace
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
class Raven_Stacktrace
|
||||
{
|
||||
public static $statements = array(
|
||||
'include',
|
||||
'include_once',
|
||||
'require',
|
||||
'require_once',
|
||||
);
|
||||
|
||||
public static function get_stack_info($frames, $trace = false, $shiftvars = true, $errcontext = null,
|
||||
$frame_var_limit = Raven_Client::MESSAGE_LIMIT, $strip_prefixes = null,
|
||||
$app_path = null)
|
||||
{
|
||||
/**
|
||||
* PHP's way of storing backstacks seems bass-ackwards to me
|
||||
* 'function' is not the function you're in; it's any function being
|
||||
* called, so we have to shift 'function' down by 1. Ugh.
|
||||
*/
|
||||
$result = array();
|
||||
for ($i = 0; $i < count($frames); $i++) {
|
||||
$frame = $frames[$i];
|
||||
$nextframe = isset($frames[$i + 1]) ? $frames[$i + 1] : null;
|
||||
|
||||
if (!array_key_exists('file', $frame)) {
|
||||
// XXX: Disable capturing of anonymous functions until we can implement a better grouping mechanism.
|
||||
// In our examples these generally didn't help with debugging as the information was found elsewhere
|
||||
// within the exception or the stacktrace
|
||||
continue;
|
||||
// if (isset($frame['args'])) {
|
||||
// $args = is_string($frame['args']) ? $frame['args'] : @json_encode($frame['args']);
|
||||
// }
|
||||
// else {
|
||||
// $args = array();
|
||||
// }
|
||||
// if (!empty($nextframe['class'])) {
|
||||
// $context['line'] = sprintf('%s%s%s(%s)',
|
||||
// $nextframe['class'], $nextframe['type'], $nextframe['function'],
|
||||
// $args);
|
||||
// }
|
||||
// else {
|
||||
// $context['line'] = sprintf('%s(%s)', $nextframe['function'], $args);
|
||||
// }
|
||||
// $abs_path = '';
|
||||
// $context['prefix'] = '';
|
||||
// $context['suffix'] = '';
|
||||
// $context['filename'] = $filename = '[Anonymous function]';
|
||||
// $context['lineno'] = 0;
|
||||
} else {
|
||||
$context = self::read_source_file($frame['file'], $frame['line']);
|
||||
$abs_path = $frame['file'];
|
||||
}
|
||||
|
||||
// strip base path if present
|
||||
$context['filename'] = self::strip_prefixes($context['filename'], $strip_prefixes);
|
||||
|
||||
$module = basename($abs_path);
|
||||
if (isset($nextframe['class'])) {
|
||||
$module .= ':' . $nextframe['class'];
|
||||
}
|
||||
|
||||
if (empty($result) && isset($errcontext)) {
|
||||
// If we've been given an error context that can be used as the vars for the first frame.
|
||||
$vars = $errcontext;
|
||||
} else {
|
||||
if ($trace) {
|
||||
if ($shiftvars) {
|
||||
$vars = self::get_frame_context($nextframe, $frame_var_limit);
|
||||
} else {
|
||||
$vars = self::get_caller_frame_context($frame);
|
||||
}
|
||||
} else {
|
||||
$vars = array();
|
||||
}
|
||||
}
|
||||
|
||||
$data = array(
|
||||
// abs_path isn't overly useful, wastes space, and exposes
|
||||
// filesystem internals
|
||||
// 'abs_path' => $abs_path,
|
||||
'filename' => $context['filename'],
|
||||
'lineno' => (int) $context['lineno'],
|
||||
'module' => $module,
|
||||
'function' => $nextframe['function'],
|
||||
'pre_context' => $context['prefix'],
|
||||
'context_line' => $context['line'],
|
||||
'post_context' => $context['suffix'],
|
||||
);
|
||||
|
||||
// detect in_app based on app path
|
||||
if ($app_path) {
|
||||
$data['in_app'] = (bool)(substr($abs_path, 0, strlen($app_path)) === $app_path);
|
||||
}
|
||||
|
||||
// dont set this as an empty array as PHP will treat it as a numeric array
|
||||
// instead of a mapping which goes against the defined Sentry spec
|
||||
if (!empty($vars)) {
|
||||
$serializer = new Raven_ReprSerializer();
|
||||
$cleanVars = array();
|
||||
foreach ($vars as $key => $value) {
|
||||
$value = $serializer->serialize($value);
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
$cleanVars[$key] = substr($value, 0, $frame_var_limit);
|
||||
} else {
|
||||
$cleanVars[$key] = $value;
|
||||
}
|
||||
}
|
||||
$data['vars'] = $cleanVars;
|
||||
}
|
||||
|
||||
$result[] = $data;
|
||||
}
|
||||
|
||||
return array_reverse($result);
|
||||
}
|
||||
|
||||
public static function get_caller_frame_context($frame)
|
||||
{
|
||||
if (!isset($frame['args'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$i = 1;
|
||||
$args = array();
|
||||
foreach ($frame['args'] as $arg) {
|
||||
$args['param'.$i] = $arg;
|
||||
$i++;
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
public static function get_frame_context($frame, $frame_arg_limit = Raven_Client::MESSAGE_LIMIT)
|
||||
{
|
||||
// The reflection API seems more appropriate if we associate it with the frame
|
||||
// where the function is actually called (since we're treating them as function context)
|
||||
if (!isset($frame['function'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (!isset($frame['args'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
if (strpos($frame['function'], '__lambda_func') !== false) {
|
||||
return array();
|
||||
}
|
||||
if (isset($frame['class']) && $frame['class'] == 'Closure') {
|
||||
return array();
|
||||
}
|
||||
if (strpos($frame['function'], '{closure}') !== false) {
|
||||
return array();
|
||||
}
|
||||
if (in_array($frame['function'], self::$statements)) {
|
||||
if (empty($frame['args'])) {
|
||||
// No arguments
|
||||
return array();
|
||||
} else {
|
||||
// Sanitize the file path
|
||||
return array($frame['args'][0]);
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (isset($frame['class'])) {
|
||||
if (method_exists($frame['class'], $frame['function'])) {
|
||||
$reflection = new ReflectionMethod($frame['class'], $frame['function']);
|
||||
} elseif ($frame['type'] === '::') {
|
||||
$reflection = new ReflectionMethod($frame['class'], '__callStatic');
|
||||
} else {
|
||||
$reflection = new ReflectionMethod($frame['class'], '__call');
|
||||
}
|
||||
} else {
|
||||
$reflection = new ReflectionFunction($frame['function']);
|
||||
}
|
||||
} catch (ReflectionException $e) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$params = $reflection->getParameters();
|
||||
|
||||
$args = array();
|
||||
foreach ($frame['args'] as $i => $arg) {
|
||||
if (isset($params[$i])) {
|
||||
// Assign the argument by the parameter name
|
||||
if (is_array($arg)) {
|
||||
foreach ($arg as $key => $value) {
|
||||
if (is_string($value) || is_numeric($value)) {
|
||||
$arg[$key] = substr($value, 0, $frame_arg_limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
$args[$params[$i]->name] = $arg;
|
||||
} else {
|
||||
// TODO: Sentry thinks of these as context locals, so they must be named
|
||||
// Assign the argument by number
|
||||
// $args[$i] = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
private static function strip_prefixes($filename, $prefixes)
|
||||
{
|
||||
if ($prefixes === null) {
|
||||
return;
|
||||
}
|
||||
foreach ($prefixes as $prefix) {
|
||||
if (substr($filename, 0, strlen($prefix)) === $prefix) {
|
||||
return substr($filename, strlen($prefix) + 1);
|
||||
}
|
||||
}
|
||||
return $filename;
|
||||
}
|
||||
|
||||
private static function read_source_file($filename, $lineno, $context_lines = 5)
|
||||
{
|
||||
$frame = array(
|
||||
'prefix' => array(),
|
||||
'line' => '',
|
||||
'suffix' => array(),
|
||||
'filename' => $filename,
|
||||
'lineno' => $lineno,
|
||||
);
|
||||
|
||||
if ($filename === null || $lineno === null) {
|
||||
return $frame;
|
||||
}
|
||||
|
||||
// Code which is eval'ed have a modified filename.. Extract the
|
||||
// correct filename + linenumber from the string.
|
||||
$matches = array();
|
||||
$matched = preg_match("/^(.*?)\((\d+)\) : eval\(\)'d code$/",
|
||||
$filename, $matches);
|
||||
if ($matched) {
|
||||
$frame['filename'] = $filename = $matches[1];
|
||||
$frame['lineno'] = $lineno = $matches[2];
|
||||
}
|
||||
|
||||
// In the case of an anonymous function, the filename is sent as:
|
||||
// "</path/to/filename>(<lineno>) : runtime-created function"
|
||||
// Extract the correct filename + linenumber from the string.
|
||||
$matches = array();
|
||||
$matched = preg_match("/^(.*?)\((\d+)\) : runtime-created function$/",
|
||||
$filename, $matches);
|
||||
if ($matched) {
|
||||
$frame['filename'] = $filename = $matches[1];
|
||||
$frame['lineno'] = $lineno = $matches[2];
|
||||
}
|
||||
|
||||
try {
|
||||
$file = new SplFileObject($filename);
|
||||
$target = max(0, ($lineno - ($context_lines + 1)));
|
||||
$file->seek($target);
|
||||
$cur_lineno = $target+1;
|
||||
while (!$file->eof()) {
|
||||
$line = rtrim($file->current(), "\r\n");
|
||||
if ($cur_lineno == $lineno) {
|
||||
$frame['line'] = $line;
|
||||
} elseif ($cur_lineno < $lineno) {
|
||||
$frame['prefix'][] = $line;
|
||||
} elseif ($cur_lineno > $lineno) {
|
||||
$frame['suffix'][] = $line;
|
||||
}
|
||||
$cur_lineno++;
|
||||
if ($cur_lineno > $lineno + $context_lines) {
|
||||
break;
|
||||
}
|
||||
$file->next();
|
||||
}
|
||||
} catch (RuntimeException $exc) {
|
||||
return $frame;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Utilities
|
||||
*
|
||||
* @package raven
|
||||
*/
|
||||
|
||||
class Raven_Util
|
||||
{
|
||||
/**
|
||||
* Because we love Python, this works much like dict.get() in Python.
|
||||
*
|
||||
* Returns $var from $array if set, otherwise returns $default.
|
||||
*/
|
||||
public static function get($array, $var, $default=null)
|
||||
{
|
||||
if (isset($array[$var])) {
|
||||
return $array[$var];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
@@ -9,17 +9,17 @@
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
bootstrap="test/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="Installers Test Suite">
|
||||
<directory>tests/Composer/Installers</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<testsuites>
|
||||
<testsuite name="Raven Test Suite">
|
||||
<directory>./test/Raven/</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory>src/Composer/Installers</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./lib/Raven/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
@@ -0,0 +1,768 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
// XXX: Is there a better way to stub the client?
|
||||
class Dummy_Raven_Client extends Raven_Client
|
||||
{
|
||||
private $__sent_events = array();
|
||||
|
||||
public function getSentEvents()
|
||||
{
|
||||
return $this->__sent_events;
|
||||
}
|
||||
public function send($data)
|
||||
{
|
||||
if (is_callable($this->send_callback) && !call_user_func($this->send_callback, $data)) {
|
||||
// if send_callback returns falsely, end native send
|
||||
return;
|
||||
}
|
||||
$this->__sent_events[] = $data;
|
||||
}
|
||||
public function is_http_request()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function get_auth_header($timestamp, $client, $api_key, $secret_key)
|
||||
{
|
||||
return parent::get_auth_header($timestamp, $client, $api_key, $secret_key);
|
||||
}
|
||||
public function get_http_data()
|
||||
{
|
||||
return parent::get_http_data();
|
||||
}
|
||||
public function get_user_data()
|
||||
{
|
||||
return parent::get_user_data();
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose the current url method to test it
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function test_get_current_url()
|
||||
{
|
||||
return $this->get_current_url();
|
||||
}
|
||||
}
|
||||
|
||||
class Raven_Tests_ClientTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
private function create_exception()
|
||||
{
|
||||
try {
|
||||
throw new Exception('Foo bar');
|
||||
} catch (Exception $ex) {
|
||||
return $ex;
|
||||
}
|
||||
}
|
||||
|
||||
private function create_chained_exception()
|
||||
{
|
||||
try {
|
||||
throw new Exception('Foo bar');
|
||||
} catch (Exception $ex) {
|
||||
try {
|
||||
throw new Exception('Child exc', 0, $ex);
|
||||
} catch (Exception $ex2) {
|
||||
return $ex2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseDsnHttp()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('http://public:secret@example.com/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['server'], 'http://example.com/api/1/store/');
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnHttps()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('https://public:secret@example.com/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['server'], 'https://example.com/api/1/store/');
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnPath()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('http://public:secret@example.com/app/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['server'], 'http://example.com/app/api/1/store/');
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnPort()
|
||||
{
|
||||
$result = Raven_Client::parseDsn('http://public:secret@example.com:9000/app/1');
|
||||
|
||||
$this->assertEquals($result['project'], 1);
|
||||
$this->assertEquals($result['server'], 'http://example.com:9000/app/api/1/store/');
|
||||
$this->assertEquals($result['public_key'], 'public');
|
||||
$this->assertEquals($result['secret_key'], 'secret');
|
||||
}
|
||||
|
||||
public function testParseDsnInvalidScheme()
|
||||
{
|
||||
try {
|
||||
Raven_Client::parseDsn('gopher://public:secret@/1');
|
||||
$this->fail();
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseDsnMissingNetloc()
|
||||
{
|
||||
try {
|
||||
Raven_Client::parseDsn('http://public:secret@/1');
|
||||
$this->fail();
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseDsnMissingProject()
|
||||
{
|
||||
try {
|
||||
Raven_Client::parseDsn('http://public:secret@example.com');
|
||||
$this->fail();
|
||||
} catch (Exception $e) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testParseDsnMissingPublicKey()
|
||||
{
|
||||
Raven_Client::parseDsn('http://:secret@example.com/1');
|
||||
}
|
||||
/**
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testParseDsnMissingSecretKey()
|
||||
{
|
||||
Raven_Client::parseDsn('http://public@example.com/1');
|
||||
}
|
||||
|
||||
public function testDsnFirstArgument()
|
||||
{
|
||||
$client = new Raven_Client('http://public:secret@example.com/1');
|
||||
|
||||
$this->assertEquals($client->project, 1);
|
||||
$this->assertEquals($client->server, 'http://example.com/api/1/store/');
|
||||
$this->assertEquals($client->public_key, 'public');
|
||||
$this->assertEquals($client->secret_key, 'secret');
|
||||
}
|
||||
|
||||
public function testDsnFirstArgumentWithOptions()
|
||||
{
|
||||
$client = new Raven_Client('http://public:secret@example.com/1', array(
|
||||
'site' => 'foo',
|
||||
));
|
||||
|
||||
$this->assertEquals($client->project, 1);
|
||||
$this->assertEquals($client->server, 'http://example.com/api/1/store/');
|
||||
$this->assertEquals($client->public_key, 'public');
|
||||
$this->assertEquals($client->secret_key, 'secret');
|
||||
$this->assertEquals($client->site, 'foo');
|
||||
}
|
||||
|
||||
public function testOptionsFirstArgument()
|
||||
{
|
||||
$client = new Raven_Client(array(
|
||||
'server' => 'http://example.com/api/1/store/',
|
||||
'project' => 1,
|
||||
));
|
||||
|
||||
$this->assertEquals($client->server, 'http://example.com/api/1/store/');
|
||||
}
|
||||
|
||||
|
||||
public function testDsnInOptionsFirstArg()
|
||||
{
|
||||
$client = new Raven_Client(array(
|
||||
'dsn' => 'http://public:secret@example.com/1',
|
||||
));
|
||||
|
||||
$this->assertEquals($client->project, 1);
|
||||
$this->assertEquals($client->server, 'http://example.com/api/1/store/');
|
||||
$this->assertEquals($client->public_key, 'public');
|
||||
$this->assertEquals($client->secret_key, 'secret');
|
||||
}
|
||||
|
||||
public function testDsnInOptionsSecondArg()
|
||||
{
|
||||
$client = new Raven_Client(null, array(
|
||||
'dsn' => 'http://public:secret@example.com/1',
|
||||
));
|
||||
|
||||
$this->assertEquals($client->project, 1);
|
||||
$this->assertEquals($client->server, 'http://example.com/api/1/store/');
|
||||
$this->assertEquals($client->public_key, 'public');
|
||||
$this->assertEquals($client->secret_key, 'secret');
|
||||
}
|
||||
|
||||
public function testOptionsFirstArgumentWithOptions()
|
||||
{
|
||||
$client = new Raven_Client(array(
|
||||
'server' => 'http://example.com/api/1/store/',
|
||||
'project' => 1,
|
||||
), array(
|
||||
'site' => 'foo',
|
||||
));
|
||||
|
||||
$this->assertEquals($client->server, 'http://example.com/api/1/store/');
|
||||
$this->assertEquals($client->site, 'foo');
|
||||
}
|
||||
|
||||
public function testOptionsExtraData()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array('extra' => array('foo' => 'bar')));
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['extra']['foo'], 'bar');
|
||||
}
|
||||
|
||||
public function testEmptyExtraData()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array('extra' => array()));
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array_key_exists('extra', $event), false);
|
||||
}
|
||||
|
||||
public function testCaptureMessageDoesHandleUninterpolatedMessage()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['message'], 'Test Message %s');
|
||||
}
|
||||
|
||||
public function testCaptureMessageDoesHandleInterpolatedMessage()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['message'], 'Test Message foo');
|
||||
}
|
||||
|
||||
public function testCaptureMessageSetsInterface()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['sentry.interfaces.Message'], array(
|
||||
'message' => 'Test Message %s',
|
||||
'params' => array('foo'),
|
||||
));
|
||||
}
|
||||
|
||||
public function testCaptureMessageHandlesOptionsAsThirdArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'), array(
|
||||
'level' => Dummy_Raven_Client::WARNING,
|
||||
'extra' => array('foo' => 'bar')
|
||||
));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::WARNING);
|
||||
$this->assertEquals($event['extra']['foo'], 'bar');
|
||||
}
|
||||
|
||||
public function testCaptureMessageHandlesLevelAsThirdArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->captureMessage('Test Message %s', array('foo'), Dummy_Raven_Client::WARNING);
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::WARNING);
|
||||
}
|
||||
|
||||
public function testCaptureExceptionSetsInterfaces()
|
||||
{
|
||||
# TODO: it'd be nice if we could mock the stacktrace extraction function here
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex);
|
||||
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
|
||||
$exc = $event['exception'];
|
||||
$this->assertEquals(count($exc['values']), 1);
|
||||
$this->assertEquals($exc['values'][0]['value'], 'Foo bar');
|
||||
$this->assertEquals($exc['values'][0]['type'], 'Exception');
|
||||
$this->assertFalse(empty($exc['values'][0]['module']));
|
||||
|
||||
$this->assertFalse(empty($exc['values'][0]['stacktrace']['frames']));
|
||||
$frames = $exc['values'][0]['stacktrace']['frames'];
|
||||
$frame = $frames[count($frames) - 1];
|
||||
$this->assertTrue($frame['lineno'] > 0);
|
||||
$this->assertEquals($frame['module'], 'ClientTest.php:Raven_Tests_ClientTest');
|
||||
$this->assertEquals($frame['function'], 'create_exception');
|
||||
$this->assertFalse(isset($frame['vars']));
|
||||
$this->assertEquals($frame['context_line'], ' throw new Exception(\'Foo bar\');');
|
||||
$this->assertFalse(empty($frame['pre_context']));
|
||||
$this->assertFalse(empty($frame['post_context']));
|
||||
}
|
||||
|
||||
public function testCaptureExceptionChainedException()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->markTestSkipped('PHP 5.3 required for chained exceptions.');
|
||||
}
|
||||
|
||||
# TODO: it'd be nice if we could mock the stacktrace extraction function here
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_chained_exception();
|
||||
$client->captureException($ex);
|
||||
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
|
||||
$exc = $event['exception'];
|
||||
$this->assertEquals(count($exc['values']), 2);
|
||||
$this->assertEquals($exc['values'][0]['value'], 'Foo bar');
|
||||
$this->assertEquals($exc['values'][1]['value'], 'Child exc');
|
||||
}
|
||||
|
||||
public function testCaptureExceptionDifferentLevelsInChainedExceptionsBug()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
$this->markTestSkipped('PHP 5.3 required for chained exceptions.');
|
||||
}
|
||||
|
||||
$client = new Dummy_Raven_Client();
|
||||
$e1 = new ErrorException('First', 0, E_DEPRECATED);
|
||||
$e2 = new ErrorException('Second', 0, E_NOTICE, __FILE__, __LINE__, $e1);
|
||||
$e3 = new ErrorException('Third', 0, E_ERROR, __FILE__, __LINE__, $e2);
|
||||
|
||||
$client->captureException($e1);
|
||||
$client->captureException($e2);
|
||||
$client->captureException($e3);
|
||||
$events = $client->getSentEvents();
|
||||
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::ERROR);
|
||||
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::INFO);
|
||||
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['level'], Dummy_Raven_Client::WARNING);
|
||||
}
|
||||
|
||||
public function testCaptureExceptionHandlesOptionsAsSecondArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex, array('culprit' => 'test'));
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['culprit'], 'test');
|
||||
}
|
||||
|
||||
public function testCaptureExceptionHandlesCulpritAsSecondArg()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex, 'test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 1);
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals($event['culprit'], 'test');
|
||||
}
|
||||
|
||||
public function testCaptureExceptionHandlesExcludeOption()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array(
|
||||
'exclude' => array('Exception'),
|
||||
));
|
||||
$ex = $this->create_exception();
|
||||
$client->captureException($ex, 'test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(count($events), 0);
|
||||
}
|
||||
|
||||
public function testDoesRegisterProcessors()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array(
|
||||
'processors' => array('Raven_SanitizeDataProcessor'),
|
||||
));
|
||||
$this->assertEquals(count($client->processors), 1);
|
||||
$this->assertTrue($client->processors[0] instanceof Raven_SanitizeDataProcessor);
|
||||
}
|
||||
|
||||
public function testProcessDoesCallProcessors()
|
||||
{
|
||||
$data = array("key"=>"value");
|
||||
|
||||
$processor = $this->getMock('Processor', array('process'));
|
||||
$processor->expects($this->once())
|
||||
->method('process')
|
||||
->with($data);
|
||||
|
||||
$client = new Dummy_Raven_Client();
|
||||
$client->processors[] = $processor;
|
||||
$client->process($data);
|
||||
}
|
||||
|
||||
public function testDefaultProcessorsAreUsed()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$defaults = Dummy_Raven_Client::getDefaultProcessors();
|
||||
|
||||
$this->assertEquals(count($client->processors), count($defaults));
|
||||
}
|
||||
|
||||
public function testDefaultProcessorsContainSanitizeDataProcessor()
|
||||
{
|
||||
$defaults = Dummy_Raven_Client::getDefaultProcessors();
|
||||
|
||||
$this->assertTrue(in_array('Raven_SanitizeDataProcessor', $defaults));
|
||||
}
|
||||
|
||||
public function testGetDefaultData()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$expected = array(
|
||||
'platform' => 'php',
|
||||
'project' => $client->project,
|
||||
'server_name' => $client->name,
|
||||
'site' => $client->site,
|
||||
'logger' => $client->logger,
|
||||
'tags' => $client->tags,
|
||||
'sdk' => array(
|
||||
'name' => 'sentry-php',
|
||||
'version' => $client::VERSION,
|
||||
),
|
||||
);
|
||||
$this->assertEquals($expected, $client->get_default_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* @backupGlobals
|
||||
*/
|
||||
public function testGetHttpData()
|
||||
{
|
||||
$_SERVER = array(
|
||||
'REDIRECT_STATUS' => '200',
|
||||
'CONTENT_TYPE' => 'text/xml',
|
||||
'CONTENT_LENGTH' => '99',
|
||||
'HTTP_HOST' => 'getsentry.com',
|
||||
'HTTP_ACCEPT' => 'text/html',
|
||||
'HTTP_ACCEPT_CHARSET' => 'utf-8',
|
||||
'HTTP_COOKIE' => 'cupcake: strawberry',
|
||||
'SERVER_PORT' => '443',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
'QUERY_STRING' => 'q=bitch&l=en',
|
||||
'REQUEST_URI' => '/welcome/',
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
);
|
||||
$_POST = array(
|
||||
'stamp' => '1c',
|
||||
);
|
||||
$_COOKIE = array(
|
||||
'donut' => 'chocolat',
|
||||
);
|
||||
|
||||
$expected = array(
|
||||
'request' => array(
|
||||
'method' => 'PATCH',
|
||||
'url' => 'https://getsentry.com/welcome/',
|
||||
'query_string' => 'q=bitch&l=en',
|
||||
'data' => array(
|
||||
'stamp' => '1c',
|
||||
),
|
||||
'cookies' => array(
|
||||
'donut' => 'chocolat',
|
||||
),
|
||||
'headers' => array(
|
||||
'Host' => 'getsentry.com',
|
||||
'Accept' => 'text/html',
|
||||
'Accept-Charset' => 'utf-8',
|
||||
'Cookie' => 'cupcake: strawberry',
|
||||
'Content-Type' => 'text/xml',
|
||||
'Content-Length' => '99',
|
||||
),
|
||||
'env' => array(
|
||||
'REDIRECT_STATUS' => '200',
|
||||
'SERVER_PORT' => '443',
|
||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||
'REQUEST_METHOD' => 'PATCH',
|
||||
'QUERY_STRING' => 'q=bitch&l=en',
|
||||
'REQUEST_URI' => '/welcome/',
|
||||
'SCRIPT_NAME' => '/index.php',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$client = new Dummy_Raven_Client();
|
||||
$this->assertEquals($expected, $client->get_http_data());
|
||||
}
|
||||
|
||||
public function testGetUserDataWithSetUser()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$id = 'unique_id';
|
||||
$email = 'foo@example.com';
|
||||
|
||||
$user = array(
|
||||
'username' => 'my_user',
|
||||
);
|
||||
|
||||
$client->set_user_data($id, $email, $user);
|
||||
|
||||
$expected = array(
|
||||
'user' => array(
|
||||
'id' => 'unique_id',
|
||||
'username' => 'my_user',
|
||||
'email' => 'foo@example.com',
|
||||
)
|
||||
);
|
||||
|
||||
$this->assertEquals($expected, $client->get_user_data());
|
||||
}
|
||||
|
||||
public function testGetUserDataWithNoUser()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$expected = array(
|
||||
'user' => array(
|
||||
'id' => session_id(),
|
||||
)
|
||||
);
|
||||
$this->assertEquals($expected, $client->get_user_data());
|
||||
}
|
||||
|
||||
public function testGetAuthHeader()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$clientstring = 'sentry-php/test';
|
||||
$timestamp = '1234341324.340000';
|
||||
|
||||
$expected = "Sentry sentry_timestamp={$timestamp}, sentry_client={$clientstring}, " .
|
||||
"sentry_version=" . Dummy_Raven_Client::PROTOCOL . ", " .
|
||||
"sentry_key=publickey, sentry_secret=secretkey";
|
||||
|
||||
$this->assertEquals($expected, $client->get_auth_header($timestamp, 'sentry-php/test', 'publickey', 'secretkey'));
|
||||
}
|
||||
|
||||
public function testCaptureMessageWithUserContext()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->user_context(array('email' => 'foo@example.com'));
|
||||
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array(
|
||||
'email' => 'foo@example.com',
|
||||
), $event['user']);
|
||||
}
|
||||
|
||||
public function testCaptureMessageWithTagsContext()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->tags_context(array('foo' => 'bar'));
|
||||
$client->tags_context(array('biz' => 'boz'));
|
||||
$client->tags_context(array('biz' => 'baz'));
|
||||
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array(
|
||||
'foo' => 'bar',
|
||||
'biz' => 'baz',
|
||||
), $event['tags']);
|
||||
}
|
||||
|
||||
public function testCaptureMessageWithExtraContext()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
|
||||
$client->extra_context(array('foo' => 'bar'));
|
||||
$client->extra_context(array('biz' => 'boz'));
|
||||
$client->extra_context(array('biz' => 'baz'));
|
||||
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
$event = array_pop($events);
|
||||
$this->assertEquals(array(
|
||||
'foo' => 'bar',
|
||||
'biz' => 'baz',
|
||||
), $event['extra']);
|
||||
}
|
||||
|
||||
public function testGetLastEventID()
|
||||
{
|
||||
$client = new Dummy_Raven_Client();
|
||||
$client->capture(array('message' => 'test', 'event_id' => 'abc'));
|
||||
$this->assertEquals($client->getLastEventID(), 'abc');
|
||||
}
|
||||
|
||||
public function cb1($data)
|
||||
{
|
||||
$this->assertEquals('test', $data['message']);
|
||||
return false;
|
||||
}
|
||||
|
||||
public function cb2($data)
|
||||
{
|
||||
$this->assertEquals('test', $data['message']);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function testSendCallback()
|
||||
{
|
||||
$client = new Dummy_Raven_Client(array('send_callback' => array($this, 'cb1')));
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(0, count($events));
|
||||
|
||||
$client = new Dummy_Raven_Client(array('send_callback' => array($this, 'cb2')));
|
||||
$client->captureMessage('test');
|
||||
$events = $client->getSentEvents();
|
||||
$this->assertEquals(1, count($events));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the server array to the test values, check the current url
|
||||
*
|
||||
* @dataProvider currentUrlProvider
|
||||
* @param array $serverData
|
||||
* @param array $options
|
||||
* @param string $expected - the url expected
|
||||
* @param string $message - fail message
|
||||
*/
|
||||
public function testCurrentUrl($serverVars, $options, $expected, $message)
|
||||
{
|
||||
$_SERVER = $serverVars;
|
||||
|
||||
$client = new Dummy_Raven_Client($options);
|
||||
$result = $client->test_get_current_url();
|
||||
|
||||
$this->assertSame($expected, $result, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Arrays of:
|
||||
* $_SERVER data
|
||||
* config
|
||||
* expected url
|
||||
* Fail message
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function currentUrlProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(),
|
||||
array(),
|
||||
null,
|
||||
'No url expected for empty REQUEST_URI'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'REQUEST_URI' => '/',
|
||||
'HTTP_HOST' => 'example.com',
|
||||
),
|
||||
array(),
|
||||
'http://example.com/',
|
||||
'The url is expected to be http with the request uri'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'REQUEST_URI' => '/',
|
||||
'HTTP_HOST' => 'example.com',
|
||||
'HTTPS' => 'on'
|
||||
),
|
||||
array(),
|
||||
'https://example.com/',
|
||||
'The url is expected to be https because of HTTPS on'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'REQUEST_URI' => '/',
|
||||
'HTTP_HOST' => 'example.com',
|
||||
'SERVER_PORT' => '443'
|
||||
),
|
||||
array(),
|
||||
'https://example.com/',
|
||||
'The url is expected to be https because of the server port'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'REQUEST_URI' => '/',
|
||||
'HTTP_HOST' => 'example.com',
|
||||
'X-FORWARDED-PROTO' => 'https'
|
||||
),
|
||||
array(),
|
||||
'http://example.com/',
|
||||
'The url is expected to be http because the X-Forwarded header is ignored'
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'REQUEST_URI' => '/',
|
||||
'HTTP_HOST' => 'example.com',
|
||||
'X-FORWARDED-PROTO' => 'https'
|
||||
),
|
||||
array('trust_x_forwarded_proto' => true),
|
||||
'https://example.com/',
|
||||
'The url is expected to be https because the X-Forwarded header is trusted'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Tests_CompatTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function test_gethostname()
|
||||
{
|
||||
$this->assertEquals(Raven_Compat::gethostname(), Raven_Compat::_gethostname());
|
||||
$this->assertTrue(strlen(Raven_Compat::_gethostname()) > 0);
|
||||
}
|
||||
|
||||
public function test_hash_hmac()
|
||||
{
|
||||
$result = Raven_Compat::hash_hmac('sha1', 'foo', 'bar');
|
||||
$this->assertEquals('85d155c55ed286a300bd1cf124de08d87e914f3a', $result);
|
||||
|
||||
$result = Raven_Compat::_hash_hmac('sha1', 'foo', 'bar');
|
||||
$this->assertEquals('85d155c55ed286a300bd1cf124de08d87e914f3a', $result);
|
||||
}
|
||||
|
||||
public function test_json_encode()
|
||||
{
|
||||
$result = Raven_Compat::json_encode(array('foo' => array('bar' => 1)));
|
||||
$this->assertEquals('{"foo":{"bar":1}}', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array('foo' => array('bar' => 1)));
|
||||
$this->assertEquals('{"foo":{"bar":1}}', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array(1, 2, 3, 4, 'foo', 'bar'));
|
||||
$this->assertEquals('[1,2,3,4,"foo","bar"]', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array(1, 'foo', 'foobar' => 'bar'));
|
||||
$this->assertEquals('{0:1,1:"foo","foobar":"bar"}', $result);
|
||||
|
||||
$result = Raven_Compat::_json_encode(array(array()));
|
||||
$this->assertEquals('[[]]', $result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Tests_ErrorHandlerTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $errorLevel;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->errorLevel = error_reporting();
|
||||
$this->errorHandlerCalled = false;
|
||||
$this->existingErrorHandler = set_error_handler(array($this, 'errorHandler'), -1);
|
||||
}
|
||||
|
||||
public function errorHandler()
|
||||
{
|
||||
$this->errorHandlerCalled = true;
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
// XXX(dcramer): this isn't great as it doesnt restore the old error reporting level
|
||||
set_error_handler(array($this, 'errorHandler'), error_reporting());
|
||||
error_reporting($this->errorLevel);
|
||||
}
|
||||
|
||||
public function testErrorsAreLoggedAsExceptions()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent', 'sendUnsentErrors'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException')
|
||||
->with($this->isInstanceOf('ErrorException'));
|
||||
|
||||
$handler = new Raven_ErrorHandler($client, E_ALL);
|
||||
$handler->handleError(E_WARNING, 'message');
|
||||
}
|
||||
|
||||
public function testExceptionsAreLogged()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException')
|
||||
->with($this->isInstanceOf('ErrorException'));
|
||||
|
||||
$e = new ErrorException('message', 0, E_WARNING, '', 0);
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->handleException($e);
|
||||
}
|
||||
|
||||
public function testErrorHandlerPassErrorReportingPass()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException');
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(false, -1);
|
||||
|
||||
error_reporting(E_USER_WARNING);
|
||||
trigger_error('Warning', E_USER_WARNING);
|
||||
}
|
||||
|
||||
public function testErrorHandlerPropagates()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->never())
|
||||
->method('captureException');
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(true, E_DEPRECATED);
|
||||
|
||||
error_reporting(E_USER_WARNING);
|
||||
trigger_error('Warning', E_USER_WARNING);
|
||||
|
||||
$this->assertEquals($this->errorHandlerCalled, 1);
|
||||
}
|
||||
|
||||
public function testErrorHandlerRespectsErrorReportingDefault()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->once())
|
||||
->method('captureException');
|
||||
|
||||
error_reporting(E_DEPRECATED);
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(true);
|
||||
|
||||
error_reporting(E_ALL);
|
||||
trigger_error('Warning', E_USER_WARNING);
|
||||
|
||||
$this->assertEquals($this->errorHandlerCalled, 1);
|
||||
}
|
||||
|
||||
// Because we cannot **know** that a user silenced an error, we always
|
||||
// defer to respecting the error reporting settings.
|
||||
public function testSilentErrorsAreReported()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->never())
|
||||
->method('captureException');
|
||||
|
||||
error_reporting(E_USER_WARNING);
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(false);
|
||||
|
||||
@trigger_error('Silent', E_USER_WARNING);
|
||||
}
|
||||
|
||||
public function testErrorHandlerDefaultsErrorReporting()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$client->expects($this->never())
|
||||
->method('captureException');
|
||||
|
||||
error_reporting(E_USER_ERROR);
|
||||
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$handler->registerErrorHandler(false);
|
||||
|
||||
trigger_error('Warning', E_USER_WARNING);
|
||||
}
|
||||
|
||||
public function testFluidInterface()
|
||||
{
|
||||
$client = $this->getMock('Client', array('captureException', 'getIdent'));
|
||||
$handler = new Raven_ErrorHandler($client);
|
||||
$result = $handler->registerErrorHandler();
|
||||
$this->assertEquals($result, $handler);
|
||||
$result = $handler->registerExceptionHandler();
|
||||
$this->assertEquals($result, $handler);
|
||||
// TODO(dcramer): cant find a great way to test resetting the shutdown
|
||||
// handler
|
||||
// $result = $handler->registerShutdownHandler();
|
||||
// $this->assertEquals($result, $handler);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_Tests_SanitizeDataProcessorTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testDoesFilterHttpData()
|
||||
{
|
||||
$data = array(
|
||||
'request' => array(
|
||||
'data' => array(
|
||||
'foo' => 'bar',
|
||||
'password' => 'hello',
|
||||
'the_secret' => 'hello',
|
||||
'a_password_here' => 'hello',
|
||||
'mypasswd' => 'hello',
|
||||
'authorization' => 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=',
|
||||
'card_number' => array(
|
||||
'1111',
|
||||
'2222',
|
||||
'3333',
|
||||
'4444'
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$client = new Raven_Client();
|
||||
$processor = new Raven_SanitizeDataProcessor($client);
|
||||
$processor->process($data);
|
||||
|
||||
$vars = $data['request']['data'];
|
||||
$this->assertEquals($vars['foo'], 'bar');
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['password']);
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['the_secret']);
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['a_password_here']);
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['mypasswd']);
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['authorization']);
|
||||
|
||||
$this->markTestIncomplete('Array scrubbing has not been implemented yet.');
|
||||
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['card_number']['0']);
|
||||
}
|
||||
|
||||
public function testDoesFilterSessionId()
|
||||
{
|
||||
$data = array(
|
||||
'request' => array(
|
||||
'cookies' => array(
|
||||
ini_get('session.name') => 'abc',
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$client = new Raven_Client();
|
||||
$processor = new Raven_SanitizeDataProcessor($client);
|
||||
$processor->process($data);
|
||||
|
||||
$cookies = $data['request']['cookies'];
|
||||
$this->assertEquals($cookies[ini_get('session.name')], Raven_SanitizeDataProcessor::MASK);
|
||||
}
|
||||
|
||||
public function testDoesFilterCreditCard()
|
||||
{
|
||||
$data = array(
|
||||
'ccnumba' => '4242424242424242'
|
||||
);
|
||||
|
||||
$client = new Raven_Client();
|
||||
$processor = new Raven_SanitizeDataProcessor($client);
|
||||
$processor->process($data);
|
||||
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $data['ccnumba']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers setProcessorOptions
|
||||
*
|
||||
*/
|
||||
public function testSettingProcessorOptions()
|
||||
{
|
||||
$client = new Raven_Client();
|
||||
$processor = new Raven_SanitizeDataProcessor($client);
|
||||
|
||||
$this->assertEquals($processor->getFieldsRe(), '/(authorization|password|passwd|secret|password_confirmation|card_number|auth_pw)/i', 'got default fields');
|
||||
$this->assertEquals($processor->getValuesRe(), '/^(?:\d[ -]*?){13,16}$/', 'got default values');
|
||||
|
||||
$options = array(
|
||||
'fields_re' => '/(api_token)/i',
|
||||
'values_re' => '/^(?:\d[ -]*?){15,16}$/'
|
||||
);
|
||||
|
||||
$processor->setProcessorOptions($options);
|
||||
|
||||
$this->assertEquals($processor->getFieldsRe(), '/(api_token)/i', 'overwrote fields');
|
||||
$this->assertEquals($processor->getValuesRe(), '/^(?:\d[ -]*?){15,16}$/', 'overwrote values');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider overrideDataProvider
|
||||
*
|
||||
* @param $processorOptions
|
||||
* @param $client_options
|
||||
* @param $dsn
|
||||
*/
|
||||
public function testOverrideOptions($processorOptions, $client_options, $dsn)
|
||||
{
|
||||
$client = new Raven_Client($dsn, $client_options);
|
||||
$processor = $client->processors[0];
|
||||
|
||||
$this->assertInstanceOf('Raven_SanitizeDataProcessor', $processor);
|
||||
$this->assertEquals($processor->getFieldsRe(), $processorOptions['Raven_SanitizeDataProcessor']['fields_re'], 'overwrote fields');
|
||||
$this->assertEquals($processor->getValuesRe(), $processorOptions['Raven_SanitizeDataProcessor']['values_re'], 'overwrote values');
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testOverrideOptions
|
||||
* @dataProvider overrideDataProvider
|
||||
*
|
||||
* @param $processorOptions
|
||||
* @param $client_options
|
||||
* @param $dsn
|
||||
*/
|
||||
public function testOverridenSanitize($processorOptions, $client_options, $dsn)
|
||||
{
|
||||
$data = array(
|
||||
'request' => array(
|
||||
'data' => array(
|
||||
'foo' => 'bar',
|
||||
'password' => 'hello',
|
||||
'the_secret' => 'hello',
|
||||
'a_password_here' => 'hello',
|
||||
'mypasswd' => 'hello',
|
||||
'api_token' => 'nioenio3nrio3jfny89nby9bhr#RML#R',
|
||||
'authorization' => 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=',
|
||||
'card_number' => array(
|
||||
'1111111111111111',
|
||||
'2222',
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$client = new Raven_Client($dsn, $client_options);
|
||||
$processor = $client->processors[0];
|
||||
|
||||
$this->assertInstanceOf('Raven_SanitizeDataProcessor', $processor);
|
||||
$this->assertEquals($processor->getFieldsRe(), $processorOptions['Raven_SanitizeDataProcessor']['fields_re'], 'overwrote fields');
|
||||
$this->assertEquals($processor->getValuesRe(), $processorOptions['Raven_SanitizeDataProcessor']['values_re'], 'overwrote values');
|
||||
|
||||
$processor->process($data);
|
||||
|
||||
$vars = $data['request']['data'];
|
||||
$this->assertEquals($vars['foo'], 'bar', 'did not alter foo');
|
||||
$this->assertEquals($vars['password'], 'hello', 'did not alter password');
|
||||
$this->assertEquals($vars['the_secret'], 'hello', 'did not alter the_secret');
|
||||
$this->assertEquals($vars['a_password_here'], 'hello', 'did not alter a_password_here');
|
||||
$this->assertEquals($vars['mypasswd'], 'hello', 'did not alter mypasswd');
|
||||
$this->assertEquals($vars['authorization'], 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'did not alter authorization');
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['api_token'], 'masked api_token');
|
||||
|
||||
$this->assertEquals(Raven_SanitizeDataProcessor::MASK, $vars['card_number']['0'], 'masked card_number[0]');
|
||||
$this->assertEquals($vars['card_number']['1'], $vars['card_number']['1'], 'did not alter card_number[1]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides data for testing overriding the processor options
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function overrideDataProvider()
|
||||
{
|
||||
$processorOptions = array(
|
||||
'Raven_SanitizeDataProcessor' => array(
|
||||
'fields_re' => '/(api_token)/i',
|
||||
'values_re' => '/^(?:\d[ -]*?){15,16}$/'
|
||||
)
|
||||
);
|
||||
|
||||
$client_options = array(
|
||||
'processors' => array('Raven_SanitizeDataProcessor'),
|
||||
'processorOptions' => $processorOptions
|
||||
);
|
||||
|
||||
$dsn = 'http://9aaa31f9a05b4e72aaa06aa8157a827a:9aa7aa82a9694a08a1a7589a2a035a9a@sentry.domain.tld/1';
|
||||
|
||||
return array(
|
||||
array($processorOptions, $client_options, $dsn)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_SerializerTestObject
|
||||
{
|
||||
private $foo = 'bar';
|
||||
}
|
||||
|
||||
class Raven_Tests_SerializerTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testArraysAreArrays()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = array(1, 2, 3);
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertEquals(array('1', '2', '3'), $result);
|
||||
}
|
||||
|
||||
public function testObjectsAreStrings()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = new Raven_StacktraceTestObject();
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertEquals('Object Raven_StacktraceTestObject', $result);
|
||||
}
|
||||
|
||||
public function testIntsAreInts()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = 1;
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertTrue(is_integer($result));
|
||||
$this->assertEquals(1, $result);
|
||||
}
|
||||
|
||||
public function testFloats()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = 1.5;
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertTrue(is_float($result));
|
||||
$this->assertEquals(1.5, $result);
|
||||
}
|
||||
|
||||
public function testBooleans()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = true;
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertTrue(is_bool($result));
|
||||
$this->assertEquals(true, $result);
|
||||
|
||||
$input = false;
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertTrue(is_bool($result));
|
||||
$this->assertEquals(false, $result);
|
||||
}
|
||||
|
||||
public function testNull()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = null;
|
||||
$result = $serializer->serialize($input);
|
||||
$this->assertTrue(is_null($result));
|
||||
$this->assertEquals(null, $result);
|
||||
}
|
||||
|
||||
public function testRecursionMaxDepth()
|
||||
{
|
||||
$serializer = new Raven_Serializer();
|
||||
$input = array();
|
||||
$input[] = &$input;
|
||||
$result = $serializer->serialize($input, 3);
|
||||
$this->assertEquals(array(array(array('Array of length 1'))), $result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
function raven_test_recurse($times, $callback)
|
||||
{
|
||||
$times -= 1;
|
||||
if ($times > 0) {
|
||||
return call_user_func('raven_test_recurse', $times, $callback);
|
||||
}
|
||||
|
||||
return call_user_func($callback);
|
||||
}
|
||||
|
||||
function raven_test_create_stacktrace($args=null, $times=3)
|
||||
{
|
||||
return raven_test_recurse($times, 'debug_backtrace');
|
||||
}
|
||||
|
||||
class Raven_Tests_StacktraceTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testCanTraceParamContext()
|
||||
{
|
||||
$stack = raven_test_create_stacktrace(array('biz', 'baz'), 0);
|
||||
|
||||
$frame = $stack[2];
|
||||
$params = Raven_Stacktrace::get_frame_context($frame);
|
||||
$this->assertEquals($params['args'], array('biz', 'baz'));
|
||||
$this->assertEquals($params['times'], 0);
|
||||
}
|
||||
|
||||
public function testSimpleTrace()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
"args"=> array(
|
||||
"friend",
|
||||
),
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"args"=> array(
|
||||
"/tmp/a.php",
|
||||
),
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true);
|
||||
|
||||
$frame = $frames[0];
|
||||
$this->assertEquals('b.php', $frame["module"]);
|
||||
$this->assertEquals(3, $frame["lineno"]);
|
||||
$this->assertNull($frame["function"]);
|
||||
$this->assertEquals("include_once '/tmp/a.php';", $frame["context_line"]);
|
||||
$frame = $frames[1];
|
||||
$this->assertEquals('a.php', $frame["module"]);
|
||||
$this->assertEquals(11, $frame["lineno"]);
|
||||
$this->assertEquals('include_once', $frame["function"]);
|
||||
$this->assertEquals('a_test($foo);', $frame["context_line"]);
|
||||
}
|
||||
|
||||
public function testSimpleUnshiftedTrace()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
"args"=> array(
|
||||
"friend",
|
||||
),
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"args"=> array(
|
||||
"/tmp/a.php",
|
||||
),
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true, false);
|
||||
|
||||
$frame = $frames[0];
|
||||
$this->assertEquals('b.php', $frame["module"]);
|
||||
$this->assertEquals(3, $frame["lineno"]);
|
||||
$this->assertNull($frame["function"]);
|
||||
$this->assertEquals('/tmp/a.php', $frame['vars']['param1']);
|
||||
$this->assertEquals("include_once '/tmp/a.php';", $frame["context_line"]);
|
||||
$frame = $frames[1];
|
||||
$this->assertEquals('a.php', $frame["module"]);
|
||||
$this->assertEquals(11, $frame["lineno"]);
|
||||
$this->assertEquals('include_once', $frame["function"]);
|
||||
$this->assertEquals('friend', $frame['vars']['param1']);
|
||||
$this->assertEquals('a_test($foo);', $frame["context_line"]);
|
||||
}
|
||||
|
||||
public function testShiftedCaptureVars()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
"args"=> array(
|
||||
"friend",
|
||||
),
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"args"=> array(
|
||||
"/tmp/a.php",
|
||||
),
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
$vars = array(
|
||||
"foo" => "bar",
|
||||
"baz" => "zoom"
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true, true, $vars);
|
||||
|
||||
$frame = $frames[0];
|
||||
$this->assertEquals('b.php', $frame["module"]);
|
||||
$this->assertEquals(3, $frame["lineno"]);
|
||||
$this->assertNull($frame["function"]);
|
||||
$this->assertEquals("include_once '/tmp/a.php';", $frame["context_line"]);
|
||||
$this->assertFalse(isset($frame['vars']));
|
||||
$frame = $frames[1];
|
||||
$this->assertEquals('a.php', $frame["module"]);
|
||||
$this->assertEquals(11, $frame["lineno"]);
|
||||
$this->assertEquals('include_once', $frame["function"]);
|
||||
$this->assertEquals('a_test($foo);', $frame["context_line"]);
|
||||
$this->assertEquals($vars, $frame['vars']);
|
||||
}
|
||||
|
||||
public function testDoesNotModifyCaptureVars()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
"args"=> array(
|
||||
"friend",
|
||||
),
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"args"=> array(
|
||||
"/tmp/a.php",
|
||||
),
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
// PHP's errcontext as passed to the error handler contains REFERENCES to any vars that were in the global scope.
|
||||
// Modification of these would be really bad, since if control is returned (non-fatal error) we'll have altered the state of things!
|
||||
$originalFoo = "bloopblarp";
|
||||
$iAmFoo = $originalFoo;
|
||||
$vars = array(
|
||||
"foo" => &$iAmFoo
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true, true, $vars, 5);
|
||||
|
||||
// Check we haven't modified our vars.
|
||||
$this->assertEquals($originalFoo, $vars["foo"]);
|
||||
|
||||
$frame = $frames[1];
|
||||
// Check that we did truncate the variable in our output
|
||||
$this->assertEquals(5, strlen($frame['vars']['foo']));
|
||||
}
|
||||
|
||||
public function testUnshiftedCaptureVars()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
"args"=> array(
|
||||
"friend",
|
||||
),
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"args"=> array(
|
||||
"/tmp/a.php",
|
||||
),
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
$vars = array(
|
||||
"foo" => "bar",
|
||||
"baz" => "zoom"
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true, false, $vars);
|
||||
|
||||
$frame = $frames[0];
|
||||
$this->assertEquals('b.php', $frame["module"]);
|
||||
$this->assertEquals(3, $frame["lineno"]);
|
||||
$this->assertNull($frame["function"]);
|
||||
$this->assertEquals(array('param1' => '/tmp/a.php'), $frame['vars']);
|
||||
$this->assertEquals("include_once '/tmp/a.php';", $frame["context_line"]);
|
||||
$frame = $frames[1];
|
||||
$this->assertEquals('a.php', $frame["module"]);
|
||||
$this->assertEquals(11, $frame["lineno"]);
|
||||
$this->assertEquals('include_once', $frame["function"]);
|
||||
$this->assertEquals($vars, $frame['vars']);
|
||||
$this->assertEquals('a_test($foo);', $frame["context_line"]);
|
||||
}
|
||||
|
||||
public function testDoesFixFrameInfo()
|
||||
{
|
||||
/**
|
||||
* PHP's way of storing backstacks seems bass-ackwards to me
|
||||
* 'function' is not the function you're in; it's any function being
|
||||
* called, so we have to shift 'function' down by 1. Ugh.
|
||||
*/
|
||||
$stack = raven_test_create_stacktrace();
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true);
|
||||
// just grab the last few frames
|
||||
$frames = array_slice($frames, -5);
|
||||
$frame = $frames[0];
|
||||
$this->assertEquals('StacktraceTest.php:Raven_Tests_StacktraceTest', $frame['module']);
|
||||
$this->assertEquals('testDoesFixFrameInfo', $frame['function']);
|
||||
$frame = $frames[1];
|
||||
$this->assertEquals('StacktraceTest.php', $frame['module']);
|
||||
$this->assertEquals('raven_test_create_stacktrace', $frame['function']);
|
||||
$frame = $frames[2];
|
||||
$this->assertEquals('StacktraceTest.php', $frame['module']);
|
||||
$this->assertEquals('raven_test_recurse', $frame['function']);
|
||||
$frame = $frames[3];
|
||||
$this->assertEquals('StacktraceTest.php', $frame['module']);
|
||||
$this->assertEquals('raven_test_recurse', $frame['function']);
|
||||
$frame = $frames[4];
|
||||
$this->assertEquals('StacktraceTest.php', $frame['module']);
|
||||
$this->assertEquals('raven_test_recurse', $frame['function']);
|
||||
}
|
||||
|
||||
public function testInApp()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true, null, null, 0, null, dirname(__FILE__));
|
||||
|
||||
$this->assertEquals($frames[0]['in_app'], true);
|
||||
$this->assertEquals($frames[1]['in_app'], true);
|
||||
}
|
||||
|
||||
public function testBasePath()
|
||||
{
|
||||
$stack = array(
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/a.php",
|
||||
"line" => 11,
|
||||
"function" => "a_test",
|
||||
),
|
||||
array(
|
||||
"file" => dirname(__FILE__) . "/resources/b.php",
|
||||
"line" => 3,
|
||||
"function" => "include_once",
|
||||
),
|
||||
);
|
||||
|
||||
$frames = Raven_Stacktrace::get_stack_info($stack, true, null, null, 0, array(dirname(__FILE__)));
|
||||
|
||||
$this->assertEquals($frames[0]['filename'], 'resources/b.php');
|
||||
$this->assertEquals($frames[1]['filename'], 'resources/a.php');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
class Raven_StacktraceTestObject
|
||||
{
|
||||
private $foo = 'bar';
|
||||
}
|
||||
|
||||
class Raven_Tests_UtilTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testGetReturnsDefaultOnMissing()
|
||||
{
|
||||
$input = array('foo' => 'bar');
|
||||
$result = Raven_Util::get($input, 'baz', 'foo');
|
||||
$this->assertEquals('foo', $result);
|
||||
}
|
||||
|
||||
public function testGetReturnsPresentValuesEvenWhenEmpty()
|
||||
{
|
||||
$input = array('foo' => '');
|
||||
$result = Raven_Util::get($input, 'foo', 'bar');
|
||||
$this->assertEquals('', $result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
// filename: /tmp/a.php
|
||||
|
||||
function a_test($str)
|
||||
{
|
||||
echo "\nHi: $str";
|
||||
var_dump(debug_backtrace());
|
||||
}
|
||||
|
||||
$foo = 'friend';
|
||||
a_test($foo);
|
||||
@@ -0,0 +1,3 @@
|
||||
<?php
|
||||
// filename: /tmp/b.php
|
||||
include_once '/tmp/a.php';
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Raven.
|
||||
*
|
||||
* (c) Sentry Team
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
error_reporting(E_ALL | E_STRICT);
|
||||
|
||||
session_start();
|
||||
|
||||
require_once dirname(__FILE__).'/../lib/Raven/Autoloader.php';
|
||||
Raven_Autoloader::register();
|
||||
@@ -0,0 +1,70 @@
|
||||
=== Plugin Name ===
|
||||
Contributors: rmb185
|
||||
Donate link: https://www.paypal.com/us/cgi-bin/webscr?cmd=_flow&SESSION=WW3LiAp4DccdyrD4QVR0c_XWINGbnIFFQKBrjdenB-0ZzQ33QBR1Xm7WMLK&dispatch=5885d80a13c0db1f8e263663d3faee8da8649a435e198e44a05ba053bc68d12e
|
||||
Tags: sentry, logging, diagnostics, debugging
|
||||
Requires at least: 3.0.1
|
||||
Tested up to: 3.4
|
||||
Stable tag: 1.2
|
||||
License: GPLv2 or later
|
||||
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
GitHub Plugin URI: https://github.com/ryanbagwell/wordpress-sentry
|
||||
GitHub Branch: master
|
||||
|
||||
A plugin that sends error messages to the Sentry error logging system.
|
||||
|
||||
== Description ==
|
||||
|
||||
A plugin that sends error messages to the [Sentry error logging system](https://getsentry.com/welcome/).
|
||||
|
||||
== Installation ==
|
||||
|
||||
1. Upload the plugin's contents to the `/wp-content/plugins/` directory.
|
||||
2. Activate the plugin through the 'Plugins' menu in WordPress.
|
||||
3. In Settings > Sentry, add your Sentry DSN and set the error reporting threshold level.
|
||||
|
||||
== Bug reports and support ==
|
||||
|
||||
To report bugs and get help, see the [official github repository](https://github.com/ryanbagwell/wordpress-sentry/issues).
|
||||
|
||||
== Changelog ==
|
||||
|
||||
= 1.2 =
|
||||
|
||||
Adding the ability to access the Raven client directly to send custom error messages to sentry. Merge PR from @wk8.
|
||||
|
||||
= 1.1 =
|
||||
|
||||
Upgrade raven php client to v0.15.0
|
||||
|
||||
= 1.0 =
|
||||
|
||||
* Bumb version to 1.0 because the WordPress plugins page keeps showing Version 1 as the current version for some reason
|
||||
|
||||
= 0.5 =
|
||||
|
||||
* Bump version to correct errant stable version number
|
||||
|
||||
= 0.4 =
|
||||
|
||||
* Bump version to sync with wordpress.org plugins page
|
||||
|
||||
= 0.3 =
|
||||
|
||||
* Now registering php error handlers with Raven client to improve error reporting.
|
||||
|
||||
= 0.2 =
|
||||
|
||||
* Updated Raven PHP Client
|
||||
|
||||
= 0.1 =
|
||||
|
||||
* Added first release.
|
||||
|
||||
== Contributors ==
|
||||
|
||||
vbartusevicius (https://github.com/vbartusevicius)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
Plugin Name: WordPress Sentry Client
|
||||
Plugin URI: http://www.hzdg.com
|
||||
Description: Sends PHP errors to Django Sentry
|
||||
Author: Ryan Bagwell
|
||||
Version: 1
|
||||
Author URI: http://www.ryanbagwell.com
|
||||
*/
|
||||
|
||||
require_once( dirname(__FILE__) . '/class.wp-raven-client.php' );
|
||||
|
||||
class WPSentry extends WP_Raven_Client {
|
||||
|
||||
private static $instance = null;
|
||||
|
||||
public function __construct() {
|
||||
add_action('admin_menu', array($this, 'addOptionsPage'));
|
||||
|
||||
if (is_admin() && $_POST)
|
||||
$this->saveOptions();
|
||||
|
||||
parent::__construct();
|
||||
|
||||
static::$instance = $this;
|
||||
}
|
||||
|
||||
public function addOptionsPage() {
|
||||
add_options_page('Sentry Error Reporting Settings', 'Sentry', 'edit_pages', 'sentrysettings', array($this, 'printOptionsHTML'));
|
||||
}
|
||||
|
||||
public function printOptionsHTML() {
|
||||
$error_levels = $this->errorLevelMap;
|
||||
$settings = $this->settings;
|
||||
require_once( dirname(__FILE__) . '/optionspage.html.php' );
|
||||
}
|
||||
|
||||
public function saveOptions() {
|
||||
|
||||
if (!isset($_POST['sentry_dsn']) || !isset($_POST['sentry_reporting_level']))
|
||||
return;
|
||||
|
||||
update_option('sentry-settings', array(
|
||||
'dsn' => $_POST['sentry_dsn'],
|
||||
'reporting_level' => $_POST['sentry_reporting_level']
|
||||
));
|
||||
}
|
||||
|
||||
public function getSettings() {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
public static function load() {
|
||||
try {
|
||||
$wps = new WPSentry();
|
||||
} catch (Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public static function getInstance() {
|
||||
return self::$instance;
|
||||
}
|
||||
}
|
||||
|
||||
add_action('plugins_loaded', array('WPSentry', 'load'));
|
||||
@@ -1,5 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
body #_simcal_attach_calendar_id,
|
||||
body .simcal-calendar-widget-settings select {
|
||||
width: 100%; }
|
||||
|
||||
body .select2-container--default .select2-selection--single {
|
||||
border-color: #ccc;
|
||||
border-radius: 0; }
|
||||
|
||||
body .select2-container {
|
||||
z-index: 1000000; }
|
||||
|
||||
body.post-type-gce_feed #gce-insert-shortcode-button {
|
||||
display: none; }
|
||||
|
||||
.wp-media-buttons a.add_calendar span.wp-media-buttons-icon {
|
||||
background: none; }
|
||||
|
||||
.gce-insert-shortcode-panel {
|
||||
max-width: 90%;
|
||||
position: relative; }
|
||||
.gce-insert-shortcode-panel select {
|
||||
display: block;
|
||||
max-width: 470px;
|
||||
width: 100%; }
|
||||
|
||||
body .gce-insert-shortcode-modal {
|
||||
height: 220px !important;
|
||||
margin-left: -250px !important;
|
||||
width: 500px !important; }
|
||||
|
||||
body .gce-insert-shortcode-modal-title {
|
||||
background: #fff !important;
|
||||
border-bottom: none !important;
|
||||
height: 0 !important; }
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
body #_simcal_attach_calendar_id,body .simcal-calendar-widget-settings select{width:100%}body .select2-container--default .select2-selection--single{border-color:#ccc;border-radius:0}body .select2-container{z-index:1000000}body.post-type-gce_feed #gce-insert-shortcode-button{display:none}.wp-media-buttons a.add_calendar span.wp-media-buttons-icon{background:0 0}.gce-insert-shortcode-panel{max-width:90%;position:relative}.gce-insert-shortcode-panel select{display:block;max-width:470px;width:100%}body .gce-insert-shortcode-modal{height:220px!important;margin-left:-250px!important;width:500px!important}body .gce-insert-shortcode-modal-title{background:#fff!important;border-bottom:none!important;height:0!important}
|
||||
@@ -1,550 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'simple-calendar';
|
||||
src: url("../fonts/simple-calendar.eot?43976014");
|
||||
src: url("../fonts/simple-calendar.eot?43976014#iefix") format("embedded-opentype"), url("../fonts/simple-calendar.woff?43976014") format("woff"), url("../fonts/simple-calendar.ttf?43976014") format("truetype"), url("../fonts/simple-calendar.svg?43976014#simple-calendar") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal; }
|
||||
|
||||
[class^="simcal-icon-"]:before,
|
||||
[class*=" simcal-icon-"]:before {
|
||||
display: inline-block;
|
||||
font-family: "simple-calendar";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
margin-right: .2em;
|
||||
speak: none;
|
||||
text-decoration: inherit;
|
||||
text-align: center;
|
||||
width: 1em;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
margin-left: .2em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale; }
|
||||
|
||||
.simcal-icon-spin {
|
||||
animation: spin 2s infinite linear;
|
||||
display: inline-block; }
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg); } }
|
||||
|
||||
.simcal-icon-animate:before {
|
||||
transition: all .2s ease-in-out; }
|
||||
|
||||
.simcal-icon-rotate-180:before {
|
||||
transform: rotate(180deg); }
|
||||
|
||||
.simcal-icon-calendar-empty:before {
|
||||
content: '\e800'; }
|
||||
|
||||
.simcal-icon-calendar:before {
|
||||
content: '\e801'; }
|
||||
|
||||
.simcal-icon-calendar-logo:before {
|
||||
content: '\e802'; }
|
||||
|
||||
.simcal-icon-settings:before {
|
||||
content: '\e804'; }
|
||||
|
||||
.simcal-icon-toggles:before {
|
||||
content: '\e805'; }
|
||||
|
||||
.simcal-icon-list:before {
|
||||
content: '\e806'; }
|
||||
|
||||
.simcal-icon-event:before {
|
||||
content: '\e807'; }
|
||||
|
||||
.simcal-icon-help:before {
|
||||
content: '\e808'; }
|
||||
|
||||
.simcal-icon-panel:before {
|
||||
content: '\e80a'; }
|
||||
|
||||
.simcal-icon-grid:before {
|
||||
content: '\e80b'; }
|
||||
|
||||
.simcal-icon-google:before {
|
||||
content: '\e80c'; }
|
||||
|
||||
.simcal-icon-docs:before {
|
||||
content: '\e80f'; }
|
||||
|
||||
.simcal-icon-hourglass:before {
|
||||
content: '\e811'; }
|
||||
|
||||
.simcal-icon-globe:before {
|
||||
content: '\e812'; }
|
||||
|
||||
.simcal-icon-timezones:before {
|
||||
content: '\e813'; }
|
||||
|
||||
.simcal-icon-warning:before {
|
||||
content: '\e815'; }
|
||||
|
||||
.simcal-icon-wordpress:before {
|
||||
content: '\e814'; }
|
||||
|
||||
.simcal-icon-up:before {
|
||||
content: '\e80e'; }
|
||||
|
||||
.simcal-icon-right:before {
|
||||
content: '\e809'; }
|
||||
|
||||
.simcal-icon-down:before {
|
||||
content: '\e80d'; }
|
||||
|
||||
.simcal-icon-left:before {
|
||||
content: '\e803'; }
|
||||
|
||||
.simcal-icon-spinner:before {
|
||||
content: '\e810'; }
|
||||
|
||||
.simcal-help-tip {
|
||||
color: rgba(0, 0, 0, 0.46);
|
||||
cursor: help; }
|
||||
|
||||
#tiptip_holder {
|
||||
display: none;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 9999999; }
|
||||
|
||||
#tiptip_holder.tip_top {
|
||||
padding-bottom: 5px; }
|
||||
|
||||
#tiptip_holder.tip_bottom {
|
||||
padding-top: 5px; }
|
||||
|
||||
#tiptip_holder.tip_right {
|
||||
padding-left: 5px; }
|
||||
|
||||
#tiptip_holder.tip_left {
|
||||
padding-right: 5px; }
|
||||
|
||||
#tiptip_content {
|
||||
background-color: rgba(25, 25, 25, 0.92);
|
||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||
border-radius: 3px;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
padding: 4px 8px; }
|
||||
|
||||
#tiptip_arrow, #tiptip_arrow_inner {
|
||||
border-color: transparent;
|
||||
border-style: solid;
|
||||
border-width: 6px;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
width: 0; }
|
||||
|
||||
#tiptip_holder.tip_top #tiptip_arrow_inner {
|
||||
border-top-color: rgba(25, 25, 25, 0.92);
|
||||
margin-left: -6px;
|
||||
margin-top: -7px; }
|
||||
|
||||
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
|
||||
border-bottom-color: rgba(25, 25, 25, 0.92);
|
||||
margin-left: -6px;
|
||||
margin-top: -5px; }
|
||||
|
||||
#tiptip_holder.tip_right #tiptip_arrow_inner {
|
||||
border-right-color: rgba(25, 25, 25, 0.92);
|
||||
margin-left: -5px;
|
||||
margin-top: -6px; }
|
||||
|
||||
#tiptip_holder.tip_left #tiptip_arrow_inner {
|
||||
border-left-color: rgba(25, 25, 25, 0.92);
|
||||
margin-left: -7px;
|
||||
margin-top: -6px; }
|
||||
|
||||
@media screen and (-webkit-min-device-pixel-ratio: 0) {
|
||||
#tiptip_content {
|
||||
background-color: rgba(45, 45, 45, 0.88);
|
||||
padding: 4px 8px 5px 8px; }
|
||||
#tiptip_holder.tip_bottom #tiptip_arrow_inner {
|
||||
border-bottom-color: rgba(45, 45, 45, 0.88); }
|
||||
#tiptip_holder.tip_top #tiptip_arrow_inner {
|
||||
border-top-color: rgba(20, 20, 20, 0.92); } }
|
||||
|
||||
.simcal-dismiss-notice {
|
||||
color: #ccc;
|
||||
float: right;
|
||||
margin-top: 9px;
|
||||
text-decoration: none; }
|
||||
.simcal-dismiss-notice:hover {
|
||||
color: #aaa; }
|
||||
.simcal-dismiss-notice:focus, .simcal-dismiss-notice:active {
|
||||
outline: 0; }
|
||||
|
||||
.wp-admin .simcal-field-inline,
|
||||
.wp-admin .simcal-field-inline > input,
|
||||
.wp-admin .simcal-field-inline > select {
|
||||
display: inline-block;
|
||||
vertical-align: baseline; }
|
||||
|
||||
body .simcal-field-tiny,
|
||||
body .simcal-panel-field .simcal-field-tiny {
|
||||
max-width: 60px; }
|
||||
|
||||
body .simcal-field-small,
|
||||
body .simcal-panel-field .simcal-field-small {
|
||||
max-width: 100px; }
|
||||
|
||||
body .simcal-field-textarea,
|
||||
body .simcal-field-select-enhanced {
|
||||
max-width: 500px;
|
||||
width: 100%; }
|
||||
|
||||
.select2-container {
|
||||
z-index: 999999; }
|
||||
|
||||
body .simcal-field-textarea {
|
||||
min-height: 64px;
|
||||
vertical-align: top; }
|
||||
|
||||
.simcal-field-radios > i {
|
||||
margin-left: 5px;
|
||||
vertical-align: middle; }
|
||||
|
||||
.simcal-field-radios-inline {
|
||||
display: inline-block;
|
||||
margin: 0; }
|
||||
.simcal-field-radios-inline > li {
|
||||
display: inline-block;
|
||||
margin-right: 10px; }
|
||||
.simcal-field-radios-inline > li:last-child {
|
||||
margin-right: 0; }
|
||||
|
||||
.simcal-field-bool > input {
|
||||
line-height: 2.4; }
|
||||
|
||||
.simcal-field-date-picker > input[type="text"] {
|
||||
max-width: 120px; }
|
||||
|
||||
#ui-datepicker-div.simcal-date-picker {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
padding: 8px 10px; }
|
||||
#ui-datepicker-div.simcal-date-picker .ui-datepicker-header > a {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin-top: 7px; }
|
||||
#ui-datepicker-div.simcal-date-picker .ui-datepicker-header > a:first-of-type {
|
||||
float: left; }
|
||||
#ui-datepicker-div.simcal-date-picker .ui-datepicker-header > a:last-of-type {
|
||||
float: right; }
|
||||
#ui-datepicker-div.simcal-date-picker .ui-datepicker-header .ui-datepicker-title {
|
||||
margin: 0 10% 4px; }
|
||||
#ui-datepicker-div.simcal-date-picker .ui-datepicker-header .ui-datepicker-title > select {
|
||||
width: 48.5%; }
|
||||
#ui-datepicker-div.simcal-date-picker .ui-datepicker-today {
|
||||
background-color: #eee; }
|
||||
#ui-datepicker-div.simcal-date-picker > table tr td,
|
||||
#ui-datepicker-div.simcal-date-picker > table tr th {
|
||||
padding: 2px 4px;
|
||||
text-align: center; }
|
||||
#ui-datepicker-div.simcal-date-picker > table tr td a,
|
||||
#ui-datepicker-div.simcal-date-picker > table tr th a {
|
||||
text-decoration: none; }
|
||||
|
||||
.simcal-field-datetime-format {
|
||||
padding: 10px 0 5px; }
|
||||
.simcal-field-datetime-format > div {
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
border: 1px dashed rgba(0, 0, 0, 0.18);
|
||||
border-radius: 3px;
|
||||
cursor: move;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin: 0 10px 15px 0;
|
||||
padding: 10px; }
|
||||
.simcal-field-datetime-format select {
|
||||
display: block; }
|
||||
.simcal-field-datetime-format > span {
|
||||
clear: both;
|
||||
display: block; }
|
||||
.simcal-field-datetime-format .ui-sortable-helper {
|
||||
box-shadow: -2px 4px 8px rgba(0, 0, 0, 0.12);
|
||||
transform: rotate(2deg); }
|
||||
|
||||
#simcal-settings-page .simcal-wide-text {
|
||||
width: 40em; }
|
||||
|
||||
#simcal-settings-page .select2 {
|
||||
max-width: 500px; }
|
||||
|
||||
#simcal-settings-page .select2-search__field {
|
||||
border: 0 !important;
|
||||
box-shadow: none !important;
|
||||
margin: 0; }
|
||||
#simcal-settings-page .select2-search__field:focus {
|
||||
border: 0 !important;
|
||||
box-shadow: none !important; }
|
||||
|
||||
#simcal-settings-page .select2-selection {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0; }
|
||||
|
||||
#simcal-settings-page .select2-container--open .select2-selection {
|
||||
border-color: #5b9dd9;
|
||||
box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); }
|
||||
|
||||
.about-wrap .simcal-badge {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0; }
|
||||
|
||||
.simcal-badge {
|
||||
background-image: url("../images/welcome/icon-185x185.png");
|
||||
height: 185px;
|
||||
width: 185px; }
|
||||
|
||||
#simcal-welcome .whats-new-wrap img {
|
||||
margin: 1em 2em 1em 0;
|
||||
border: 1px solid #d6d6d6;
|
||||
box-sizing: border-box;
|
||||
vertical-align: top; }
|
||||
|
||||
#simcal-system-status-report textarea {
|
||||
font-family: monospace;
|
||||
min-height: 200px;
|
||||
padding: 5px 20px;
|
||||
white-space: pre;
|
||||
width: 100%; }
|
||||
|
||||
.simcal-system-status-report-panel {
|
||||
margin: 20px 0; }
|
||||
.simcal-system-status-report-panel thead th {
|
||||
font-weight: bold; }
|
||||
.simcal-system-status-report-panel tbody td,
|
||||
.simcal-system-status-report-panel thead th {
|
||||
font-size: 14px;
|
||||
vertical-align: top; }
|
||||
.simcal-system-status-report-panel tbody .tooltip {
|
||||
text-align: center;
|
||||
width: 20px; }
|
||||
.simcal-system-status-report-panel tbody .label {
|
||||
width: 30%; }
|
||||
.simcal-system-status-report-panel tbody tr:nth-child(odd) td {
|
||||
background-color: rgba(0, 0, 0, 0.02); }
|
||||
.simcal-system-status-report-panel dl {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
.simcal-system-status-report-panel dt {
|
||||
float: left;
|
||||
font-style: italic;
|
||||
margin: 0 4px 0 0; }
|
||||
.simcal-system-status-report-panel dd {
|
||||
margin: 0; }
|
||||
.simcal-system-status-report-panel mark {
|
||||
background-color: transparent;
|
||||
font-weight: bold; }
|
||||
.simcal-system-status-report-panel mark.ok {
|
||||
color: green; }
|
||||
.simcal-system-status-report-panel mark.error {
|
||||
color: red; }
|
||||
|
||||
#simcal-reset-licenses {
|
||||
color: red; }
|
||||
|
||||
.ui-datepicker {
|
||||
left: -9999px;
|
||||
position: absolute; }
|
||||
|
||||
#simcal-clear-cache {
|
||||
float: right;
|
||||
margin: 0 10px 10px; }
|
||||
|
||||
#simcal-get-shortcode .inside {
|
||||
padding: 5px 15px 10px;
|
||||
text-align: center; }
|
||||
|
||||
#simcal-get-shortcode input {
|
||||
width: 100%; }
|
||||
|
||||
#simcal-newsletter {
|
||||
background-color: #fcf8e3; }
|
||||
#simcal-newsletter input {
|
||||
width: 100%; }
|
||||
|
||||
#simcal-calendar-settings {
|
||||
display: none; }
|
||||
#simcal-calendar-settings .hndle {
|
||||
line-height: 2;
|
||||
padding: 10px; }
|
||||
#simcal-calendar-settings .inside {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
#simcal-calendar-settings .select2-container {
|
||||
border-radius: 0;
|
||||
max-width: 500px; }
|
||||
#simcal-calendar-settings .select2-search__field {
|
||||
border: 0 !important;
|
||||
box-shadow: none !important;
|
||||
margin: 0; }
|
||||
#simcal-calendar-settings .select2-search__field:focus {
|
||||
border: 0 !important;
|
||||
box-shadow: none !important; }
|
||||
#simcal-calendar-settings .select2-selection {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 0; }
|
||||
#simcal-calendar-settings .select2-container--open .select2-selection {
|
||||
border-color: #5b9dd9;
|
||||
box-shadow: 0 0 2px rgba(30, 140, 190, 0.8); }
|
||||
#simcal-calendar-settings .select2-selection__choice {
|
||||
margin-bottom: 0; }
|
||||
#simcal-calendar-settings .wp-picker-container {
|
||||
vertical-align: inherit; }
|
||||
|
||||
.simcal-box-handle {
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
margin-left: 8px; }
|
||||
.simcal-box-handle:before {
|
||||
content: '\2014';
|
||||
display: inline-block;
|
||||
font-weight: normal; }
|
||||
.simcal-box-handle label {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
margin-right: 10px;
|
||||
vertical-align: baseline; }
|
||||
.simcal-box-handle select {
|
||||
font-weight: bold;
|
||||
margin: -3px 0 0 .5em;
|
||||
vertical-align: middle; }
|
||||
|
||||
.simcal-tabs {
|
||||
background: #fafafa;
|
||||
border-right: 1px solid #eee;
|
||||
box-sizing: border-box;
|
||||
float: left;
|
||||
line-height: 1em;
|
||||
margin: 0;
|
||||
padding: 0 0 10px;
|
||||
position: relative;
|
||||
width: 20%; }
|
||||
.simcal-tabs a {
|
||||
border-bottom: 1px solid #eee;
|
||||
display: block;
|
||||
line-height: 20px !important;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
text-decoration: none; }
|
||||
.simcal-tabs a:focus {
|
||||
box-shadow: none; }
|
||||
.simcal-tabs li {
|
||||
display: block;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
.simcal-tabs li.active a {
|
||||
background-color: #eee;
|
||||
color: #555;
|
||||
position: relative; }
|
||||
.simcal-tabs:after {
|
||||
background-color: #fafafa;
|
||||
border-right: 1px solid #eee;
|
||||
bottom: -9999em;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 9999em;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 100%; }
|
||||
|
||||
.simcal-panels-wrap {
|
||||
background: #fff;
|
||||
overflow: hidden; }
|
||||
|
||||
.simcal-panel {
|
||||
margin-left: 20%;
|
||||
max-width: 80%; }
|
||||
.simcal-panel > table {
|
||||
padding-bottom: 11px;
|
||||
width: 100%; }
|
||||
.simcal-panel > table thead th {
|
||||
border-bottom: 1px solid #eee;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
padding: 12px 0 15px 10px;
|
||||
text-align: left; }
|
||||
.simcal-panel > table > tbody tr:first-child td,
|
||||
.simcal-panel > table > tbody tr:first-child th {
|
||||
padding-top: 14px; }
|
||||
.simcal-panel > table > tbody tr:last-child td,
|
||||
.simcal-panel > table > tbody tr:last-child th {
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 14px; }
|
||||
.simcal-panel > table > tbody:last-of-type tr:last-child td,
|
||||
.simcal-panel > table > tbody:last-of-type tr:last-child th {
|
||||
border-bottom: 0; }
|
||||
|
||||
.simcal-panel-field > td {
|
||||
width: 82%; }
|
||||
|
||||
.simcal-panel-field > th {
|
||||
font-weight: normal;
|
||||
min-width: 100px;
|
||||
width: 15%; }
|
||||
|
||||
.simcal-panel-field > td,
|
||||
.simcal-panel-field > th {
|
||||
padding: 9px 3% 9px 10px;
|
||||
text-align: left;
|
||||
vertical-align: text-top; }
|
||||
|
||||
.simcal-panel-field .simcal-field-text {
|
||||
max-width: 500px;
|
||||
width: 90%; }
|
||||
|
||||
@media screen and (max-width: 1023px) {
|
||||
.simcal-box-handle {
|
||||
display: block;
|
||||
line-height: 2;
|
||||
margin: 16px 0 0; }
|
||||
.simcal-box-handle:before {
|
||||
display: none; }
|
||||
.simcal-box-handle label {
|
||||
display: table;
|
||||
margin-bottom: 16px;
|
||||
width: 100%; }
|
||||
.simcal-box-handle label > span {
|
||||
display: table-cell;
|
||||
width: 20%; }
|
||||
.simcal-box-handle label > select {
|
||||
display: table-cell;
|
||||
width: 80%; }
|
||||
.simcal-box-handle .simcal-tabs {
|
||||
width: 16%; }
|
||||
.simcal-box-handle .simcal-tabs i {
|
||||
font-size: 18px;
|
||||
line-height: 1; }
|
||||
.simcal-box-handle .simcal-tabs span {
|
||||
display: none; }
|
||||
.simcal-box-handle .simcal-panel {
|
||||
margin-left: 16%;
|
||||
max-width: 84%; }
|
||||
.simcal-box-handle .simcal-panel-section {
|
||||
display: block;
|
||||
overflow: hidden; }
|
||||
.simcal-box-handle .simcal-panel-field th {
|
||||
display: block;
|
||||
width: 100%; }
|
||||
.simcal-box-handle .simcal-panel-field td {
|
||||
display: inline-block;
|
||||
width: 100%; }
|
||||
.simcal-box-handle .simcal-panel-field select {
|
||||
max-width: 86%; } }
|
||||
|
||||
input.simcal-shortcode {
|
||||
border: dashed 1px rgba(0, 0, 0, 0.3);
|
||||
color: rgba(0, 0, 0, 0.58);
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
text-align: center; }
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
@font-face{font-family:simple-calendar;src:url(../fonts/simple-calendar.eot?43976014);src:url(../fonts/simple-calendar.eot?43976014#iefix) format("embedded-opentype"),url(../fonts/simple-calendar.woff?43976014) format("woff"),url(../fonts/simple-calendar.ttf?43976014) format("truetype"),url(../fonts/simple-calendar.svg?43976014#simple-calendar) format("svg");font-weight:400;font-style:normal}[class*=" simcal-icon-"]:before,[class^=simcal-icon-]:before{display:inline-block;font-family:simple-calendar;font-style:normal;font-weight:400;margin-right:.2em;speak:none;text-decoration:inherit;text-align:center;width:1em;font-variant:normal;text-transform:none;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}#ui-datepicker-div.simcal-date-picker>table tr td a,#ui-datepicker-div.simcal-date-picker>table tr th a,.simcal-tabs a{text-decoration:none}.simcal-icon-spin{animation:spin 2s infinite linear;display:inline-block}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(359deg)}}.simcal-icon-animate:before{transition:all .2s ease-in-out}.simcal-icon-rotate-180:before{transform:rotate(180deg)}.simcal-icon-calendar-empty:before{content:'\e800'}.simcal-icon-calendar:before{content:'\e801'}.simcal-icon-calendar-logo:before{content:'\e802'}.simcal-icon-settings:before{content:'\e804'}.simcal-icon-toggles:before{content:'\e805'}.simcal-icon-list:before{content:'\e806'}.simcal-icon-event:before{content:'\e807'}.simcal-icon-help:before{content:'\e808'}.simcal-icon-panel:before{content:'\e80a'}.simcal-icon-grid:before{content:'\e80b'}.simcal-icon-google:before{content:'\e80c'}.simcal-icon-docs:before{content:'\e80f'}.simcal-icon-hourglass:before{content:'\e811'}.simcal-icon-globe:before{content:'\e812'}.simcal-icon-timezones:before{content:'\e813'}.simcal-icon-warning:before{content:'\e815'}.simcal-icon-wordpress:before{content:'\e814'}.simcal-icon-up:before{content:'\e80e'}.simcal-icon-right:before{content:'\e809'}.simcal-icon-down:before{content:'\e80d'}.simcal-icon-left:before{content:'\e803'}.simcal-icon-spinner:before{content:'\e810'}.simcal-help-tip{color:rgba(0,0,0,.46);cursor:help}#tiptip_holder{display:none;left:0;position:absolute;top:0;z-index:9999999}#tiptip_holder.tip_top{padding-bottom:5px}#tiptip_holder.tip_bottom{padding-top:5px}#tiptip_holder.tip_right{padding-left:5px}#tiptip_holder.tip_left{padding-right:5px}#tiptip_content{background-color:rgba(25,25,25,.92);border:1px solid rgba(255,255,255,.25);border-radius:3px;color:#fff;font-size:11px;padding:4px 8px}#tiptip_arrow,#tiptip_arrow_inner{border-color:transparent;border-style:solid;border-width:6px;height:0;position:absolute;width:0}#tiptip_holder.tip_top #tiptip_arrow_inner{border-top-color:rgba(25,25,25,.92);margin-left:-6px;margin-top:-7px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{border-bottom-color:rgba(25,25,25,.92);margin-left:-6px;margin-top:-5px}#tiptip_holder.tip_right #tiptip_arrow_inner{border-right-color:rgba(25,25,25,.92);margin-left:-5px;margin-top:-6px}#tiptip_holder.tip_left #tiptip_arrow_inner{border-left-color:rgba(25,25,25,.92);margin-left:-7px;margin-top:-6px}@media screen and (-webkit-min-device-pixel-ratio:0){#tiptip_content{background-color:rgba(45,45,45,.88);padding:4px 8px 5px}#tiptip_holder.tip_bottom #tiptip_arrow_inner{border-bottom-color:rgba(45,45,45,.88)}#tiptip_holder.tip_top #tiptip_arrow_inner{border-top-color:rgba(20,20,20,.92)}}.simcal-dismiss-notice{color:#ccc;float:right;margin-top:9px;text-decoration:none}.simcal-dismiss-notice:hover{color:#aaa}.simcal-dismiss-notice:active,.simcal-dismiss-notice:focus{outline:0}.wp-admin .simcal-field-inline,.wp-admin .simcal-field-inline>input,.wp-admin .simcal-field-inline>select{display:inline-block;vertical-align:baseline}body .simcal-field-tiny,body .simcal-panel-field .simcal-field-tiny{max-width:60px}body .simcal-field-small,body .simcal-panel-field .simcal-field-small{max-width:100px}body .simcal-field-select-enhanced,body .simcal-field-textarea{max-width:500px;width:100%}.select2-container{z-index:999999}body .simcal-field-textarea{min-height:64px;vertical-align:top}.simcal-field-radios>i{margin-left:5px;vertical-align:middle}.simcal-field-radios-inline{display:inline-block;margin:0}.simcal-field-radios-inline>li{display:inline-block;margin-right:10px}.simcal-field-radios-inline>li:last-child{margin-right:0}.simcal-field-bool>input{line-height:2.4}.simcal-field-date-picker>input[type=text]{max-width:120px}#ui-datepicker-div.simcal-date-picker{background-color:#fff;box-shadow:0 2px 10px rgba(0,0,0,.1);padding:8px 10px}#ui-datepicker-div.simcal-date-picker .ui-datepicker-header>a{display:inline-block;cursor:pointer;margin-top:7px}#ui-datepicker-div.simcal-date-picker .ui-datepicker-header>a:first-of-type{float:left}#ui-datepicker-div.simcal-date-picker .ui-datepicker-header>a:last-of-type{float:right}#ui-datepicker-div.simcal-date-picker .ui-datepicker-header .ui-datepicker-title{margin:0 10% 4px}#ui-datepicker-div.simcal-dateLine truncated
|
||||
@@ -1,366 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'simple-calendar';
|
||||
src: url("../fonts/simple-calendar.eot?43976014");
|
||||
src: url("../fonts/simple-calendar.eot?43976014#iefix") format("embedded-opentype"), url("../fonts/simple-calendar.woff?43976014") format("woff"), url("../fonts/simple-calendar.ttf?43976014") format("truetype"), url("../fonts/simple-calendar.svg?43976014#simple-calendar") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal; }
|
||||
|
||||
[class^="simcal-icon-"]:before,
|
||||
[class*=" simcal-icon-"]:before {
|
||||
display: inline-block;
|
||||
font-family: "simple-calendar";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
margin-right: .2em;
|
||||
speak: none;
|
||||
text-decoration: inherit;
|
||||
text-align: center;
|
||||
width: 1em;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
margin-left: .2em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale; }
|
||||
|
||||
.simcal-icon-spin {
|
||||
animation: spin 2s infinite linear;
|
||||
display: inline-block; }
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg); } }
|
||||
|
||||
.simcal-icon-animate:before {
|
||||
transition: all .2s ease-in-out; }
|
||||
|
||||
.simcal-icon-rotate-180:before {
|
||||
transform: rotate(180deg); }
|
||||
|
||||
.simcal-icon-calendar-empty:before {
|
||||
content: '\e800'; }
|
||||
|
||||
.simcal-icon-calendar:before {
|
||||
content: '\e801'; }
|
||||
|
||||
.simcal-icon-calendar-logo:before {
|
||||
content: '\e802'; }
|
||||
|
||||
.simcal-icon-settings:before {
|
||||
content: '\e804'; }
|
||||
|
||||
.simcal-icon-toggles:before {
|
||||
content: '\e805'; }
|
||||
|
||||
.simcal-icon-list:before {
|
||||
content: '\e806'; }
|
||||
|
||||
.simcal-icon-event:before {
|
||||
content: '\e807'; }
|
||||
|
||||
.simcal-icon-help:before {
|
||||
content: '\e808'; }
|
||||
|
||||
.simcal-icon-panel:before {
|
||||
content: '\e80a'; }
|
||||
|
||||
.simcal-icon-grid:before {
|
||||
content: '\e80b'; }
|
||||
|
||||
.simcal-icon-google:before {
|
||||
content: '\e80c'; }
|
||||
|
||||
.simcal-icon-docs:before {
|
||||
content: '\e80f'; }
|
||||
|
||||
.simcal-icon-hourglass:before {
|
||||
content: '\e811'; }
|
||||
|
||||
.simcal-icon-globe:before {
|
||||
content: '\e812'; }
|
||||
|
||||
.simcal-icon-timezones:before {
|
||||
content: '\e813'; }
|
||||
|
||||
.simcal-icon-warning:before {
|
||||
content: '\e815'; }
|
||||
|
||||
.simcal-icon-wordpress:before {
|
||||
content: '\e814'; }
|
||||
|
||||
.simcal-icon-up:before {
|
||||
content: '\e80e'; }
|
||||
|
||||
.simcal-icon-right:before {
|
||||
content: '\e809'; }
|
||||
|
||||
.simcal-icon-down:before {
|
||||
content: '\e80d'; }
|
||||
|
||||
.simcal-icon-left:before {
|
||||
content: '\e803'; }
|
||||
|
||||
.simcal-icon-spinner:before {
|
||||
content: '\e810'; }
|
||||
|
||||
.simcal-calendar {
|
||||
position: relative; }
|
||||
|
||||
.simcal-powered {
|
||||
display: block;
|
||||
margin: -10px 0 20px; }
|
||||
|
||||
.simcal-align-left {
|
||||
text-align: left; }
|
||||
|
||||
.simcal-align-right {
|
||||
text-align: right; }
|
||||
|
||||
.simcal-default-calendar .simcal-current h3 {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.simcal-default-calendar .simcal-nav {
|
||||
vertical-align: middle; }
|
||||
|
||||
.simcal-default-calendar .simcal-nav-button {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
transition: margin .2s ease-out;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar .simcal-nav-button:focus, .simcal-default-calendar .simcal-nav-button:hover {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: none; }
|
||||
.simcal-default-calendar .simcal-nav-button.simcal-prev:hover {
|
||||
margin-left: -10px; }
|
||||
.simcal-default-calendar .simcal-nav-button.simcal-next:hover {
|
||||
margin-right: -10px; }
|
||||
.simcal-default-calendar .simcal-nav-button:disabled {
|
||||
cursor: default; }
|
||||
.simcal-default-calendar .simcal-nav-button:disabled:hover {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.simcal-default-calendar .simcal-events {
|
||||
list-style: none;
|
||||
margin-left: 0; }
|
||||
|
||||
.simcal-default-calendar .simcal-events-toggle {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
text-align: center;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar .simcal-events-toggle:active, .simcal-default-calendar .simcal-events-toggle:focus, .simcal-default-calendar .simcal-events-toggle:hover {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: none; }
|
||||
|
||||
.simcal-default-calendar ul.simcal-attachments,
|
||||
.simcal-default-calendar ul.simcal-attendees {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.simcal-default-calendar li.simcal-attachment,
|
||||
.simcal-default-calendar li.simcal-attendee {
|
||||
list-style: none;
|
||||
margin-bottom: 4px; }
|
||||
.simcal-default-calendar li.simcal-attachment:last-child,
|
||||
.simcal-default-calendar li.simcal-attendee:last-child {
|
||||
margin-bottom: 0; }
|
||||
.simcal-default-calendar li.simcal-attachment small,
|
||||
.simcal-default-calendar li.simcal-attendee small {
|
||||
opacity: .9;
|
||||
text-transform: lowercase; }
|
||||
|
||||
.simcal-default-calendar li.simcal-attachment a,
|
||||
.simcal-default-calendar li.simcal-attendee a,
|
||||
.simcal-default-calendar .simcal-organizer a {
|
||||
border-bottom: 0;
|
||||
text-decoration: none; }
|
||||
|
||||
.simcal-default-calendar li.simcal-attachment img,
|
||||
.simcal-default-calendar li.simcal-attendee img,
|
||||
.simcal-default-calendar .simcal-organizer img {
|
||||
display: inline-block;
|
||||
margin: 0 4px;
|
||||
max-height: 24px;
|
||||
max-width: 24px; }
|
||||
|
||||
.simcal-default-calendar .simcal-tooltip-content {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.4;
|
||||
padding: 5px; }
|
||||
|
||||
.simcal-default-calendar .simcal-ajax-loader {
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar .simcal-ajax-loader > i {
|
||||
font-size: 48px;
|
||||
left: 50%;
|
||||
line-height: 1;
|
||||
margin: -36px 0 0 -36px;
|
||||
position: absolute;
|
||||
top: 50%; }
|
||||
.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-top > i {
|
||||
top: 20%; }
|
||||
.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-bottom > i {
|
||||
bottom: 20%;
|
||||
top: auto; }
|
||||
|
||||
.simcal-default-calendar-light .simcal-nav-button {
|
||||
color: rgba(0, 0, 0, 0.6); }
|
||||
.simcal-default-calendar-light .simcal-nav-button:disabled {
|
||||
color: rgba(255, 255, 255, 0.9) !important; }
|
||||
.simcal-default-calendar-light .simcal-nav-button:disabled:hover {
|
||||
color: rgba(255, 255, 255, 0.9) !important; }
|
||||
.simcal-default-calendar-light .simcal-nav-button:focus, .simcal-default-calendar-light .simcal-nav-button:hover {
|
||||
color: rgba(0, 0, 0, 0.9); }
|
||||
|
||||
.simcal-default-calendar-light .simcal-events-toggle {
|
||||
color: rgba(0, 0, 0, 0.6); }
|
||||
.simcal-default-calendar-light .simcal-events-toggle:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
color: white; }
|
||||
|
||||
.simcal-default-calendar-light .simcal-ajax-loader {
|
||||
background-color: rgba(0, 0, 0, 0.1); }
|
||||
.simcal-default-calendar-light .simcal-ajax-loader > i {
|
||||
color: rgba(0, 0, 0, 0.3); }
|
||||
|
||||
.simcal-default-calendar-dark .simcal-nav-button {
|
||||
color: rgba(255, 255, 255, 0.6); }
|
||||
.simcal-default-calendar-dark .simcal-nav-button:disabled {
|
||||
color: rgba(0, 0, 0, 0.9) !important; }
|
||||
.simcal-default-calendar-dark .simcal-nav-button:disabled:hover {
|
||||
color: rgba(0, 0, 0, 0.9) !important; }
|
||||
.simcal-default-calendar-dark .simcal-nav-button:focus, .simcal-default-calendar-dark .simcal-nav-button:hover {
|
||||
color: rgba(255, 255, 255, 0.9); }
|
||||
|
||||
.simcal-default-calendar-dark .simcal-events-toggle {
|
||||
color: rgba(255, 255, 255, 0.6); }
|
||||
.simcal-default-calendar-dark .simcal-events-toggle:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: black; }
|
||||
|
||||
.simcal-default-calendar-dark .simcal-ajax-loader {
|
||||
background-color: rgba(255, 255, 255, 0.1); }
|
||||
.simcal-default-calendar-dark .simcal-ajax-loader > i {
|
||||
color: rgba(255, 255, 255, 0.3); }
|
||||
|
||||
.simcal-default-calendar-grid > table {
|
||||
table-layout: fixed;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar-grid > table thead th,
|
||||
.simcal-default-calendar-grid > table tbody td {
|
||||
text-align: center;
|
||||
vertical-align: top; }
|
||||
.simcal-default-calendar-grid > table tbody td {
|
||||
padding: 0 !important; }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-calendar-head .simcal-nav {
|
||||
padding: 10px 0;
|
||||
vertical-align: middle; }
|
||||
.simcal-default-calendar-grid .simcal-calendar-head .simcal-nav.simcal-prev-wrapper, .simcal-default-calendar-grid .simcal-calendar-head .simcal-nav.simcal-current {
|
||||
border-right: 0; }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-day > div {
|
||||
box-sizing: content-box;
|
||||
display: block;
|
||||
height: 100%; }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-day-void {
|
||||
border-width: 0 0 1px 0;
|
||||
height: 100%;
|
||||
min-height: 32px; }
|
||||
.simcal-default-calendar-grid .simcal-day-void.simcal-day-void-last {
|
||||
border-right-width: 1px; }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-day-number {
|
||||
display: block;
|
||||
line-height: 1;
|
||||
padding: 2px 4px 3px;
|
||||
vertical-align: middle; }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-no-events {
|
||||
display: block;
|
||||
min-height: 32px; }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-light .simcal-day:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1); }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-light .simcal-day-void {
|
||||
background-color: rgba(0, 0, 0, 0.04); }
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-light .simcal-day-void:hover {
|
||||
background-color: rgba(0, 0, 0, 0.04); }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-light .simcal-day-number {
|
||||
background: rgba(0, 0, 0, 0.1); }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-dark .simcal-day:hover {
|
||||
background-color: rgba(255, 255, 255, 0.18); }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-dark .simcal-day-void {
|
||||
background-color: rgba(255, 255, 255, 0.05); }
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-dark .simcal-day-void:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05); }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-dark .simcal-day-number {
|
||||
background: rgba(255, 255, 255, 0.1); }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-events {
|
||||
font-size: .68em;
|
||||
line-height: 1.4;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: left; }
|
||||
.simcal-default-calendar-grid .simcal-events > .simcal-event {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
cursor: pointer;
|
||||
list-style: none;
|
||||
margin: 0 0 2px 0;
|
||||
padding: 4px; }
|
||||
.simcal-default-calendar-grid .simcal-events > .simcal-event:hover {
|
||||
text-decoration: underline; }
|
||||
.simcal-default-calendar-grid .simcal-events > .simcal-event:last-child {
|
||||
border-bottom: 0;
|
||||
margin-bottom: 0; }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-light .simcal-event {
|
||||
border-bottom-color: rgba(0, 0, 0, 0.1); }
|
||||
|
||||
.simcal-default-calendar-grid.simcal-default-calendar-dark .simcal-event {
|
||||
border-bottom-color: rgba(255, 255, 255, 0.1); }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-events-dots {
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
line-height: .7;
|
||||
margin: 3px 0;
|
||||
text-align: center; }
|
||||
|
||||
.simcal-default-calendar-grid .simcal-events-toggle {
|
||||
background: transparent;
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
padding: 2px 0; }
|
||||
|
||||
.simcal-event-bubble {
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); }
|
||||
.simcal-event-bubble .simcal-event-details p,
|
||||
.simcal-event-bubble .simcal-event-details .simcal-event-description {
|
||||
margin: 0 0 1em; }
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
.simcal-default-calendar .simcal-nav-button,.simcal-default-calendar .simcal-nav-button:focus,.simcal-default-calendar .simcal-nav-button:hover{background:0 0;border:0;box-shadow:none;outline:0}@font-face{font-family:simple-calendar;src:url(../fonts/simple-calendar.eot?43976014);src:url(../fonts/simple-calendar.eot?43976014#iefix) format("embedded-opentype"),url(../fonts/simple-calendar.woff?43976014) format("woff"),url(../fonts/simple-calendar.ttf?43976014) format("truetype"),url(../fonts/simple-calendar.svg?43976014#simple-calendar) format("svg");font-weight:400;font-style:normal}[class*=" simcal-icon-"]:before,[class^=simcal-icon-]:before{display:inline-block;font-family:simple-calendar;font-style:normal;font-weight:400;margin-right:.2em;speak:none;text-decoration:inherit;text-align:center;width:1em;font-variant:normal;text-transform:none;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.simcal-icon-spin{animation:spin 2s infinite linear;display:inline-block}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(359deg)}}.simcal-icon-animate:before{transition:all .2s ease-in-out}.simcal-icon-rotate-180:before{transform:rotate(180deg)}.simcal-icon-calendar-empty:before{content:'\e800'}.simcal-icon-calendar:before{content:'\e801'}.simcal-icon-calendar-logo:before{content:'\e802'}.simcal-icon-settings:before{content:'\e804'}.simcal-icon-toggles:before{content:'\e805'}.simcal-icon-list:before{content:'\e806'}.simcal-icon-event:before{content:'\e807'}.simcal-icon-help:before{content:'\e808'}.simcal-icon-panel:before{content:'\e80a'}.simcal-icon-grid:before{content:'\e80b'}.simcal-icon-google:before{content:'\e80c'}.simcal-icon-docs:before{content:'\e80f'}.simcal-icon-hourglass:before{content:'\e811'}.simcal-icon-globe:before{content:'\e812'}.simcal-icon-timezones:before{content:'\e813'}.simcal-icon-warning:before{content:'\e815'}.simcal-icon-wordpress:before{content:'\e814'}.simcal-icon-up:before{content:'\e80e'}.simcal-icon-right:before{content:'\e809'}.simcal-icon-down:before{content:'\e80d'}.simcal-icon-left:before{content:'\e803'}.simcal-icon-spinner:before{content:'\e810'}.simcal-calendar{position:relative}.simcal-powered{display:block;margin:-10px 0 20px}.simcal-align-left{text-align:left}.simcal-align-right{text-align:right}.simcal-default-calendar .simcal-current h3{margin:0;padding:0}.simcal-default-calendar .simcal-nav{vertical-align:middle}.simcal-default-calendar .simcal-nav-button{cursor:pointer;margin:0;padding:0;transition:margin .2s ease-out;width:100%}.simcal-default-calendar .simcal-nav-button.simcal-prev:hover{margin-left:-10px}.simcal-default-calendar .simcal-nav-button.simcal-next:hover{margin-right:-10px}.simcal-default-calendar .simcal-nav-button:disabled:hover,.simcal-default-calendar ul.simcal-attachments,.simcal-default-calendar ul.simcal-attendees{margin:0;padding:0}.simcal-default-calendar .simcal-nav-button:disabled{cursor:default}.simcal-default-calendar .simcal-events{list-style:none;margin-left:0}.simcal-default-calendar .simcal-events-toggle{border:0;box-shadow:none;text-align:center;width:100%}.simcal-default-calendar .simcal-events-toggle:active,.simcal-default-calendar .simcal-events-toggle:focus,.simcal-default-calendar .simcal-events-toggle:hover{border:0;box-shadow:none;outline:0}.simcal-default-calendar li.simcal-attachment,.simcal-default-calendar li.simcal-attendee{list-style:none;margin-bottom:4px}.simcal-default-calendar li.simcal-attachment:last-child,.simcal-default-calendar li.simcal-attendee:last-child{margin-bottom:0}.simcal-default-calendar li.simcal-attachment small,.simcal-default-calendar li.simcal-attendee small{opacity:.9;text-transform:lowercase}.simcal-default-calendar .simcal-organizer a,.simcal-default-calendar li.simcal-attachment a,.simcal-default-calendar li.simcal-attendee a{border-bottom:0;text-decoration:none}.simcal-default-calendar .simcal-organizer img,.simcal-default-calendar li.simcal-attachment img,.simcal-default-calendar li.simcal-attendee img{display:inline-block;margin:0 4px;max-height:24px;max-width:24px}.simcal-default-calendar .simcal-tooltip-content{font-size:1.2em;line-height:1.4;padding:5px}.simcal-default-calendar .simcal-ajax-loader{height:100%;left:0;position:absolute;top:0;width:100%}.simcal-default-calendar .simcal-ajax-loader>i{font-size:48px;left:50%;line-height:1;margin:-36px 0 0 -36px;position:absolute;top:50%}.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-top>i{top:20%}.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-bottom>i{bottom:20%;top:auto}.simcal-default-calendar-light .simcal-nav-button{color:rgba(0,0,0,.6)}.simcal-default-calendar-light .simcal-nav-button:disabled,.simcal-default-calendar-light .simcal-nav-button:disabled:hover{color:rgba(255,255,255,.9)!important}.simcal-default-calendar-light .simcal-nav-button:focus,.simcal-default-calendar-light .simcal-nav-button:hover{color:rgba(0,0,0,.9)}.simcal-default-calendar-light .simcal-events-toggLine truncated
|
||||
@@ -1,314 +0,0 @@
|
||||
@font-face {
|
||||
font-family: 'simple-calendar';
|
||||
src: url("../fonts/simple-calendar.eot?43976014");
|
||||
src: url("../fonts/simple-calendar.eot?43976014#iefix") format("embedded-opentype"), url("../fonts/simple-calendar.woff?43976014") format("woff"), url("../fonts/simple-calendar.ttf?43976014") format("truetype"), url("../fonts/simple-calendar.svg?43976014#simple-calendar") format("svg");
|
||||
font-weight: normal;
|
||||
font-style: normal; }
|
||||
|
||||
[class^="simcal-icon-"]:before,
|
||||
[class*=" simcal-icon-"]:before {
|
||||
display: inline-block;
|
||||
font-family: "simple-calendar";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
margin-right: .2em;
|
||||
speak: none;
|
||||
text-decoration: inherit;
|
||||
text-align: center;
|
||||
width: 1em;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
margin-left: .2em;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale; }
|
||||
|
||||
.simcal-icon-spin {
|
||||
animation: spin 2s infinite linear;
|
||||
display: inline-block; }
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
transform: rotate(359deg); } }
|
||||
|
||||
.simcal-icon-animate:before {
|
||||
transition: all .2s ease-in-out; }
|
||||
|
||||
.simcal-icon-rotate-180:before {
|
||||
transform: rotate(180deg); }
|
||||
|
||||
.simcal-icon-calendar-empty:before {
|
||||
content: '\e800'; }
|
||||
|
||||
.simcal-icon-calendar:before {
|
||||
content: '\e801'; }
|
||||
|
||||
.simcal-icon-calendar-logo:before {
|
||||
content: '\e802'; }
|
||||
|
||||
.simcal-icon-settings:before {
|
||||
content: '\e804'; }
|
||||
|
||||
.simcal-icon-toggles:before {
|
||||
content: '\e805'; }
|
||||
|
||||
.simcal-icon-list:before {
|
||||
content: '\e806'; }
|
||||
|
||||
.simcal-icon-event:before {
|
||||
content: '\e807'; }
|
||||
|
||||
.simcal-icon-help:before {
|
||||
content: '\e808'; }
|
||||
|
||||
.simcal-icon-panel:before {
|
||||
content: '\e80a'; }
|
||||
|
||||
.simcal-icon-grid:before {
|
||||
content: '\e80b'; }
|
||||
|
||||
.simcal-icon-google:before {
|
||||
content: '\e80c'; }
|
||||
|
||||
.simcal-icon-docs:before {
|
||||
content: '\e80f'; }
|
||||
|
||||
.simcal-icon-hourglass:before {
|
||||
content: '\e811'; }
|
||||
|
||||
.simcal-icon-globe:before {
|
||||
content: '\e812'; }
|
||||
|
||||
.simcal-icon-timezones:before {
|
||||
content: '\e813'; }
|
||||
|
||||
.simcal-icon-warning:before {
|
||||
content: '\e815'; }
|
||||
|
||||
.simcal-icon-wordpress:before {
|
||||
content: '\e814'; }
|
||||
|
||||
.simcal-icon-up:before {
|
||||
content: '\e80e'; }
|
||||
|
||||
.simcal-icon-right:before {
|
||||
content: '\e809'; }
|
||||
|
||||
.simcal-icon-down:before {
|
||||
content: '\e80d'; }
|
||||
|
||||
.simcal-icon-left:before {
|
||||
content: '\e803'; }
|
||||
|
||||
.simcal-icon-spinner:before {
|
||||
content: '\e810'; }
|
||||
|
||||
.simcal-calendar {
|
||||
position: relative; }
|
||||
|
||||
.simcal-powered {
|
||||
display: block;
|
||||
margin: -10px 0 20px; }
|
||||
|
||||
.simcal-align-left {
|
||||
text-align: left; }
|
||||
|
||||
.simcal-align-right {
|
||||
text-align: right; }
|
||||
|
||||
.simcal-default-calendar .simcal-current h3 {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.simcal-default-calendar .simcal-nav {
|
||||
vertical-align: middle; }
|
||||
|
||||
.simcal-default-calendar .simcal-nav-button {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
transition: margin .2s ease-out;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar .simcal-nav-button:focus, .simcal-default-calendar .simcal-nav-button:hover {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: none; }
|
||||
.simcal-default-calendar .simcal-nav-button.simcal-prev:hover {
|
||||
margin-left: -10px; }
|
||||
.simcal-default-calendar .simcal-nav-button.simcal-next:hover {
|
||||
margin-right: -10px; }
|
||||
.simcal-default-calendar .simcal-nav-button:disabled {
|
||||
cursor: default; }
|
||||
.simcal-default-calendar .simcal-nav-button:disabled:hover {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.simcal-default-calendar .simcal-events {
|
||||
list-style: none;
|
||||
margin-left: 0; }
|
||||
|
||||
.simcal-default-calendar .simcal-events-toggle {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
text-align: center;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar .simcal-events-toggle:active, .simcal-default-calendar .simcal-events-toggle:focus, .simcal-default-calendar .simcal-events-toggle:hover {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
outline: none; }
|
||||
|
||||
.simcal-default-calendar ul.simcal-attachments,
|
||||
.simcal-default-calendar ul.simcal-attendees {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.simcal-default-calendar li.simcal-attachment,
|
||||
.simcal-default-calendar li.simcal-attendee {
|
||||
list-style: none;
|
||||
margin-bottom: 4px; }
|
||||
.simcal-default-calendar li.simcal-attachment:last-child,
|
||||
.simcal-default-calendar li.simcal-attendee:last-child {
|
||||
margin-bottom: 0; }
|
||||
.simcal-default-calendar li.simcal-attachment small,
|
||||
.simcal-default-calendar li.simcal-attendee small {
|
||||
opacity: .9;
|
||||
text-transform: lowercase; }
|
||||
|
||||
.simcal-default-calendar li.simcal-attachment a,
|
||||
.simcal-default-calendar li.simcal-attendee a,
|
||||
.simcal-default-calendar .simcal-organizer a {
|
||||
border-bottom: 0;
|
||||
text-decoration: none; }
|
||||
|
||||
.simcal-default-calendar li.simcal-attachment img,
|
||||
.simcal-default-calendar li.simcal-attendee img,
|
||||
.simcal-default-calendar .simcal-organizer img {
|
||||
display: inline-block;
|
||||
margin: 0 4px;
|
||||
max-height: 24px;
|
||||
max-width: 24px; }
|
||||
|
||||
.simcal-default-calendar .simcal-tooltip-content {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.4;
|
||||
padding: 5px; }
|
||||
|
||||
.simcal-default-calendar .simcal-ajax-loader {
|
||||
height: 100%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar .simcal-ajax-loader > i {
|
||||
font-size: 48px;
|
||||
left: 50%;
|
||||
line-height: 1;
|
||||
margin: -36px 0 0 -36px;
|
||||
position: absolute;
|
||||
top: 50%; }
|
||||
.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-top > i {
|
||||
top: 20%; }
|
||||
.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-bottom > i {
|
||||
bottom: 20%;
|
||||
top: auto; }
|
||||
|
||||
.simcal-default-calendar-light .simcal-nav-button {
|
||||
color: rgba(0, 0, 0, 0.6); }
|
||||
.simcal-default-calendar-light .simcal-nav-button:disabled {
|
||||
color: rgba(255, 255, 255, 0.9) !important; }
|
||||
.simcal-default-calendar-light .simcal-nav-button:disabled:hover {
|
||||
color: rgba(255, 255, 255, 0.9) !important; }
|
||||
.simcal-default-calendar-light .simcal-nav-button:focus, .simcal-default-calendar-light .simcal-nav-button:hover {
|
||||
color: rgba(0, 0, 0, 0.9); }
|
||||
|
||||
.simcal-default-calendar-light .simcal-events-toggle {
|
||||
color: rgba(0, 0, 0, 0.6); }
|
||||
.simcal-default-calendar-light .simcal-events-toggle:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
color: white; }
|
||||
|
||||
.simcal-default-calendar-light .simcal-ajax-loader {
|
||||
background-color: rgba(0, 0, 0, 0.1); }
|
||||
.simcal-default-calendar-light .simcal-ajax-loader > i {
|
||||
color: rgba(0, 0, 0, 0.3); }
|
||||
|
||||
.simcal-default-calendar-dark .simcal-nav-button {
|
||||
color: rgba(255, 255, 255, 0.6); }
|
||||
.simcal-default-calendar-dark .simcal-nav-button:disabled {
|
||||
color: rgba(0, 0, 0, 0.9) !important; }
|
||||
.simcal-default-calendar-dark .simcal-nav-button:disabled:hover {
|
||||
color: rgba(0, 0, 0, 0.9) !important; }
|
||||
.simcal-default-calendar-dark .simcal-nav-button:focus, .simcal-default-calendar-dark .simcal-nav-button:hover {
|
||||
color: rgba(255, 255, 255, 0.9); }
|
||||
|
||||
.simcal-default-calendar-dark .simcal-events-toggle {
|
||||
color: rgba(255, 255, 255, 0.6); }
|
||||
.simcal-default-calendar-dark .simcal-events-toggle:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
color: black; }
|
||||
|
||||
.simcal-default-calendar-dark .simcal-ajax-loader {
|
||||
background-color: rgba(255, 255, 255, 0.1); }
|
||||
.simcal-default-calendar-dark .simcal-ajax-loader > i {
|
||||
color: rgba(255, 255, 255, 0.3); }
|
||||
|
||||
.simcal-default-calendar-list {
|
||||
min-height: 100px;
|
||||
padding: 10px 0;
|
||||
text-align: left; }
|
||||
.simcal-default-calendar-list .simcal-calendar-head {
|
||||
display: table;
|
||||
padding-bottom: 10px;
|
||||
width: 100%; }
|
||||
.simcal-default-calendar-list .simcal-calendar-head .simcal-nav {
|
||||
display: table-cell;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
width: 20%; }
|
||||
.simcal-default-calendar-list .simcal-calendar-head .simcal-nav:nth-child(2) {
|
||||
width: 60%; }
|
||||
.simcal-default-calendar-list .simcal-calendar-head .simcal-current span {
|
||||
display: inline-block; }
|
||||
.simcal-default-calendar-list .simcal-calendar-head .simcal-hide-header {
|
||||
visibility: hidden; }
|
||||
.simcal-default-calendar-list dl.simcal-month {
|
||||
margin-bottom: 10px;
|
||||
padding: 0 10px 10px; }
|
||||
.simcal-default-calendar-list dd.simcal-day {
|
||||
list-style: none;
|
||||
margin: 0; }
|
||||
.simcal-default-calendar-list dt.simcal-day-label {
|
||||
font-size: .9em;
|
||||
list-style: none;
|
||||
margin: 20px 0 10px; }
|
||||
.simcal-default-calendar-list dt.simcal-day-label > span {
|
||||
display: inline-block;
|
||||
padding: 4px 8px; }
|
||||
.simcal-default-calendar-list ul.simcal-events {
|
||||
margin: 10px 14px 0; }
|
||||
.simcal-default-calendar-list ul.simcal-events li.simcal-event {
|
||||
list-style-type: none;
|
||||
margin-bottom: 10px;
|
||||
word-wrap: break-word; }
|
||||
.simcal-default-calendar-list .simcal-event-details {
|
||||
font-size: .84em;
|
||||
line-height: 1.5;
|
||||
overflow: hidden; }
|
||||
.simcal-default-calendar-list .simcal-event-details p,
|
||||
.simcal-default-calendar-list .simcal-event-details .simcal-event-description {
|
||||
margin: 0 0 1em; }
|
||||
.simcal-default-calendar-list .simcal-events-toggle {
|
||||
display: inline-block;
|
||||
padding: 0; }
|
||||
.simcal-default-calendar-list.simcal-default-calendar-light .simcal-events-toggle {
|
||||
background-color: rgba(0, 0, 0, 0.1); }
|
||||
.simcal-default-calendar-list.simcal-default-calendar-dark .simcal-events-toggle {
|
||||
background-color: rgba(255, 255, 255, 0.1); }
|
||||
.simcal-default-calendar-list .simcal-calendar-list-compact .simcal-calendar-head .simcal-nav h3 {
|
||||
font-size: 1em; }
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
.simcal-default-calendar .simcal-nav-button,.simcal-default-calendar .simcal-nav-button:focus,.simcal-default-calendar .simcal-nav-button:hover{background:0 0;border:0;box-shadow:none;outline:0}@font-face{font-family:simple-calendar;src:url(../fonts/simple-calendar.eot?43976014);src:url(../fonts/simple-calendar.eot?43976014#iefix) format("embedded-opentype"),url(../fonts/simple-calendar.woff?43976014) format("woff"),url(../fonts/simple-calendar.ttf?43976014) format("truetype"),url(../fonts/simple-calendar.svg?43976014#simple-calendar) format("svg");font-weight:400;font-style:normal}[class*=" simcal-icon-"]:before,[class^=simcal-icon-]:before{display:inline-block;font-family:simple-calendar;font-style:normal;font-weight:400;margin-right:.2em;speak:none;text-decoration:inherit;text-align:center;width:1em;font-variant:normal;text-transform:none;margin-left:.2em;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.simcal-icon-spin{animation:spin 2s infinite linear;display:inline-block}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(359deg)}}.simcal-icon-animate:before{transition:all .2s ease-in-out}.simcal-icon-rotate-180:before{transform:rotate(180deg)}.simcal-icon-calendar-empty:before{content:'\e800'}.simcal-icon-calendar:before{content:'\e801'}.simcal-icon-calendar-logo:before{content:'\e802'}.simcal-icon-settings:before{content:'\e804'}.simcal-icon-toggles:before{content:'\e805'}.simcal-icon-list:before{content:'\e806'}.simcal-icon-event:before{content:'\e807'}.simcal-icon-help:before{content:'\e808'}.simcal-icon-panel:before{content:'\e80a'}.simcal-icon-grid:before{content:'\e80b'}.simcal-icon-google:before{content:'\e80c'}.simcal-icon-docs:before{content:'\e80f'}.simcal-icon-hourglass:before{content:'\e811'}.simcal-icon-globe:before{content:'\e812'}.simcal-icon-timezones:before{content:'\e813'}.simcal-icon-warning:before{content:'\e815'}.simcal-icon-wordpress:before{content:'\e814'}.simcal-icon-up:before{content:'\e80e'}.simcal-icon-right:before{content:'\e809'}.simcal-icon-down:before{content:'\e80d'}.simcal-icon-left:before{content:'\e803'}.simcal-icon-spinner:before{content:'\e810'}.simcal-calendar{position:relative}.simcal-powered{display:block;margin:-10px 0 20px}.simcal-align-left{text-align:left}.simcal-align-right{text-align:right}.simcal-default-calendar .simcal-current h3{margin:0;padding:0}.simcal-default-calendar .simcal-nav{vertical-align:middle}.simcal-default-calendar .simcal-nav-button{cursor:pointer;margin:0;padding:0;transition:margin .2s ease-out;width:100%}.simcal-default-calendar .simcal-nav-button.simcal-prev:hover{margin-left:-10px}.simcal-default-calendar .simcal-nav-button.simcal-next:hover{margin-right:-10px}.simcal-default-calendar .simcal-nav-button:disabled:hover,.simcal-default-calendar ul.simcal-attachments,.simcal-default-calendar ul.simcal-attendees{margin:0;padding:0}.simcal-default-calendar .simcal-nav-button:disabled{cursor:default}.simcal-default-calendar .simcal-events{list-style:none;margin-left:0}.simcal-default-calendar .simcal-events-toggle{border:0;box-shadow:none;text-align:center;width:100%}.simcal-default-calendar .simcal-events-toggle:active,.simcal-default-calendar .simcal-events-toggle:focus,.simcal-default-calendar .simcal-events-toggle:hover{border:0;box-shadow:none;outline:0}.simcal-default-calendar li.simcal-attachment,.simcal-default-calendar li.simcal-attendee{list-style:none;margin-bottom:4px}.simcal-default-calendar li.simcal-attachment:last-child,.simcal-default-calendar li.simcal-attendee:last-child{margin-bottom:0}.simcal-default-calendar li.simcal-attachment small,.simcal-default-calendar li.simcal-attendee small{opacity:.9;text-transform:lowercase}.simcal-default-calendar .simcal-organizer a,.simcal-default-calendar li.simcal-attachment a,.simcal-default-calendar li.simcal-attendee a{border-bottom:0;text-decoration:none}.simcal-default-calendar .simcal-organizer img,.simcal-default-calendar li.simcal-attachment img,.simcal-default-calendar li.simcal-attendee img{display:inline-block;margin:0 4px;max-height:24px;max-width:24px}.simcal-default-calendar .simcal-tooltip-content{font-size:1.2em;line-height:1.4;padding:5px}.simcal-default-calendar .simcal-ajax-loader{height:100%;left:0;position:absolute;top:0;width:100%}.simcal-default-calendar .simcal-ajax-loader>i{font-size:48px;left:50%;line-height:1;margin:-36px 0 0 -36px;position:absolute;top:50%}.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-top>i{top:20%}.simcal-default-calendar .simcal-ajax-loader.simcal-spinner-bottom>i{bottom:20%;top:auto}.simcal-default-calendar-light .simcal-nav-button{color:rgba(0,0,0,.6)}.simcal-default-calendar-light .simcal-nav-button:disabled,.simcal-default-calendar-light .simcal-nav-button:disabled:hover{color:rgba(255,255,255,.9)!important}.simcal-default-calendar-light .simcal-nav-button:focus,.simcal-default-calendar-light .simcal-nav-button:hover{color:rgba(0,0,0,.9)}.simcal-default-calendar-light .simcal-events-toggLine truncated
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
* qTip2 - Pretty powerful tooltips - v2.2.1
|
||||
* http://qtip2.com
|
||||
*
|
||||
* Copyright (c) 2015
|
||||
* Released under the MIT licenses
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Date: Wed Aug 12 2015 04:16 EDT-0400
|
||||
* Plugins: tips viewport
|
||||
* Styles: core
|
||||
*/
|
||||
.qtip{
|
||||
position: absolute;
|
||||
left: -28000px;
|
||||
top: -28000px;
|
||||
display: none;
|
||||
|
||||
max-width: 280px;
|
||||
min-width: 50px;
|
||||
|
||||
font-size: 10.5px;
|
||||
line-height: 12px;
|
||||
|
||||
direction: ltr;
|
||||
|
||||
box-shadow: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.qtip-content{
|
||||
position: relative;
|
||||
padding: 5px 9px;
|
||||
overflow: hidden;
|
||||
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.qtip-titlebar{
|
||||
position: relative;
|
||||
padding: 5px 35px 5px 10px;
|
||||
overflow: hidden;
|
||||
|
||||
border-width: 0 0 1px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.qtip-titlebar + .qtip-content{ border-top-width: 0 !important; }
|
||||
|
||||
/* Default close button class */
|
||||
.qtip-close{
|
||||
position: absolute;
|
||||
right: -9px; top: -9px;
|
||||
z-index: 11; /* Overlap .qtip-tip */
|
||||
|
||||
cursor: pointer;
|
||||
outline: medium none;
|
||||
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.qtip-titlebar .qtip-close{
|
||||
right: 4px; top: 50%;
|
||||
margin-top: -9px;
|
||||
}
|
||||
|
||||
* html .qtip-titlebar .qtip-close{ top: 16px; } /* IE fix */
|
||||
|
||||
.qtip-titlebar .ui-icon,
|
||||
.qtip-icon .ui-icon{
|
||||
display: block;
|
||||
text-indent: -1000em;
|
||||
direction: ltr;
|
||||
}
|
||||
|
||||
.qtip-icon, .qtip-icon .ui-icon{
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.qtip-icon .ui-icon{
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
|
||||
line-height: 14px;
|
||||
text-align: center;
|
||||
text-indent: 0;
|
||||
font: normal bold 10px/13px Tahoma,sans-serif;
|
||||
|
||||
color: inherit;
|
||||
background: transparent none no-repeat -100em -100em;
|
||||
}
|
||||
|
||||
/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
|
||||
.qtip-focus{}
|
||||
|
||||
/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
|
||||
.qtip-hover{}
|
||||
|
||||
/* Default tooltip style */
|
||||
.qtip-default{
|
||||
border: 1px solid #F1D031;
|
||||
|
||||
background-color: #FFFFA3;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.qtip-default .qtip-titlebar{
|
||||
background-color: #FFEF93;
|
||||
}
|
||||
|
||||
.qtip-default .qtip-icon{
|
||||
border-color: #CCC;
|
||||
background: #F1F1F1;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.qtip-default .qtip-titlebar .qtip-close{
|
||||
border-color: #AAA;
|
||||
color: #111;
|
||||
}
|
||||
|
||||
|
||||
.qtip .qtip-tip{
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
z-index: 10;
|
||||
|
||||
}
|
||||
|
||||
/* Opera bug #357 - Incorrect tip position
|
||||
https://github.com/Craga89/qTip2/issues/367 */
|
||||
x:-o-prefocus, .qtip .qtip-tip{
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.qtip .qtip-tip,
|
||||
.qtip .qtip-tip .qtip-vml,
|
||||
.qtip .qtip-tip canvas{
|
||||
position: absolute;
|
||||
|
||||
color: #123456;
|
||||
background: transparent;
|
||||
border: 0 dashed transparent;
|
||||
}
|
||||
|
||||
.qtip .qtip-tip canvas{ top: 0; left: 0; }
|
||||
|
||||
.qtip .qtip-tip .qtip-vml{
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
visibility: visible;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
/* qTip2 v2.2.1 | Plugins: tips viewport | Styles: core | qtip2.com | Licensed MIT | Wed Aug 12 2015 16:16:42 */
|
||||
|
||||
.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr;box-shadow:none;padding:0}.qtip-content{position:relative;padding:5px 9px;overflow:hidden;text-align:left;word-wrap:break-word}.qtip-titlebar{position:relative;padding:5px 35px 5px 10px;overflow:hidden;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;z-index:11;cursor:pointer;outline:0;border:1px solid transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-icon .ui-icon,.qtip-titlebar .ui-icon{display:block;text-indent:-1000em;direction:ltr}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;line-height:14px;text-align:center;text-indent:0;font:400 bold 10px/13px Tahoma,sans-serif;color:inherit;background:-100em -100em no-repeat}.qtip-default{border:1px solid #F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}.qtip .qtip-tip,x:-o-prefocus{visibility:hidden}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml,.qtip .qtip-tip canvas{position:absolute;color:#123456;background:0 0;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}
|
||||
@@ -1,484 +0,0 @@
|
||||
.select2-container {
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
vertical-align: middle; }
|
||||
.select2-container .select2-selection--single {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
height: 28px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--single .select2-selection__rendered {
|
||||
display: block;
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-selection--single .select2-selection__clear {
|
||||
position: relative; }
|
||||
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
|
||||
padding-right: 8px;
|
||||
padding-left: 20px; }
|
||||
.select2-container .select2-selection--multiple {
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
min-height: 32px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-container .select2-selection--multiple .select2-selection__rendered {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
.select2-container .select2-search--inline {
|
||||
float: left; }
|
||||
.select2-container .select2-search--inline .select2-search__field {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
padding: 0; }
|
||||
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
|
||||
.select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: -100000px;
|
||||
width: 100%;
|
||||
z-index: 1051; }
|
||||
|
||||
.select2-results {
|
||||
display: block; }
|
||||
|
||||
.select2-results__options {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
|
||||
.select2-results__option {
|
||||
padding: 6px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none; }
|
||||
.select2-results__option[aria-selected] {
|
||||
cursor: pointer; }
|
||||
|
||||
.select2-container--open .select2-dropdown {
|
||||
left: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--above {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--open .select2-dropdown--below {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-search--dropdown {
|
||||
display: block;
|
||||
padding: 4px; }
|
||||
.select2-search--dropdown .select2-search__field {
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box; }
|
||||
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none; }
|
||||
.select2-search--dropdown.select2-search--hide {
|
||||
display: none; }
|
||||
|
||||
.select2-close-mask {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
height: auto;
|
||||
width: auto;
|
||||
opacity: 0;
|
||||
z-index: 99;
|
||||
background-color: #fff;
|
||||
filter: alpha(opacity=0); }
|
||||
|
||||
.select2-hidden-accessible {
|
||||
border: 0 !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
height: 1px !important;
|
||||
margin: -1px !important;
|
||||
overflow: hidden !important;
|
||||
padding: 0 !important;
|
||||
position: absolute !important;
|
||||
width: 1px !important; }
|
||||
|
||||
.select2-container--default .select2-selection--single {
|
||||
background-color: #fff;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px; }
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--default .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
|
||||
box-sizing: border-box;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
width: 100%; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
|
||||
list-style: none; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__placeholder {
|
||||
color: #999;
|
||||
margin-top: 5px;
|
||||
float: left; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #333; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
|
||||
float: right; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--default.select2-container--focus .select2-selection--multiple {
|
||||
border: solid black 1px;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection--multiple {
|
||||
background-color: #eee;
|
||||
cursor: default; }
|
||||
|
||||
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
|
||||
display: none; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--default .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa; }
|
||||
|
||||
.select2-container--default .select2-search--inline .select2-search__field {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
-webkit-appearance: textfield; }
|
||||
|
||||
.select2-container--default .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--default .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-disabled=true] {
|
||||
color: #999; }
|
||||
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background-color: #ddd; }
|
||||
|
||||
.select2-container--default .select2-results__option .select2-results__option {
|
||||
padding-left: 1em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
|
||||
padding-left: 0; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em; }
|
||||
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em; }
|
||||
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #5897fb;
|
||||
color: white; }
|
||||
|
||||
.select2-container--default .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic .select2-selection--single {
|
||||
background-color: #f7f7f7;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
outline: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%);
|
||||
background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__rendered {
|
||||
color: #444;
|
||||
line-height: 28px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
|
||||
color: #999; }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow {
|
||||
background-color: #ddd;
|
||||
border: none;
|
||||
border-left: 1px solid #aaa;
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
height: 26px;
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
width: 20px;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); }
|
||||
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
height: 0;
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 0; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
|
||||
float: left; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
|
||||
border: none;
|
||||
border-right: 1px solid #aaa;
|
||||
border-radius: 0;
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
left: 1px;
|
||||
right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--single {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
|
||||
background: transparent;
|
||||
border: none; }
|
||||
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%);
|
||||
background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%);
|
||||
background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); }
|
||||
|
||||
.select2-container--classic .select2-selection--multiple {
|
||||
background-color: white;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
outline: 0; }
|
||||
.select2-container--classic .select2-selection--multiple:focus {
|
||||
border: 1px solid #5897fb; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
|
||||
display: none; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
|
||||
background-color: #e4e4e4;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin-right: 2px; }
|
||||
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
|
||||
color: #555; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
float: right; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-selection--multiple {
|
||||
border: 1px solid #5897fb; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0; }
|
||||
|
||||
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--dropdown .select2-search__field {
|
||||
border: 1px solid #aaa;
|
||||
outline: 0; }
|
||||
|
||||
.select2-container--classic .select2-search--inline .select2-search__field {
|
||||
outline: 0;
|
||||
box-shadow: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown {
|
||||
background-color: white;
|
||||
border: 1px solid transparent; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--above {
|
||||
border-bottom: none; }
|
||||
|
||||
.select2-container--classic .select2-dropdown--below {
|
||||
border-top: none; }
|
||||
|
||||
.select2-container--classic .select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto; }
|
||||
|
||||
.select2-container--classic .select2-results__option[role=group] {
|
||||
padding: 0; }
|
||||
|
||||
.select2-container--classic .select2-results__option[aria-disabled=true] {
|
||||
color: grey; }
|
||||
|
||||
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
|
||||
background-color: #3875d7;
|
||||
color: white; }
|
||||
|
||||
.select2-container--classic .select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px; }
|
||||
|
||||
.select2-container--classic.select2-container--open .select2-dropdown {
|
||||
border-color: #5897fb; }
|
||||
@@ -1 +0,0 @@
|
||||
.select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;height:1px !important;margin:-1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__chLine truncated
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Copyright (C) 2015 by original authors @ fontello.com</metadata>
|
||||
<defs>
|
||||
<font id="simple-calendar" horiz-adv-x="1000" >
|
||||
<font-face font-family="simple-calendar" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
|
||||
<missing-glyph horiz-adv-x="1000" />
|
||||
<glyph glyph-name="calendar-empty" unicode="" d="m71-79h786v572h-786v-572z m215 679v161q0 8-5 13t-13 5h-36q-8 0-13-5t-5-13v-161q0-8 5-13t13-5h36q8 0 13 5t5 13z m428 0v161q0 8-5 13t-13 5h-35q-8 0-13-5t-5-13v-161q0-8 5-13t13-5h35q8 0 13 5t5 13z m215 36v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50v715q0 29 21 50t50 21h72v54q0 36 26 63t63 26h36q37 0 63-26t26-63v-54h214v54q0 36 27 63t63 26h35q37 0 63-26t27-63v-54h71q29 0 50-21t22-50z" horiz-adv-x="928.6" />
|
||||
<glyph glyph-name="calendar" unicode="" d="m71-79h161v161h-161v-161z m197 0h178v161h-178v-161z m-197 197h161v178h-161v-178z m197 0h178v178h-178v-178z m-197 214h161v161h-161v-161z m411-411h179v161h-179v-161z m-214 411h178v161h-178v-161z m428-411h161v161h-161v-161z m-214 197h179v178h-179v-178z m-196 482v161q0 7-6 12t-12 6h-36q-7 0-12-6t-6-12v-161q0-7 6-13t12-5h36q7 0 12 5t6 13z m410-482h161v178h-161v-178z m-214 214h179v161h-179v-161z m214 0h161v161h-161v-161z m18 268v161q0 7-5 12t-13 6h-35q-8 0-13-6t-5-12v-161q0-7 5-13t13-5h35q8 0 13 5t5 13z m215 36v-715q0-29-22-50t-50-21h-786q-29 0-50 21t-21 50v715q0 29 21 50t50 21h72v54q0 36 26 63t63 26h36q37 0 63-26t26-63v-54h214v54q0 36 27 63t63 26h35q37 0 63-26t27-63v-54h71q29 0 50-21t22-50z" horiz-adv-x="928.6" />
|
||||
<glyph glyph-name="calendar-logo" unicode="" d="m0-150l0 649 893 0 0-649-893 0z m0 705l0 221 109 0 0-141 200 0 0 141 275 0 0-141 199 0 0 141 110 0 0-221-893 0z m168 139l0 156 82 0 0-156-82 0z m59-619q0-112 123-112 47 0 84 32 39 31 39 80 0 68-78 90 48 15 64 48 12 28-2 73-27 62-107 62-51 0-86-26t-37-77l72 0q0 45 49 46 43 0 45-52 0-49-84-47l0-57q48 0 68-8 23-11 23-46 0-57-54-61-43 0-47 55l-72 0z m281 146q49 14 88 47l0-297 70 0 0 371-64 0q-38-37-94-58l0-63z m135 473l0 156 82 0 0-156-82 0z" horiz-adv-x="893" />
|
||||
<glyph glyph-name="left-open" unicode="" d="m653 682l-296-296 296-297q11-10 11-25t-11-25l-92-93q-11-10-25-10t-25 10l-414 415q-11 10-11 25t11 25l414 414q10 10 25 10t25-10l92-93q11-10 11-25t-11-25z" horiz-adv-x="714.3" />
|
||||
<glyph glyph-name="settings" unicode="" d="m500 350q0 59-42 101t-101 42-101-42-42-101 42-101 101-42 101 42 42 101z m429-286q0 29-22 51t-50 21-50-21-21-51q0-29 21-50t50-21 51 21 21 50z m0 572q0 29-22 50t-50 21-50-21-21-50q0-30 21-51t50-21 51 21 21 51z m-215-235v-103q0-6-4-11t-9-6l-86-14q-6-19-18-42 19-27 50-64 4-6 4-11 0-7-4-11-13-17-46-50t-44-33q-6 0-11 4l-64 50q-21-11-43-17-6-60-13-87-4-13-17-13h-104q-6 0-11 4t-5 10l-13 85q-19 6-42 18l-66-50q-4-4-11-4-6 0-12 4-80 75-80 90 0 5 4 10 5 8 23 30t26 34q-13 24-20 46l-85 13q-5 1-9 5t-4 11v103q0 6 4 11t9 6l86 14q7 19 18 42-19 27-50 64-4 6-4 11 0 7 4 11 12 17 46 50t44 33q6 0 12-4l64-50q19 10 43 18 6 60 13 86 3 13 16 13h104q6 0 11-4t6-10l13-85q19-6 41-17l66 49q5 4 11 4 7 0 12-4 81-75 81-90 0-5-4-10-7-9-24-30t-25-34q13-27 19-46l85-12q5-2 9-6t4-11z m357-298v-78q0-9-83-17-6-15-16-29 28-63 28-77 0-2-2-4-68-40-69-40-5 0-26 27t-29 37q-11-1-17-1t-17 1q-7-11-29-37t-25-27q-1 0-69 40-3 2-3 4 0 14 29 77-10 14-17 29-83 8-83 17v78q0 9 83 18 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-38q12 1 17 1t17-1q28 40 51 63l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-9 83-18z m0 572v-78q0-9-83-18-6-15-16-29 28-63 28-77 0-2-2-4-68-39-69-39-5 0-26 26t-29 38q-11-1-17-1t-17 1q-7-12-29-38t-25-26q-1 0-69 39-3 2-3 4 0 14 29 77-10 14-17 29-83 9-83 18v78q0 9 83 17 7 16 17 29-29 63-29 77 0 2 3 4 2 1 19 11t33 19 17 9q4 0 25-26t29-38q12 2 17 2t17-2q28 40 51 63l4 1q2 0 69-39 2-2 2-4 0-14-28-77 9-13 16-29 83-8 83-17z" horiz-adv-x="1071.4" />
|
||||
<glyph glyph-name="toggles" unicode="" d="m196 64v-71h-196v71h196z m197 72q14 0 25-11t11-25v-143q0-14-11-25t-25-11h-143q-14 0-25 11t-11 25v143q0 15 11 25t25 11h143z m89 214v-71h-482v71h482z m-357 286v-72h-125v72h125z m732-572v-71h-411v71h411z m-536 643q15 0 26-10t10-26v-142q0-15-10-26t-26-10h-142q-15 0-26 10t-10 26v142q0 15 10 26t26 10h142z m358-286q14 0 25-10t10-25v-143q0-15-10-25t-25-11h-143q-15 0-25 11t-11 25v143q0 14 11 25t25 10h143z m178-71v-71h-125v71h125z m0 286v-72h-482v72h482z" horiz-adv-x="857.1" />
|
||||
<glyph glyph-name="list" unicode="" d="m650 400q22 0 36-15t14-35-15-35-35-15l-600 0q-20 0-35 15t-15 35 14 35 36 15l600 0z m-600 100q-20 0-35 15t-15 35 14 35 36 15l600 0q22 0 36-15t14-35-15-35-35-15l-600 0z m600-300q22 0 36-15t14-35-15-35-35-15l-600 0q-20 0-35 15t-15 35 14 35 36 15l600 0z" horiz-adv-x="700" />
|
||||
<glyph glyph-name="event" unicode="" d="m460 810q190 0 325-135t135-325-135-325-325-135-325 135-135 325 135 325 325 135z m0-820q150 0 255 106t105 254q0 150-105 255t-255 105q-148 0-254-105t-106-255q0-148 106-254t254-106z m36 620l0-244 150-150-50-50-170 170 0 274 70 0z" horiz-adv-x="920" />
|
||||
<glyph glyph-name="help" unicode="" d="m0 350q0 95 37 182t100 149 149 100 183 37q95 0 182-37t149-100 100-149 37-182q0-95-37-182t-100-150-149-100-182-37q-96 0-183 37t-149 100-100 150-37 182z m117 0q0-71 28-137t75-112 112-75 137-28 136 28 112 75 75 112 28 137q0 95-47 176t-128 128-176 47-177-47-128-128-47-176z m216 176l31-101q45 29 93 29 49 0 49-23 0-4-2-8t-3-5-6-5-7-5-8-4l-8-4-40-21q-22-12-28-25t-6-37v-37h117v16q0 7 0 10t3 6 6 5q1 1 11 5t17 8 19 11 18 13q19 17 29 37t11 55q0 49-42 83t-106 34q-83 0-148-37z m48-334q0-32 21-49t55-17q33 0 54 17t20 49-20 49-54 18q-35 0-55-18t-21-49z" horiz-adv-x="937.5" />
|
||||
<glyph glyph-name="right-open" unicode="" d="m618 361l-414-415q-11-10-25-10t-26 10l-92 93q-11 11-11 25t11 25l296 297-296 296q-11 11-11 25t11 25l92 93q11 10 26 10t25-10l414-414q10-11 10-25t-10-25z" horiz-adv-x="714.3" />
|
||||
<glyph glyph-name="panel" unicode="" d="m311 504l489 0c36 0 65-30 65-65l0-404c0-35-29-65-65-65l-489 0c-35 0-65 30-65 65l0 404c0 35 30 65 65 65z m454-94l-419 0 0-346 419 0 0 346z m-146 181l-101 0 0 44-417 0 0-336 58 0 0-95-93 0c-36 0-66 30-66 65l0 395c0 36 30 66 66 66l488 0c36 0 65-30 65-66l0-73z" horiz-adv-x="865" />
|
||||
<glyph glyph-name="grid" unicode="" d="m0-22l0 744 970 0 0-744-970 0z m519 452l0-159 159 0 0 159-159 0z m0-384l159 0 0 157-159 0 0-157z m159 609l-159 0 0-158 159 0 0 158z m225-384l0 159-158 0 0-159 158 0z m-158-225l158 0 0 157-158 0 0-157z m158 451l0 158-158 0 0-158 158 0z m-835-67l0-159 158 0 0 159-158 0z m0-384l158 0 0 157-158 0 0-157z m158 609l-158 0 0-158 158 0 0 158z m225-384l0 159-157 0 0-159 157 0z m-157-225l157 0 0 157-157 0 0-157z m157 451l0 158-157 0 0-158 157 0z" horiz-adv-x="970" />
|
||||
<glyph glyph-name="google" unicode="" d="m547 103q0 14-3 27t-9 24-15 23-16 19-22 20-20 16-23 16-20 15q-9 1-28 1-29 0-58-4t-60-14-54-25-38-42-15-59q0-31 13-57t34-42 48-28 56-16 57-5q32 0 62 7t55 22 41 41 15 61z m-65 479q0 33-9 70t-27 72-47 57-65 23q-24 0-46-11t-37-29q-26-33-26-89 0-26 6-55t17-57 29-52 42-37 54-15q20 0 43 10t37 24q29 31 29 89z m-62 268h232l-76-49h-74q42-35 63-74t22-90q0-40-14-72t-33-52-39-36-33-34-14-37q0-20 18-40t43-38 51-41 43-58 18-79q0-51-28-96-39-68-117-101t-166-32q-74 0-138 24t-96 76q-20 33-20 73 0 46 25 84t66 64q73 46 225 56-17 23-26 41t-9 41q0 22 12 47-26-2-38-2-83 0-139 54t-57 137q0 45 20 88t55 73q43 37 102 55t122 18z" horiz-adv-x="714.3" />
|
||||
<glyph glyph-name="down-open" unicode="" d="m939 399l-414-413q-10-11-25-11t-25 11l-414 413q-11 11-11 26t11 25l92 92q11 11 26 11t25-11l296-296 296 296q11 11 25 11t26-11l92-92q11-11 11-25t-11-26z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="up-open" unicode="" d="m939 107l-92-92q-11-10-26-10t-25 10l-296 297-296-297q-11-10-25-10t-26 10l-92 92q-11 11-11 26t11 25l414 414q11 10 25 10t25-10l414-414q11-11 11-25t-11-26z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="docs" unicode="" d="m970 480q38-10 30-46l-150-556q-4-16-18-23t-30-3l-406 110q-16 4-24 18t-4 28l24 92-180-48q-40-10-50 26l-160 602q-10 36 28 48l454 122q16 4 30-3t18-23l66-244z m-888 190l144-542 392 106-144 540z m702-742l132 492-298 82 76-282q10-34-28-46l-196-52-26-102z" horiz-adv-x="1001" />
|
||||
<glyph glyph-name="spin3" unicode="" d="m494 850c-266 0-483-210-494-472-1-19 13-20 13-20l84 0c16 0 19 10 19 18 10 199 176 358 378 358 107 0 205-45 273-118l-58-57c-11-12-11-27 5-31l247-50c21-5 46 11 37 44l-58 227c-2 9-16 22-29 13l-65-60c-89 91-214 148-352 148z m409-508c-16 0-19-10-19-18-10-199-176-358-377-358-108 0-205 45-274 118l59 57c10 12 10 27-5 31l-248 50c-21 5-46-11-37-44l58-227c2-9 16-22 30-13l64 60c89-91 214-148 353-148 265 0 482 210 493 473 1 18-13 19-13 19l-84 0z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="hourglass" unicode="" d="m0-37v70q0 22 12 49t24 46 38 55l24 33t26 36 22 33 18 35 5 30-5 30-18 35-22 33-26 36l-24 32q-26 37-38 55t-24 46-12 49v70q0 34 24 58t59 24h419q35 0 59-24t25-58v-70q0-22-12-49t-24-46-38-55l-24-32t-27-36-22-33-17-36-6-29 6-30 17-35 22-33 27-37l24-32q25-36 38-55t24-46 12-49v-70q0-34-25-58t-59-24h-419q-34 0-59 24t-24 58z m100 35h40q0 9 2 17t9 18 12 16 17 18 19 16 22 17 23 16 25 18 24 17q8-6 26-19t28-19 25-19 25-19 19-19 16-19 10-19 4-20h40v35q0 7-14 31-8 14-42 63-53 75-71 108-34 64-34 115 0 26 7 54t25 57 30 50 36 51l7 10q33 47 42 64 6 9 9 17t4 11l1 2v35h-386v-35q1-8 13-30 10-17 43-64 53-75 71-108 34-63 34-114 0-27-8-54t-25-58-29-49-36-52q-1-1-2-2t-2-2-2-3-1-3q-34-49-43-63-13-24-13-31v-35z" horiz-adv-x="585.9" />
|
||||
<glyph glyph-name="globe" unicode="" d="m429 779q116 0 215-58t156-156 57-215-57-215-156-156-215-58-216 58-155 156-58 215 58 215 155 156 216 58z m152-291q-1-1-5-5t-7-6q1 0 2 3t3 6 2 4q3 4 12 8 8 4 29 7 19 5 29-6-1 1 5 7t8 7q2 1 8 2t9 5l1 12q-7-1-10 4t-3 12q0-2-4-5 0 4-2 5t-7-1-5-1q-5 2-8 5t-5 9-2 8q-1 3-5 6t-5 6q-1 1-2 3t-2 4-2 3-3 1-4-3-4-5-2-3q-2 1-4 1t-2-1-3-2-3-2q-1-1-4-1t-5-1q8 3-1 6-5 2-9 1 5 3 5 7t-5 8h3q-1 2-5 5t-10 4-7 4q-5 3-19 5t-18 0q-3-3-3-5t2-8 2-7q1-4-3-7t-3-7q0-4 7-9t6-12q-2-4-9-9t-9-6q-3-5-1-11t6-9q1-1 1-2t-2-3-3-2-4-2l-1-1q-7-3-12 3t-7 15q-4 14-9 17-13 4-17-1-2 7-22 15-14 5-33 2 4 0 0 8-4 9-10 7 1 3 2 10t0 7q2 7 7 13 1 1 4 5t5 7 1 4q19-3 28 6 2 2 6 9t6 10q5 3 8 3t8-3 8-3q8-1 8 6t-4 11q7 0 2 10-3 4-5 5-6 2-15-3-4-2 2-4-1 0-6-6t-9-10-9 3q0 0-3 7t-5 8q-5 0-9-9 1 5-6 9t-14 4q11 7-4 15-4 3-12 3t-11-2q-2-4-3-7t3-4 6-3 6-2 5-2q8-6 5-8-1 0-5-2t-6-2-4-3q-2-2 0-7t-1-8q-3 3-5 10t-4 9q4-5-14-4l-5 1q-3 0-9-1t-12-1-7 5q-3 4 0 11 0 2 2 1-2 2-6 5t-6 5q-25-8-52-23 3 0 6 1 3 1 8 3t5 4q19 7 24 3l3 3q7-9 11-14-4 3-17 1-11-4-12-7 4-7 2-10-2 2-6 6t-8 6-8 3q-9 0-13-1-81-45-131-124 4-4 7-4 2-1 3-5t1-6 6 1q5-4 2-10 1 0 25-15 10-10 11-12 2-6-5-10-1 1-5 5t-5 2q-2-3 0-10t6-7q-4 0-5-9t-2-20 0-13l1-1q-2-6 3-19t12-11q-7-1 11-24 3-4 4-5 2-1 7-4t9-6 5-5q2-3 6-13t8-13q-2-3 5-11t6-13q-1 0-2-1t-1 0q2-4 9-8t8-7q1-2 1-6t2-6 4-1q2 11-13 34-8 14-9 17-2 2-4 8t-2 8q1 0 3 0t5-2 4-3 1-1q-1-4 1-10t7-10 10-11 6-7q4-4 8-11t0-8q5 0 11-5t10-11q3-5 4-15t3-13q1-4 5-8t7-5l9-5t7-3q3-2 10-6t12-7q6-2 9-2t8 1 8 2q8 1 16-8t12-12q20-10 30-6-1 0 1-4t4-9 5-8 3-5q3-3 10-8t10-8q4 2 4 5-1-5 4-11t10-6q8 2 8 18-17-9-27 10 0 0-2 3t-2 5-1 4 0 5 2 1q5 0 6 2t-1 7-2 8q-1 4-6 11t-7 8q-3-5-9-4t-9 5q0-1-1-3t-1-4q-7 0-8 0 1 2 1 10t2 13q1 2 3 6t5 9 2 7-3 5-9 1q-11 0-15-11-1-2-2-6t-2-6-5-4q-4-2-14-1t-13 3q-8 4-13 16t-5 20q0 6 1 15t2 14-3 14q2 1 5 5t5 6q2 1 3 1t2 0 3 1 1 3q0 1-2 2-2 1-2 1 4-1 16 1t15-1q9-6 12 1 0 1-1 6t0 7q3-15 16-5 2-1 9-3t9-2q2-1 4-3t3-3 3 0 5 4q5-8 7-13 6-23 10-25 4-2 6-1t3 5 0 8-1 7l-1 4v11l0 4q-8 2-10 7t0 10 9 10q0 1 4 2t9 4 7 4q12 11 8 20 4 0 6 5 0 0-2 2t-5 2-2 2q5 2 1 8 3 2 4 7t4 5q5-7 12-1 4 5 1 9 2 4 11 6t10 5q4-1 5 1t0 7 2 7q2 2 8 5t8 2l9 7q2 2 0 2 10-1 18 6 5 6-4 11 2 3-2 5t-8 3q2 1 7 1t5 1q9 5-4 9-9 2-24-7z m-90-490q114 21 195 106-1 2-7 2t-7 2q-10 4-13 5 1 4-1 7t-5 5-7 5-6 4q-1 1-4 3t-4 3-4 2-5 2-5-1l-2-1q-2 0-3-1t-3-2-2-1 0-2q-12 10-20 13-3 0-7 3t-5 4-6 0-6-4q-3-2-4-8t-1-7q-4 3 0 10t1 10q-1 3-6 2t-6-2-7-5-5-3-4-3-5-5q-2-2-4-6t-2-7q-1 3-7 4t-5 3q1-5 2-19t3-22q4-17-7-26-15-14-16-23-2-12 7-14 0-4-5-12t-4-12q0-3 2-9z" horiz-adv-x="857.1" />
|
||||
<glyph glyph-name="globe-1" unicode="" d="m406 755c227 0 405-180 405-404 0-226-178-406-405-406-225 0-406 180-406 406 0 224 181 404 406 404z m23-734c65 0 100 113 116 169-39-4-77-6-116-7l0-162z m-129 82c19-45 48-82 81-82l0 162c-38 1-77 3-115 7 8-32 19-61 34-87z m-222 202c16-19 57-44 132-57-5 31-7 66-7 100 0 25 1 45 3 68-57 12-91 20-117 32-9-30-14-64-14-97 0-16 0-32 3-46z m170 43c0-37 2-75 7-109 43-8 84-11 126-13l0 177c-45 1-90 3-132 8 0-22-1-41-1-63z m131 331c-56-23-104-110-124-225 41-4 84-6 126-8l0 233-2 0z m82-18c-11 8-23 18-32 18l0-233c44 2 85 4 127 8-16 90-52 169-95 207z m-32-435c44 2 85 5 126 12 6 33 8 72 8 110 0 22 0 41-2 62-42-4-86-6-132-7l0-177z m176 190c3-23 3-43 3-68 0-34-3-70-7-102 130 22 135 52 135 105 0 32-5 65-15 95-23-10-66-25-116-30z m99 74c-35 78-101 140-179 168 38-49 61-118 74-199 67 12 95 24 105 31z m-531 93c-29-27-50-59-65-92 11-10 30-11 103-31 14 80 38 146 75 196-42-20-80-37-113-73z m0-465c30-33 67-55 106-72-29 40-48 92-60 152-50 11-95 25-125 41 19-46 42-88 79-121z m466 0c35 32 59 72 75 116-33-15-75-28-121-38-14-60-32-108-62-150 39 17 78 39 108 72z" horiz-adv-x="811" />
|
||||
<glyph glyph-name="wordpress" unicode="" d="m0 350q4 209 151 354t349 146q207-4 353-151t147-349q-4-207-151-353t-349-147q-209 4-353 151t-147 349z m35 0q2-193 140-328t325-137q193 4 328 141t137 324q-4 193-141 328t-324 137q-193-4-329-141t-136-324z m41-30q-8 108 33 200l205-553q-109 55-173 155-57 89-65 198z m69 264q62 90 157 140t198 52q168-4 287-111-47 1-70-40-4-25-6-39t7-35 14-33 18-31l18-30q33-62 7-144l-62-219-154 459q43 4 46 4 12 4 15 14t-7 15q-6 6-11 6l-94-8-70 0q-4 0-27 4t-37 2-17-13q-3-16 14-20 33-4 47-6l68-179-93-278-157 459q43 4 49 4 18 2 16 20-4 15-20 15-70-10-136-8z m234-642l129 367 133-359q-131-45-262-8z m334 39q6 19 21 62l120 346q15 49 23 111 2 28-2 49 76-162 33-312-51-172-195-256z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="attention-1" unicode="" d="m571 83v106q0 8-5 13t-12 5h-108q-7 0-12-5t-5-13v-106q0-8 5-13t12-6h108q7 0 12 6t5 13z m-1 208l10 257q0 6-5 10-7 6-14 6h-122q-7 0-14-6-5-4-5-12l9-255q0-5 6-9t13-3h103q8 0 13 3t6 9z m-7 522l428-786q20-35-1-70-10-17-26-26t-35-10h-858q-18 0-35 10t-26 26q-21 35-1 70l429 786q9 17 26 27t36 10 36-10 27-27z" horiz-adv-x="1000" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 14 KiB |
@@ -1,32 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
|
||||
<g>
|
||||
<path d="M513.4,1013.3c-163.8,0-327.7,0-491.5,0c-9.7,0-8.8,0.9-8.8-8.9c0-243.7,0.2-487.3-0.3-731c-0.1-39.6,27.7-76.4,69.6-82.3
|
||||
c3-0.4,6-0.5,9-0.5c35,0,70,0.1,105-0.1c5.1,0,6.5,1.4,6.5,6.5c-0.2,26.8,0.1,53.7-0.2,80.5c-0.2,15.2,3.9,28.2,15.9,38.2
|
||||
c2.7,2.2,5,4.8,7.4,7.4c8,8.6,18.1,12.4,29.6,12.4c30.7,0.2,61.3,0.2,92,0c11.2-0.1,21.2-3.9,29.1-12.2c3.4-3.6,7-7.2,10.6-10.6
|
||||
c9-8.4,12.7-18.9,12.7-31c0.1-28.2,0-56.3,0-84.5c0-6.6,0-6.6,6.6-6.6c71.5,0,143,0,214.5,0c6.6,0,6.6,0,6.6,6.7
|
||||
c0,26.8,0.2,53.7-0.1,80.5c-0.2,15,5.1,26.8,15.4,38c13.6,14.7,28.9,20.8,48.7,20.1c25.6-1,51.3-0.4,77-0.2
|
||||
c13.9,0.1,24.8-5.1,35.4-14.4c15.9-14,22.1-30.4,21.1-51.3c-1.1-24.3-0.1-48.7-0.4-73c0-5.1,1.4-6.5,6.5-6.5
|
||||
c34.7,0.2,69.3,0,104,0.1c42.3,0.2,78.3,36,78.3,78.3c0.1,246,0,492,0,738c0,6.4,0,6.4-7.3,6.4
|
||||
C842,1013.3,677.7,1013.3,513.4,1013.3z M439.5,678.9c1.6-1,2.2-1.5,3-1.8c11.8-5.8,21.5-14.2,29-24.8
|
||||
c24.3-34.1,24.3-70.9,8.6-107.8c-13.3-31.3-39.3-49.3-71-59.4c-27.6-8.8-56-9.4-84.5-5.6c-20.3,2.7-39.2,9.6-55.5,22.2
|
||||
c-35.5,27.2-48.4,65.1-50.4,108c-0.2,3.7,2.1,3.9,4.8,3.9c22.2,0,44.3-0.1,66.5,0c3.8,0,5.4-1.1,5.3-5.1c-0.1-7.7,1-15.3,3-22.7
|
||||
c5.4-20,16.5-34.7,37.8-39.7c8.1-1.9,16.3-2.1,24.4-1.3c21.4,2.1,36.3,13.1,43.5,33.7c3.5,10.1,3.9,20.4,2.9,31
|
||||
c-2.2,23.4-16.2,39.7-39.1,44.6c-13.2,2.8-26.6,4.1-40.2,4c-3.7,0-5,1.2-4.9,4.9c0.1,16.5,0.2,33,0,49.5c0,4,1.5,5.2,5.3,5.1
|
||||
c12.9-0.3,25.6,0.9,38.3,3c26.3,4.2,43.5,18.8,49.2,42c3.3,13.5,3,27.1-0.2,40.6c-2.3,9.7-6.8,18.4-13.8,25.7
|
||||
c-15.4,16.1-34.5,21.6-56,18.9c-27.5-3.4-43.5-18-50.5-44.8c-1.9-7.3-3.1-14.7-2.8-22.2c0.2-4-1.1-5.6-5.4-5.6
|
||||
c-23.7,0.2-47.3,0.2-71,0c-4,0-5.4,1.2-4.9,5.2c1.4,13.2,2.7,26.5,5.9,39.5c11.1,45.2,38.2,75.6,83.4,88.2
|
||||
c36.7,10.3,73.8,10.1,110.5,0.1c24.5-6.6,44.7-20.1,61-39.8c24.5-29.7,34.4-63.9,31.4-101.9c-2.2-27.4-12.5-51.3-33.6-69.8
|
||||
C460.7,689.3,451.9,682,439.5,678.9z M755,692.5c0-68.6-0.1-137.3,0.1-205.9c0-5.1-1.4-6.5-6.5-6.4c-18.3,0.3-36.7,0.4-55,0
|
||||
c-5.7-0.1-7.2,1.9-8.2,7c-5.9,32.1-24.4,53-56.3,61.1c-17.5,4.5-35.6,5-53.5,5.8c-3.9,0.2-5.2,1.4-5.2,5.3c0.2,15.3,0.2,30.7,0,46
|
||||
c-0.1,4.3,1.6,5.4,5.6,5.3c14.2-0.2,28.3-0.1,42.5-0.1c15.5,0,31,0.1,46.5-0.1c4.1,0,5.9,1.3,5.5,5.4c-0.1,1.7,0,3.3,0,5
|
||||
c0,92.1,0,184.3,0,276.4c0,7.2,0,7.2,7,7.2c23.5,0,47,0,70.5,0c7,0,7,0,7-7.2C755,829.1,755,760.8,755,692.5z"/>
|
||||
<path d="M376.7,199.2c0,24.2,0,48.3,0,72.5c-0.1,23.1-17.4,40.5-40.4,40.6c-23.3,0.1-46.6,0.1-70,0c-22.8-0.1-40.3-17.4-40.3-40.1
|
||||
c-0.1-48.5-0.1-96.9,0-145.4c0-22.4,17.5-40,39.9-40.1c23.7-0.1,47.3-0.1,71,0c22.4,0.1,39.8,17.7,39.8,40.1
|
||||
C376.8,150.9,376.7,175.1,376.7,199.2z"/>
|
||||
<path d="M801.7,199.6c0,24,0,48,0,72c0,23.4-17.3,40.7-40.7,40.8c-23.2,0.1-46.3,0.1-69.5,0c-23.1-0.1-40.5-17.4-40.5-40.5
|
||||
c-0.1-48.3-0.1-96.6,0-144.9c0-22.7,17.5-40.2,40.2-40.3c23.3-0.1,46.6-0.1,70,0c23.1,0.1,40.4,17.4,40.5,40.5
|
||||
C801.8,151.3,801.7,175.4,801.7,199.6z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Shapes_xA0_Image_1_" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" viewBox="0 0 1024 1024" enable-background="new 0 0 1024 1024" xml:space="preserve">
|
||||
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M513.4,1013.3c-163.8,0-327.7,0-491.5,0c-9.7,0-8.8,0.9-8.8-8.9
|
||||
c0-243.7,0.2-487.3-0.3-731c-0.1-39.6,27.7-76.4,69.6-82.3c3-0.4,6-0.5,9-0.5c35,0,70,0.1,105-0.1c5.1,0,6.5,1.4,6.5,6.5
|
||||
c-0.2,26.8,0.1,53.7-0.2,80.5c-0.2,15.2,3.9,28.2,15.9,38.2c2.7,2.2,5,4.8,7.4,7.4c8,8.6,18.1,12.4,29.6,12.4
|
||||
c30.7,0.2,61.3,0.2,92,0c11.2-0.1,21.2-3.9,29.1-12.2c3.4-3.6,7-7.2,10.6-10.6c9-8.4,12.7-18.9,12.7-31c0.1-28.2,0-56.3,0-84.5
|
||||
c0-6.6,0-6.6,6.6-6.6c71.5,0,143,0,214.5,0c6.6,0,6.6,0,6.6,6.7c0,26.8,0.2,53.7-0.1,80.5c-0.2,15,5.1,26.8,15.4,38
|
||||
c13.6,14.7,28.9,20.8,48.7,20.1c25.6-1,51.3-0.4,77-0.2c13.9,0.1,24.8-5.1,35.4-14.4c15.9-14,22.1-30.4,21.1-51.3
|
||||
c-1.1-24.3-0.1-48.7-0.4-73c0-5.1,1.4-6.5,6.5-6.5c34.7,0.2,69.3,0,104,0.1c42.3,0.2,78.3,36,78.3,78.3c0.1,246,0,492,0,738
|
||||
c0,6.4,0,6.4-7.3,6.4C842,1013.3,677.7,1013.3,513.4,1013.3z M439.5,678.9c1.6-1,2.2-1.5,3-1.8c11.8-5.8,21.5-14.2,29-24.8
|
||||
c24.3-34.1,24.3-70.9,8.6-107.8c-13.3-31.3-39.3-49.3-71-59.4c-27.6-8.8-56-9.4-84.5-5.6c-20.3,2.7-39.2,9.6-55.5,22.2
|
||||
c-35.5,27.2-48.4,65.1-50.4,108c-0.2,3.7,2.1,3.9,4.8,3.9c22.2,0,44.3-0.1,66.5,0c3.8,0,5.4-1.1,5.3-5.1c-0.1-7.7,1-15.3,3-22.7
|
||||
c5.4-20,16.5-34.7,37.8-39.7c8.1-1.9,16.3-2.1,24.4-1.3c21.4,2.1,36.3,13.1,43.5,33.7c3.5,10.1,3.9,20.4,2.9,31
|
||||
c-2.2,23.4-16.2,39.7-39.1,44.6c-13.2,2.8-26.6,4.1-40.2,4c-3.7,0-5,1.2-4.9,4.9c0.1,16.5,0.2,33,0,49.5c0,4,1.5,5.2,5.3,5.1
|
||||
c12.9-0.3,25.6,0.9,38.3,3c26.3,4.2,43.5,18.8,49.2,42c3.3,13.5,3,27.1-0.2,40.6c-2.3,9.7-6.8,18.4-13.8,25.7
|
||||
c-15.4,16.1-34.5,21.6-56,18.9c-27.5-3.4-43.5-18-50.5-44.8c-1.9-7.3-3.1-14.7-2.8-22.2c0.2-4-1.1-5.6-5.4-5.6
|
||||
c-23.7,0.2-47.3,0.2-71,0c-4,0-5.4,1.2-4.9,5.2c1.4,13.2,2.7,26.5,5.9,39.5c11.1,45.2,38.2,75.6,83.4,88.2
|
||||
c36.7,10.3,73.8,10.1,110.5,0.1c24.5-6.6,44.7-20.1,61-39.8c24.5-29.7,34.4-63.9,31.4-101.9c-2.2-27.4-12.5-51.3-33.6-69.8
|
||||
C460.7,689.3,451.9,682,439.5,678.9z M755,692.5c0-68.6-0.1-137.3,0.1-205.9c0-5.1-1.4-6.5-6.5-6.4c-18.3,0.3-36.7,0.4-55,0
|
||||
c-5.7-0.1-7.2,1.9-8.2,7c-5.9,32.1-24.4,53-56.3,61.1c-17.5,4.5-35.6,5-53.5,5.8c-3.9,0.2-5.2,1.4-5.2,5.3c0.2,15.3,0.2,30.7,0,46
|
||||
c-0.1,4.3,1.6,5.4,5.6,5.3c14.2-0.2,28.3-0.1,42.5-0.1c15.5,0,31,0.1,46.5-0.1c4.1,0,5.9,1.3,5.5,5.4c-0.1,1.7,0,3.3,0,5
|
||||
c0,92.1,0,184.3,0,276.4c0,7.2,0,7.2,7,7.2c23.5,0,47,0,70.5,0c7,0,7,0,7-7.2C755,829.1,755,760.8,755,692.5z"/>
|
||||
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M376.7,199.2c0,24.2,0,48.3,0,72.5c-0.1,23.1-17.4,40.5-40.4,40.6
|
||||
c-23.3,0.1-46.6,0.1-70,0c-22.8-0.1-40.3-17.4-40.3-40.1c-0.1-48.5-0.1-96.9,0-145.4c0-22.4,17.5-40,39.9-40.1
|
||||
c23.7-0.1,47.3-0.1,71,0c22.4,0.1,39.8,17.7,39.8,40.1C376.8,150.9,376.7,175.1,376.7,199.2z"/>
|
||||
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M801.7,199.6c0,24,0,48,0,72c0,23.4-17.3,40.7-40.7,40.8
|
||||
c-23.2,0.1-46.3,0.1-69.5,0c-23.1-0.1-40.5-17.4-40.5-40.5c-0.1-48.3-0.1-96.6,0-144.9c0-22.7,17.5-40.2,40.2-40.3
|
||||
c23.3-0.1,46.6-0.1,70,0c23.1,0.1,40.4,17.4,40.5,40.5C801.8,151.3,801.7,175.4,801.7,199.6z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 37 KiB |
@@ -1,122 +0,0 @@
|
||||
( function( window, undefined ) {
|
||||
'use strict';
|
||||
|
||||
jQuery( function( $ ) {
|
||||
|
||||
/* ===================== *
|
||||
* Add Calendar Meta Box *
|
||||
* ===================== */
|
||||
|
||||
var ajaxEnhance = false,
|
||||
widgets = $( '#widgets-left' );
|
||||
|
||||
if ( widgets.length ) {
|
||||
|
||||
// See: http://wordpress.stackexchange.com/a/37707/48502
|
||||
$( document ).ajaxComplete( function( event, XMLHttpRequest, ajaxOptions ) {
|
||||
|
||||
// Determine which ajax request is this (we are after "save-widget").
|
||||
var request = {},
|
||||
pairs = ajaxOptions.data.split( '&' ),
|
||||
i,
|
||||
split,
|
||||
widget;
|
||||
|
||||
for ( i in pairs ) {
|
||||
split = pairs[i].split('=');
|
||||
request[ decodeURIComponent( split[0] ) ] = decodeURIComponent( split[1] );
|
||||
}
|
||||
|
||||
if ( request.action && ( request.action === 'save-widget' ) ) {
|
||||
|
||||
widget = $( 'input.widget-id[value="' + request['widget-id'] + '"]' ).parents( '.widget' );
|
||||
|
||||
// Trigger manual save, if this was the save request
|
||||
// and if we didn't get the form html response.
|
||||
if ( !XMLHttpRequest.responseText ) {
|
||||
wpWidgets.save( widget, 0, 1, 0 );
|
||||
} else {
|
||||
// We got a response, this could be either our request above,
|
||||
// or a correct widget-save call, so fire an event on which we can hook our code.
|
||||
$( document ).trigger( 'saved_widget', widget );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
// Bind our Select2 function to the saved_widget event.
|
||||
$( document ).bind( 'saved_widget', function( event, widget ) {
|
||||
ajaxEnhance = true;
|
||||
enhanceDropDown();
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
if ( ! ajaxEnhance ) {
|
||||
enhanceDropDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select2.
|
||||
*/
|
||||
function enhanceDropDown() {
|
||||
$( '.simcal-field-select-enhanced' ).each( function( e, i ) {
|
||||
|
||||
var field = $( i ),
|
||||
noResults = field.data( 'noresults' ),
|
||||
allowClear = field.data( 'allowclear' );
|
||||
|
||||
field.select2({
|
||||
allowClear : allowClear != 'undefined' ? allowClear : false,
|
||||
placeholder : {
|
||||
id : '',
|
||||
placeholder: ''
|
||||
},
|
||||
dir : simcal_admin.text_dir != 'undefined' ? simcal_admin.text_dir : 'ltr',
|
||||
tokenSeparators: [','],
|
||||
width : '100%',
|
||||
language : {
|
||||
noResults: function() {
|
||||
return noResults != 'undefined' ? noResults : '';
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
/* ========================= *
|
||||
* Add Calendar Media Button *
|
||||
* ========================= */
|
||||
|
||||
// Very Ugly ThickBox hack: https://core.trac.wordpress.org/ticket/17249
|
||||
$( '#simcal-insert-shortcode-button' ).on( 'click', function() {
|
||||
// ThickBox creates a div which is not immediately available.
|
||||
setTimeout( function() {
|
||||
var thickBox = document.getElementById( 'TB_window');
|
||||
if ( thickBox != 'undefined' ) {
|
||||
thickBox.classList.add( 'simcal-insert-shortcode-modal' );
|
||||
}
|
||||
var thickBoxTitle = document.getElementById( 'TB_title' );
|
||||
if ( thickBoxTitle != 'undefined' ) {
|
||||
thickBoxTitle.classList.add( 'simcal-insert-shortcode-modal-title' );
|
||||
}
|
||||
}, 120 );
|
||||
} );
|
||||
|
||||
// Add shortcode in WordPress post editor.
|
||||
$( '#simcal-insert-shortcode' ).on( 'click', function( e ) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var feedId = $( '#simcal-choose-calendar' ).val();
|
||||
|
||||
wp.media.editor.insert( '[calendar id="' + feedId + '"] ' );
|
||||
|
||||
// Close Thickbox.
|
||||
tb_remove();
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
} )( this );
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
!function(a,b){"use strict";jQuery(function(a){function b(){a(".simcal-field-select-enhanced").each(function(b,c){var d=a(c),e=d.data("noresults"),f=d.data("allowclear");d.select2({allowClear:"undefined"!=f?f:!1,placeholder:{id:"",placeholder:""},dir:"undefined"!=simcal_admin.text_dir?simcal_admin.text_dir:"ltr",tokenSeparators:[","],width:"100%",language:{noResults:function(){return"undefined"!=e?e:""}}})})}var c=!1,d=a("#widgets-left");d.length&&(a(document).ajaxComplete(function(b,c,d){var e,f,g,h={},i=d.data.split("&");for(e in i)f=i[e].split("="),h[decodeURIComponent(f[0])]=decodeURIComponent(f[1]);h.action&&"save-widget"===h.action&&(g=a('input.widget-id[value="'+h["widget-id"]+'"]').parents(".widget"),c.responseText?a(document).trigger("saved_widget",g):wpWidgets.save(g,0,1,0))}),a(document).bind("saved_widget",function(a,d){c=!0,b()})),c||b(),a("#simcal-insert-shortcode-button").on("click",function(){setTimeout(function(){var a=document.getElementById("TB_window");"undefined"!=a&&a.classList.add("simcal-insert-shortcode-modal");var b=document.getElementById("TB_title");"undefined"!=b&&b.classList.add("simcal-insert-shortcode-modal-title")},120)}),a("#simcal-insert-shortcode").on("click",function(b){b.preventDefault();var c=a("#simcal-choose-calendar").val();wp.media.editor.insert('[calendar id="'+c+'"] '),tb_remove()})})}(this);
|
||||
@@ -1,557 +0,0 @@
|
||||
(function( window, undefined ) {
|
||||
'use strict';
|
||||
|
||||
jQuery( function( $ ) {
|
||||
|
||||
/* ======== *
|
||||
* Tooltips *
|
||||
* ======== */
|
||||
|
||||
// Initialize Tooltips (tiptip.js).
|
||||
$( '.simcal-help-tip' ).tipTip( {
|
||||
attribute: 'data-tip',
|
||||
delay: 200,
|
||||
fadeIn: 50,
|
||||
fadeOut: 50
|
||||
} );
|
||||
|
||||
// Tooltips to ease shortcode copying.
|
||||
$( '.simcal-shortcode-tip' ).tipTip( {
|
||||
activation: 'click',
|
||||
defaultPosition: 'top',
|
||||
delay: 200,
|
||||
fadeIn: 50,
|
||||
fadeOut: 50
|
||||
} );
|
||||
|
||||
/* ========== *
|
||||
* Meta Boxes *
|
||||
* ========== */
|
||||
|
||||
var // Calendar Settings Meta Box
|
||||
calendarSettings = $( '#simcal-calendar-settings' ),
|
||||
simCalBoxHandle = calendarSettings.find( '.simcal-box-handle' ),
|
||||
boxHandle = calendarSettings.find( '.hndle' );
|
||||
|
||||
// Move the into the Meta Box header handle.
|
||||
$( simCalBoxHandle ).appendTo( boxHandle );
|
||||
$( function() {
|
||||
// Prevent inputs in meta box headings opening/closing contents.
|
||||
$( boxHandle ).unbind( 'click.postboxes' );
|
||||
calendarSettings.on( 'click', 'h3.hndle', function( event ) {
|
||||
// If the user clicks on some form input inside the h3 the box should not be toggled.
|
||||
if ( $( event.target ).filter( 'input, option, label, select' ).length ) {
|
||||
return;
|
||||
}
|
||||
calendarSettings.toggleClass( 'closed' );
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
// Tabbed Panels in Settings Meta Box.
|
||||
$( document.body ).on( 'simcal-init-tabbed-panels', function() {
|
||||
$( '.simcal-tabs' ).show();
|
||||
$( '.simcal-tabs a' ).click( function() {
|
||||
var panel_wrap = $( this ).closest( 'div.simcal-panels-wrap' );
|
||||
$( 'ul.simcal-tabs li', panel_wrap ).removeClass( 'active' );
|
||||
$( this ).parent().addClass( 'active' );
|
||||
$( 'div.simcal-panel', panel_wrap ).hide();
|
||||
$( $( this ).attr( 'href' ) ).show();
|
||||
return false;
|
||||
} );
|
||||
$( 'div.simcal-panels-wrap' ).each( function() {
|
||||
$( this ).find( 'ul.simcal-tabs > li' ).eq( 0 ).find( 'a' ).click();
|
||||
} );
|
||||
} ).trigger( 'simcal-init-tabbed-panels' );
|
||||
|
||||
// Swap feed type tabs and panels according to selection.
|
||||
$( '#_feed_type' ).on( 'change', function() {
|
||||
|
||||
var selected = $( this ).find( 'option:selected' ),
|
||||
feed = selected.val(),
|
||||
ul = $( '.simcal-tabs' ),
|
||||
tabs = ul.find( '> .simcal-feed-type' ),
|
||||
tab = ul.find( '> .simcal-feed-type-' + feed ),
|
||||
a = ul.find( '> li:first-child > a' );
|
||||
|
||||
tabs.each( function() {
|
||||
$( this ).hide();
|
||||
} );
|
||||
tab.show();
|
||||
a.trigger( 'click' );
|
||||
|
||||
} ).trigger( 'change' );
|
||||
|
||||
// Brings back the meta box after all the manipulations above.
|
||||
calendarSettings.show();
|
||||
|
||||
// Toggle default calendar settings.
|
||||
var defCalViews = $( '#_calendar_view_default-calendar' ),
|
||||
defCalSettings = $( '#default-calendar-settings' ),
|
||||
gridSettings = defCalSettings.find( '.simcal-default-calendar-grid' ),
|
||||
listSettings = defCalSettings.find( '.simcal-default-calendar-list' ),
|
||||
groupedListSettings = defCalSettings.find( '.simcal-default-calendar-list-grouped' );
|
||||
|
||||
defCalViews.on( 'change', function() {
|
||||
|
||||
var selView = $( this ).val();
|
||||
|
||||
if ( 'grid' == selView ) {
|
||||
listSettings.hide();
|
||||
groupedListSettings.hide();
|
||||
gridSettings.show();
|
||||
} else if ( 'list' == selView ) {
|
||||
gridSettings.hide();
|
||||
groupedListSettings.hide();
|
||||
listSettings.show();
|
||||
} else if ( 'list-grouped' == selView ) {
|
||||
gridSettings.hide();
|
||||
listSettings.hide();
|
||||
groupedListSettings.show();
|
||||
}
|
||||
|
||||
} ).trigger( 'change' );
|
||||
|
||||
var calendar_type = $( '#_calendar_type' );
|
||||
|
||||
calendar_type.on( 'change', function() {
|
||||
|
||||
$( 'label[for*="_calendar_view_"]').hide();
|
||||
$( '#calendar-settings-panel table[id*="-settings"]').hide();
|
||||
|
||||
$('label[for="_calendar_view_' + $(this).val() + '"]').show();
|
||||
$( '#calendar-settings-panel table[id="' + $(this).val() + '-settings"]').show();
|
||||
}).trigger( 'change' );
|
||||
|
||||
/* ============ *
|
||||
* Input Fields *
|
||||
* ============ */
|
||||
|
||||
// WordPress color picker.
|
||||
$( '.simcal-field-color-picker' ).wpColorPicker();
|
||||
|
||||
// Select2 enhanced select.
|
||||
$( '.simcal-field-select-enhanced' ).each( function( e, i ) {
|
||||
|
||||
var field = $( i ),
|
||||
noResults = field.data( 'noresults' ),
|
||||
allowClear = field.data( 'allowclear' );
|
||||
|
||||
field.select2( {
|
||||
allowClear: allowClear != 'undefined' ? allowClear : false,
|
||||
placeholder: {
|
||||
id: '',
|
||||
placeholder: ''
|
||||
},
|
||||
dir: simcal_admin.text_dir != 'undefined' ? simcal_admin.text_dir : 'ltr',
|
||||
tokenSeparators: [ ',' ],
|
||||
width: '100%',
|
||||
language: {
|
||||
noResults: function() {
|
||||
return noResults != 'undefined' ? noResults : '';
|
||||
}
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
// jQuery Date Picker.
|
||||
var fieldDatePicker = $( '.simcal-field-date-picker' );
|
||||
fieldDatePicker.each( function( e, i ) {
|
||||
|
||||
var input = $( i ).find( 'input' ),
|
||||
args = {
|
||||
autoSize: true,
|
||||
changeMonth: true,
|
||||
changeYear: true,
|
||||
dateFormat: 'yy-mm-dd',
|
||||
firstDay: 1,
|
||||
prevText: '<i class="simcal-icon-left"></i>',
|
||||
nextText: '<i class="simcal-icon-right"></i>',
|
||||
yearRange: '1900:2050',
|
||||
beforeShow: function( input, instance ) {
|
||||
$( '#ui-datepicker-div' ).addClass( 'simcal-date-picker' );
|
||||
}
|
||||
};
|
||||
|
||||
$( input ).datepicker( args );
|
||||
$( input ).datepicker( 'option', $.datepicker.regional[ simcal_admin.locale ] );
|
||||
|
||||
} );
|
||||
|
||||
// Datetime formatter field.
|
||||
var fieldDateTime = $( '.simcal-field-datetime-format' );
|
||||
fieldDateTime.sortable( {
|
||||
items: '> div',
|
||||
stop: function() {
|
||||
formatDateTime( $( this ) );
|
||||
}
|
||||
} );
|
||||
fieldDateTime.each( function( e, i ) {
|
||||
|
||||
var select = $( i ).find( '> div select' );
|
||||
|
||||
select.each( function( e, i ) {
|
||||
$( i ).on( 'change', function() {
|
||||
formatDateTime( $( this ).closest( 'div.simcal-field-datetime-format' ) );
|
||||
} );
|
||||
} );
|
||||
|
||||
formatDateTime( i );
|
||||
} );
|
||||
// Helper function for datetime formatter field.
|
||||
function formatDateTime( field ) {
|
||||
|
||||
var input = $( field ).find( 'input' ),
|
||||
select = $( field ).find( '> div select' ),
|
||||
code = $( field ).find( 'code' ),
|
||||
format = '',
|
||||
preview = '';
|
||||
|
||||
select.each( function( i, e ) {
|
||||
|
||||
var value = $( e ).val(),
|
||||
selected = $( e ).find( '> option:selected' );
|
||||
|
||||
if ( value.length ) {
|
||||
if ( selected.data( 'trim' ) ) {
|
||||
format = format.trim() + $( e ).val();
|
||||
preview = preview.trim() + selected.data( 'preview' );
|
||||
} else {
|
||||
format += $( e ).val() + ' ';
|
||||
preview += selected.data( 'preview' ) + ' ';
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
input.val( format );
|
||||
code.text( preview );
|
||||
}
|
||||
|
||||
// If PHP datetime formatter is used, this will live preview the user input.
|
||||
$( '.simcal-field-datetime-format-php' ).each( function( e, i ) {
|
||||
|
||||
var input = $( i ).find( 'input' ),
|
||||
preview = $( i ).find( 'code' );
|
||||
|
||||
$( input ).on( 'keyup', function() {
|
||||
|
||||
var data = {
|
||||
action: 'simcal_date_i18n_input_preview',
|
||||
value: input.val()
|
||||
};
|
||||
$.post( simcal_admin.ajax_url, data, function( response ) {
|
||||
$( preview ).text( response.data );
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
/* =============== *
|
||||
* Input Fields UI *
|
||||
* =============== */
|
||||
|
||||
// Enforce min or max value on number inputs
|
||||
$( 'input[type="number"].simcal-field' ).each( function( e, i ) {
|
||||
|
||||
var field = $( i ),
|
||||
min = field.attr( 'min' ),
|
||||
max = field.attr( 'max' );
|
||||
|
||||
field.on( 'change', function() {
|
||||
|
||||
var value = parseInt( $( this ).val() );
|
||||
|
||||
if ( min && ( value < min ) ) {
|
||||
$( this ).val( min );
|
||||
}
|
||||
|
||||
if ( max && ( value > max ) ) {
|
||||
$( this ).val( max );
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
// Show or hide a field when an option is selected.
|
||||
$( '.simcal-field-switch-other' ).on( 'change', function() {
|
||||
|
||||
var options = $( this ).find( 'option' );
|
||||
|
||||
options.each( function( e, option ) {
|
||||
|
||||
var show = $( option ).data( 'show-field' ),
|
||||
showMany = $( option ).data( 'show-fields' ),
|
||||
hide = $( option ).data( 'hide-field' ),
|
||||
hideMany = $( option ).data( 'hide-fields' );
|
||||
|
||||
var fieldShow = show ? $( '#' + show ) : '',
|
||||
fieldHide = hide ? $( '#' + hide ) : '';
|
||||
|
||||
if ( $( option ).is( ':selected' ) ) {
|
||||
if ( fieldShow ) {
|
||||
fieldShow.show();
|
||||
}
|
||||
if ( fieldHide ) {
|
||||
fieldHide.hide();
|
||||
}
|
||||
if ( showMany ) {
|
||||
var s = hideMany.split( ',' );
|
||||
$( s ).each( function( e, field ) {
|
||||
$( '#' + field ).hide();
|
||||
} );
|
||||
}
|
||||
if ( hideMany ) {
|
||||
var h = hideMany.split( ',' );
|
||||
$( h ).each( function( e, field ) {
|
||||
$( '#' + field ).hide();
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
} ).trigger( 'change' );
|
||||
|
||||
// Show another field based on the selection of a field.
|
||||
$( '.simcal-field-show-other' ).on( 'change', function() {
|
||||
|
||||
var options = $( this ).find( 'option' );
|
||||
|
||||
options.each( function( e, option ) {
|
||||
|
||||
var id = $( option ).data( 'show-field' ),
|
||||
field = typeof id !== 'undefined' && id.length ? $( '#' + id ) : '',
|
||||
next = typeof id !== 'undefined' && id.length ? field.next() : '';
|
||||
|
||||
if ( field.length ) {
|
||||
if ( $( option ).is( ':selected' ) ) {
|
||||
field.show();
|
||||
if ( next.hasClass( 'select2' ) ) {
|
||||
next.show();
|
||||
}
|
||||
} else {
|
||||
field.hide();
|
||||
if ( next.hasClass( 'select2' ) ) {
|
||||
next.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
|
||||
} ).trigger( 'change' );
|
||||
|
||||
// Show the next field when a particular option is chosen in a field.
|
||||
$( '.simcal-field-show-next' ).on( 'change', function() {
|
||||
|
||||
var value,
|
||||
trigger,
|
||||
el,
|
||||
next;
|
||||
|
||||
if ( $( this ).is( ':checkbox' ) ) {
|
||||
|
||||
el = $( this ).parent().next();
|
||||
|
||||
if ( $( this ).is( ':checked' ) ) {
|
||||
el.show();
|
||||
} else {
|
||||
el.hide();
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
value = $( this ).val();
|
||||
trigger = $( this ).data( 'show-next-if-value' );
|
||||
el = $( this ).nextUntil().not( 'i' );
|
||||
next = el.length ? el.next() : '';
|
||||
|
||||
if ( value == trigger ) {
|
||||
el.show();
|
||||
if ( next.hasClass( 'select2' ) ) {
|
||||
next.show();
|
||||
}
|
||||
} else {
|
||||
el.hide();
|
||||
if ( next.hasClass( 'select2' ) ) {
|
||||
next.hide();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} ).trigger( 'change' );
|
||||
|
||||
/* ==== *
|
||||
* Misc *
|
||||
* ==== */
|
||||
|
||||
// Clear cache buttons.
|
||||
$( '#simcal-clear-cache' ).on( 'click', function( e ) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var spinner = $( this ).find( 'i' );
|
||||
|
||||
$.ajax( {
|
||||
url: simcal_admin.ajax_url,
|
||||
method: 'POST',
|
||||
data: {
|
||||
action: 'simcal_clear_cache',
|
||||
id: $( this ).data( 'id' )
|
||||
},
|
||||
beforeSend: function() {
|
||||
spinner.fadeToggle();
|
||||
},
|
||||
success: function() {
|
||||
spinner.fadeToggle();
|
||||
},
|
||||
error: function( response ) {
|
||||
console.log( response );
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
// Newsletter signup
|
||||
$( '#simcal-drip-signup' ).on( 'click', function( e ) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var nlMetaBox = $( '#simcal-drip' ),
|
||||
signupDiv = nlMetaBox.find( '.signup' ),
|
||||
thankYou = nlMetaBox.find( '.thank-you' ),
|
||||
nlForm = $( '#simcal-drip-form' ),
|
||||
name = nlMetaBox.find( '#simcal-drip-field-first_name' ),
|
||||
nameReal = nlForm.find( '#simcal-drip-real-field-first_name' ),
|
||||
email = nlMetaBox.find( '#simcal-drip-field-email' ),
|
||||
emailReal = nlForm.find( '#simcal-drip-real-field-email' );
|
||||
|
||||
nameReal.val( name.val() );
|
||||
emailReal.val( email.val() );
|
||||
|
||||
signupDiv.hide();
|
||||
thankYou.show();
|
||||
|
||||
nlForm.submit();
|
||||
|
||||
} );
|
||||
|
||||
// Hide the timezone option for "event source" when a grouped calendar is selected.
|
||||
$( '#_feed_type').on( 'change', function( e ) {
|
||||
if( $(this).val() === 'grouped-calendars' ) {
|
||||
$('#use_calendar').remove();
|
||||
} else {
|
||||
var html = '<option id="use_calendar" value="use_calendar" data-show-field="_use_calendar_warning">Event source default</option>';
|
||||
$('#_feed_timezone_setting').append( html );
|
||||
}
|
||||
});
|
||||
|
||||
/* ========================= *
|
||||
* Add-on License Management *
|
||||
* ========================= */
|
||||
|
||||
$( '.simcal-addon-manage-license' ).on( 'click', function( e ) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var manage_license_action = '',
|
||||
button = $( this ),
|
||||
buttons = button.closest( '.simcal-addon-manage-license-buttons' ),
|
||||
field = button.closest( '.simcal-addon-manage-license-field' ).find( '> input' ),
|
||||
error = buttons.find( '.error' ),
|
||||
spinner = button.find( 'i' );
|
||||
|
||||
if ( $( this ).hasClass( 'activate' ) ) {
|
||||
manage_license_action = 'activate_license';
|
||||
} else if ( $( this ).hasClass( 'deactivate' ) ) {
|
||||
manage_license_action = 'deactivate_license';
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax( {
|
||||
url: simcal_admin.ajax_url,
|
||||
method: 'POST',
|
||||
data: {
|
||||
action: 'simcal_manage_add_on_license',
|
||||
add_on: $( this ).data( 'add-on' ),
|
||||
license_key: field.val(),
|
||||
license_action: manage_license_action,
|
||||
nonce: $( '#simcal_license_manager' ).val()
|
||||
},
|
||||
beforeSend: function() {
|
||||
spinner.fadeToggle();
|
||||
},
|
||||
success: function( response ) {
|
||||
spinner.fadeToggle();
|
||||
if ( 'activate_license' == manage_license_action ) {
|
||||
if ( 'valid' == response.data ) {
|
||||
button.hide();
|
||||
field.attr( 'disabled', 'disabled' );
|
||||
$( buttons ).find( '.label' ).show();
|
||||
$( buttons ).find( '.deactivate' ).show();
|
||||
error.hide();
|
||||
} else {
|
||||
error.show().text( response.data );
|
||||
}
|
||||
} else {
|
||||
if ( 'deactivated' == response.data ) {
|
||||
button.hide();
|
||||
field.removeAttr( 'disabled' );
|
||||
$( buttons ).find( '.label' ).hide();
|
||||
$( buttons ).find( '.activate' ).show();
|
||||
error.hide();
|
||||
} else {
|
||||
error.show().text( response.data );
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function( response ) {
|
||||
console.log( response );
|
||||
spinner.fadeToggle();
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
$( '#simcal-reset-licenses' ).on( 'click', function( e ) {
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
var spinner = $( this ).find( 'i' ),
|
||||
dialog = $( this ).data( 'dialog' ),
|
||||
reply = confirm( dialog );
|
||||
|
||||
if ( true !== reply ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax( {
|
||||
url: simcal_admin.ajax_url,
|
||||
method: 'POST',
|
||||
data: {
|
||||
action: 'simcal_reset_add_ons_licenses',
|
||||
nonce: $( '#simcal_license_manager' ).val()
|
||||
},
|
||||
beforeSend: function() {
|
||||
spinner.toggle();
|
||||
},
|
||||
success: function( response ) {
|
||||
if ( 'success' == response.data ) {
|
||||
location.reload();
|
||||
} else {
|
||||
console.log( response );
|
||||
}
|
||||
},
|
||||
error: function( response ) {
|
||||
console.log( response );
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
})( this );
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
!function(a,b){"use strict";jQuery(function(a){function b(b){var c=a(b).find("input"),d=a(b).find("> div select"),e=a(b).find("code"),f="",g="";d.each(function(b,c){var d=a(c).val(),e=a(c).find("> option:selected");d.length&&(e.data("trim")?(f=f.trim()+a(c).val(),g=g.trim()+e.data("preview")):(f+=a(c).val()+" ",g+=e.data("preview")+" "))}),c.val(f),e.text(g)}a(".simcal-help-tip").tipTip({attribute:"data-tip",delay:200,fadeIn:50,fadeOut:50}),a(".simcal-shortcode-tip").tipTip({activation:"click",defaultPosition:"top",delay:200,fadeIn:50,fadeOut:50});var c=a("#simcal-calendar-settings"),d=c.find(".simcal-box-handle"),e=c.find(".hndle");a(d).appendTo(e),a(function(){a(e).unbind("click.postboxes"),c.on("click","h3.hndle",function(b){a(b.target).filter("input, option, label, select").length||c.toggleClass("closed")})}),a(document.body).on("simcal-init-tabbed-panels",function(){a(".simcal-tabs").show(),a(".simcal-tabs a").click(function(){var b=a(this).closest("div.simcal-panels-wrap");return a("ul.simcal-tabs li",b).removeClass("active"),a(this).parent().addClass("active"),a("div.simcal-panel",b).hide(),a(a(this).attr("href")).show(),!1}),a("div.simcal-panels-wrap").each(function(){a(this).find("ul.simcal-tabs > li").eq(0).find("a").click()})}).trigger("simcal-init-tabbed-panels"),a("#_feed_type").on("change",function(){var b=a(this).find("option:selected"),c=b.val(),d=a(".simcal-tabs"),e=d.find("> .simcal-feed-type"),f=d.find("> .simcal-feed-type-"+c),g=d.find("> li:first-child > a");e.each(function(){a(this).hide()}),f.show(),g.trigger("click")}).trigger("change"),c.show();var f=a("#_calendar_view_default-calendar"),g=a("#default-calendar-settings"),h=g.find(".simcal-default-calendar-grid"),i=g.find(".simcal-default-calendar-list"),j=g.find(".simcal-default-calendar-list-grouped");f.on("change",function(){var b=a(this).val();"grid"==b?(i.hide(),j.hide(),h.show()):"list"==b?(h.hide(),j.hide(),i.show()):"list-grouped"==b&&(h.hide(),i.hide(),j.show())}).trigger("change");var k=a("#_calendar_type");k.on("change",function(){a('label[for*="_calendar_view_"]').hide(),a('#calendar-settings-panel table[id*="-settings"]').hide(),a('label[for="_calendar_view_'+a(this).val()+'"]').show(),a('#calendar-settings-panel table[id="'+a(this).val()+'-settings"]').show()}).trigger("change"),a(".simcal-field-color-picker").wpColorPicker(),a(".simcal-field-select-enhanced").each(function(b,c){var d=a(c),e=d.data("noresults"),f=d.data("allowclear");d.select2({allowClear:"undefined"!=f?f:!1,placeholder:{id:"",placeholder:""},dir:"undefined"!=simcal_admin.text_dir?simcal_admin.text_dir:"ltr",tokenSeparators:[","],width:"100%",language:{noResults:function(){return"undefined"!=e?e:""}}})});var l=a(".simcal-field-date-picker");l.each(function(b,c){var d=a(c).find("input"),e={autoSize:!0,changeMonth:!0,changeYear:!0,dateFormat:"yy-mm-dd",firstDay:1,prevText:'<i class="simcal-icon-left"></i>',nextText:'<i class="simcal-icon-right"></i>',yearRange:"1900:2050",beforeShow:function(b,c){a("#ui-datepicker-div").addClass("simcal-date-picker")}};a(d).datepicker(e),a(d).datepicker("option",a.datepicker.regional[simcal_admin.locale])});var m=a(".simcal-field-datetime-format");m.sortable({items:"> div",stop:function(){b(a(this))}}),m.each(function(c,d){var e=a(d).find("> div select");e.each(function(c,d){a(d).on("change",function(){b(a(this).closest("div.simcal-field-datetime-format"))})}),b(d)}),a(".simcal-field-datetime-format-php").each(function(b,c){var d=a(c).find("input"),e=a(c).find("code");a(d).on("keyup",function(){var b={action:"simcal_date_i18n_input_preview",value:d.val()};a.post(simcal_admin.ajax_url,b,function(b){a(e).text(b.data)})})}),a('input[type="number"].simcal-field').each(function(b,c){var d=a(c),e=d.attr("min"),f=d.attr("max");d.on("change",function(){var b=parseInt(a(this).val());e&&e>b&&a(this).val(e),f&&b>f&&a(this).val(f)})}),a(".simcal-field-switch-other").on("change",function(){var b=a(this).find("option");b.each(function(b,c){var d=a(c).data("show-field"),e=a(c).data("show-fields"),f=a(c).data("hide-field"),g=a(c).data("hide-fields"),h=d?a("#"+d):"",i=f?a("#"+f):"";if(a(c).is(":selected")){if(h&&h.show(),i&&i.hide(),e){var j=g.split(",");a(j).each(function(b,c){a("#"+c).hide()})}if(g){var k=g.split(",");a(k).each(function(b,c){a("#"+c).hide()})}}})}).trigger("change"),a(".simcal-field-show-other").on("change",function(){var b=a(this).find("option");b.each(function(b,c){var d=a(c).data("show-field"),e="undefined"!=typeof d&&d.length?a("#"+d):"",f="undefined"!=typeof d&&d.length?e.next():"";e.length&&(a(c).is(":selected")?(e.show(),f.hasClass("select2")&&f.show()):(e.hide(),f.hasClass("select2")&&f.hide()))})}).trigger("change"),a(".simcal-field-show-next").on("change",function(){var b,c,d,e;a(this).is(":checkbox")?(d=a(this).parent().next(),a(this).is(":checked")?d.show():d.hide()):(b=a(this).val(),c=a(this).data("show-next-if-value"),d=a(this).nextUntil().not("i"),e=d.length?d.next():"",b==c?(d.show(),e.hasClass("select2Line truncated
|
||||
@@ -1,449 +0,0 @@
|
||||
( function( window, undefined ) {
|
||||
'use strict';
|
||||
|
||||
jQuery( function( $ ) {
|
||||
|
||||
// Browse calendar pages.
|
||||
$( '.simcal-default-calendar' ).each( function( e, i ) {
|
||||
|
||||
var calendar = $( i ),
|
||||
id = calendar.data( 'calendar-id' ),
|
||||
offset = calendar.data( 'offset' ),
|
||||
start = calendar.data( 'events-first' ),
|
||||
end = calendar.data( 'calendar-end' ),
|
||||
nav = calendar.find( '.simcal-calendar-head' ),
|
||||
buttons = nav.find( '.simcal-nav-button' ),
|
||||
spinner = calendar.find( '.simcal-ajax-loader' ),
|
||||
current = nav.find( '.simcal-current' ),
|
||||
currentTime = current.data( 'calendar-current' ),
|
||||
currentMonth = current.find( 'span.simcal-current-month' ),
|
||||
currentYear = current.find( 'span.simcal-current-year' ),
|
||||
currentDate = moment.tz( currentTime * 1000, calendar.data( 'timezone' ) ),
|
||||
date,
|
||||
action;
|
||||
|
||||
if ( calendar.hasClass( 'simcal-default-calendar-grid' ) ) {
|
||||
action = 'simcal_default_calendar_draw_grid';
|
||||
// Always use the first of the month in grid.
|
||||
date = new Date( currentDate.year(), currentDate.month() );
|
||||
toggleGridNavButtons( buttons, date.getTime() / 1000, start, end );
|
||||
} else {
|
||||
action = 'simcal_default_calendar_draw_list';
|
||||
toggleListNavButtons( buttons, calendar, start, end, false, currentTime );
|
||||
toggleListHeading( calendar );
|
||||
}
|
||||
|
||||
// Navigate the calendar.
|
||||
buttons.on( 'click', function() {
|
||||
|
||||
var direction = $( this ).hasClass( 'simcal-next' ) ? 'next' : 'prev';
|
||||
|
||||
if ( action == 'simcal_default_calendar_draw_grid' ) {
|
||||
|
||||
// Monthly grid calendars.
|
||||
|
||||
var body = calendar.find( '.simcal-month' ),
|
||||
newDate,
|
||||
month,
|
||||
year;
|
||||
|
||||
if ( 'prev' == direction ) {
|
||||
// Beginning of the previous month.
|
||||
newDate = new Date( date.setMonth( date.getMonth() - 1, 1 ) );
|
||||
} else {
|
||||
// Last day of next month.
|
||||
newDate = new Date( date.setMonth( date.getMonth() + 2, 1 ) );
|
||||
newDate.setDate( 0 );
|
||||
newDate.setHours( 23 );
|
||||
newDate.setMinutes( 59 );
|
||||
newDate.setSeconds( 59 );
|
||||
}
|
||||
|
||||
month = newDate.getMonth();
|
||||
year = newDate.getFullYear();
|
||||
|
||||
$.ajax({
|
||||
url : simcal_default_calendar.ajax_url,
|
||||
method : 'POST',
|
||||
dataType : 'json',
|
||||
cache : false,
|
||||
data : {
|
||||
action: action,
|
||||
month : month + 1, // month count in PHP goes 1-12 vs 0-11 in JavaScript
|
||||
year : year,
|
||||
id : id
|
||||
},
|
||||
beforeSend: function() {
|
||||
spinner.fadeToggle();
|
||||
},
|
||||
success : function( response ) {
|
||||
|
||||
currentMonth.text( simcal_default_calendar.months.full[month] );
|
||||
currentYear.text( year );
|
||||
current.attr( 'data-calendar-current', ( newDate.getTime() / 1000 ) + offset + 1 );
|
||||
|
||||
toggleGridNavButtons( buttons, newDate.getTime() / 1000, start, end );
|
||||
|
||||
spinner.fadeToggle();
|
||||
|
||||
date = newDate;
|
||||
|
||||
body.replaceWith( response.data );
|
||||
|
||||
calendarBubbles( calendar, list );
|
||||
expandEventsToggle();
|
||||
},
|
||||
error : function( response ) {
|
||||
console.log(response );
|
||||
}
|
||||
} );
|
||||
|
||||
} else {
|
||||
|
||||
// List calendars.
|
||||
|
||||
var list = calendar.find( '.simcal-events-list-container' ),
|
||||
prev = list.data( 'prev' ),
|
||||
next = list.data( 'next' ),
|
||||
timestamp = direction == 'prev' ? prev : next;
|
||||
|
||||
$.ajax( {
|
||||
url : simcal_default_calendar.ajax_url,
|
||||
method : 'POST',
|
||||
dataType : 'json',
|
||||
cache : false,
|
||||
data : {
|
||||
action: action,
|
||||
ts : timestamp,
|
||||
id : id
|
||||
},
|
||||
beforeSend: function() {
|
||||
spinner.fadeToggle();
|
||||
},
|
||||
success : function( response ) {
|
||||
|
||||
list.replaceWith( response.data );
|
||||
current.attr( 'data-calendar-current', timestamp );
|
||||
|
||||
toggleListHeading( calendar );
|
||||
toggleListNavButtons( buttons, calendar, start, end, direction, timestamp );
|
||||
|
||||
spinner.fadeToggle();
|
||||
expandEventsToggle();
|
||||
},
|
||||
error : function( response ) {
|
||||
console.log( response );
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
} );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Enable or disable grid calendar navigation buttons.
|
||||
*
|
||||
* @param buttons Previous and Next buttons elements.
|
||||
* @param time Current time.
|
||||
* @param min Lower bound timestamp.
|
||||
* @param max Upper bound timestamp.
|
||||
*/
|
||||
function toggleGridNavButtons( buttons, time, min, max ) {
|
||||
|
||||
buttons.each( function( e, i ) {
|
||||
|
||||
var button = $( i),
|
||||
month = new Date( time * 1000 );
|
||||
|
||||
if ( button.hasClass( 'simcal-prev' ) ) {
|
||||
|
||||
month = new Date( month.setMonth( month.getMonth(), 1 ) );
|
||||
month.setDate( 0 );
|
||||
|
||||
if ( month.getTime() / 1000 <= min ) {
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
} else {
|
||||
button.removeAttr( 'disabled' );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
month = new Date( month.setMonth( month.getMonth() + 1, 1 ) );
|
||||
month.setDate( 0 );
|
||||
month.setHours( 23 );
|
||||
month.setMinutes( 59 );
|
||||
month.setSeconds( 59 );
|
||||
|
||||
if ( month.getTime() / 1000 >= max ) {
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
} else {
|
||||
button.removeAttr( 'disabled' );
|
||||
}
|
||||
}
|
||||
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable grid calendar navigation buttons.
|
||||
*
|
||||
* @param buttons Previous and Next button elements.
|
||||
* @param calendar Current calendar.
|
||||
* @param start Lower bound timestamp.
|
||||
* @param end Upper bound timestamp.
|
||||
* @param direction Direction intent.
|
||||
*/
|
||||
function toggleListNavButtons( buttons, calendar, start, end, direction, currentTime ) {
|
||||
|
||||
var list = calendar.find( '.simcal-events-list-container' ),
|
||||
prev = list.data( 'prev' ),
|
||||
next = list.data( 'next' ),
|
||||
last_event = list.find( 'li.simcal-event:last').data( 'start' );
|
||||
|
||||
//var currentTime = nav.find( '.simcal-current' ).data( 'calendar-current' );
|
||||
// TODO: Add script_debug check to show these
|
||||
//console.log( "current time: ", currentTime );
|
||||
//console.log( "start: ", start );
|
||||
//console.log( "end: ", end );
|
||||
//console.log( 'next: ', next );
|
||||
//console.log( 'last event: ', last_event );
|
||||
//console.log( "ct == start", ( ct == start ? "Yes" : "No" ) );
|
||||
|
||||
buttons.each( function( e, b ) {
|
||||
|
||||
var button = $( b );
|
||||
|
||||
if ( direction ) {
|
||||
|
||||
if ( direction == 'prev' && button.hasClass( 'simcal-prev' ) ) {
|
||||
if ( ( prev <= start ) && ( currentTime <= start ) ) {
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
}
|
||||
} else if ( button.hasClass( 'simcal-prev' ) ) {
|
||||
button.removeAttr( 'disabled' );
|
||||
}
|
||||
|
||||
if ( direction == 'next' && button.hasClass( 'simcal-next' ) ) {
|
||||
if ( ( ( next >= end ) && ( currentTime >= end ) ) || last_event >= end ) {
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
}
|
||||
} else if( $(button).hasClass( 'simcal-next' ) ) {
|
||||
button.removeAttr( 'disabled' );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if ( prev <= start && button.hasClass( 'simcal-prev' ) && ( currentTime <= start ) ) {
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
}
|
||||
|
||||
if ( ( next >= end && button.hasClass( 'simcal-next' ) && ( currentTime >= end ) ) || last_event >= end ) {
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
}
|
||||
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the list heading with current page.
|
||||
*
|
||||
* @param calendar Current calendar.
|
||||
*/
|
||||
function toggleListHeading( calendar ) {
|
||||
|
||||
var current = $( calendar ).find( '.simcal-current' ),
|
||||
heading = $( calendar ).find( '.simcal-events-list-container' ),
|
||||
small = heading.data( 'heading-small' ),
|
||||
large = heading.data( 'heading-large' ),
|
||||
newHeading = $( '<h3 />' );
|
||||
|
||||
if ( calendar.width() < 400 ) {
|
||||
newHeading.text( small );
|
||||
} else {
|
||||
newHeading.text( large );
|
||||
}
|
||||
|
||||
current.html( newHeading );
|
||||
}
|
||||
|
||||
var gridCalendars = $( '.simcal-default-calendar-grid' );
|
||||
|
||||
/**
|
||||
* Default calendar grid event bubbles.
|
||||
*
|
||||
* Initializes tooltips for events in grid.
|
||||
* Adjusts UI for mobile or desktop.
|
||||
*
|
||||
* @param calendar The calendar element.
|
||||
*/
|
||||
function calendarBubbles( calendar ) {
|
||||
|
||||
var table = $( calendar ).find( '> table' ),
|
||||
thead = table.find( 'thead' ),
|
||||
weekDayNames = thead.find( 'th.simcal-week-day' ),
|
||||
cells = table.find( 'td.simcal-day > div' ),
|
||||
eventsList = table.find( 'ul.simcal-events' ),
|
||||
eventTitles = eventsList.find( '> li > .simcal-event-title' ),
|
||||
eventsToggle = table.find( '.simcal-events-toggle' ),
|
||||
eventsDots = table.find( 'span.simcal-events-dots' ),
|
||||
events = table.find( '.simcal-tooltip-content' ),
|
||||
hiddenEvents = table.find( '.simcal-event-toggled' ),
|
||||
bubbleTrigger = table.data( 'event-bubble-trigger' ),
|
||||
width = cells.first().width();
|
||||
|
||||
if ( width < 60 ) {
|
||||
|
||||
weekDayNames.each( function( e, w ) {
|
||||
$( w ).text( $( w ).data( 'screen-small' ) );
|
||||
} );
|
||||
|
||||
// Hide list of events titles and show dots.
|
||||
eventsList.hide();
|
||||
eventTitles.hide();
|
||||
if ( eventsToggle != 'undefined' ) {
|
||||
eventsToggle.hide();
|
||||
if ( hiddenEvents != 'undefined' ) {
|
||||
hiddenEvents.show();
|
||||
}
|
||||
}
|
||||
eventsDots.show();
|
||||
|
||||
// Force click/tap on mobile.
|
||||
bubbleTrigger = 'click';
|
||||
// Adapts cells to be more squareish on mobile.
|
||||
var minH = ( width - 10 ) + 'px';
|
||||
cells.css( 'min-height', minH );
|
||||
table.find( 'span.simcal-events-dots:not(:empty)' ).css( 'min-height', minH );
|
||||
|
||||
} else {
|
||||
|
||||
if ( width <= 240 ) {
|
||||
weekDayNames.each( function( e, w ) {
|
||||
$( w ).text( $( w ).data( 'screen-medium' ) );
|
||||
});
|
||||
} else {
|
||||
weekDayNames.each( function( e, w ) {
|
||||
$( w ).text( $( w ).data( 'screen-large' ) );
|
||||
} );
|
||||
}
|
||||
|
||||
// Hide dots and show list of events titles and toggle.
|
||||
eventsList.show();
|
||||
eventTitles.show();
|
||||
if ( eventsToggle != 'undefined' ) {
|
||||
eventsToggle.show();
|
||||
if ( hiddenEvents != 'undefined' ) {
|
||||
hiddenEvents.hide();
|
||||
}
|
||||
}
|
||||
eventsDots.hide();
|
||||
|
||||
// Cells default min-height value.
|
||||
cells.css( 'min-height', ( width ) + 'px' );
|
||||
}
|
||||
|
||||
// Create bubbles for each cell.
|
||||
cells.each( function( e, cell ) {
|
||||
|
||||
var cellDots = $( cell ).find( 'span.simcal-events-dots' ),
|
||||
tooltips = $( cell ).find( '.simcal-tooltip' ),
|
||||
eventBubbles,
|
||||
content,
|
||||
last;
|
||||
|
||||
// Mobile mode.
|
||||
if ( width < 60 ) {
|
||||
events.show();
|
||||
// Use a single bubble from dots as a whole.
|
||||
eventBubbles = cellDots;
|
||||
} else {
|
||||
events.hide();
|
||||
// Create a bubble for each event in list.
|
||||
eventBubbles = tooltips;
|
||||
}
|
||||
|
||||
eventBubbles.each( function( e, i ) {
|
||||
$( i ).qtip( {
|
||||
content : width < 60 ? $( cell ).find( 'ul.simcal-events' ) : $( i ).find( '> .simcal-tooltip-content' ),
|
||||
position: {
|
||||
my : 'top center',
|
||||
at : 'bottom center',
|
||||
target : $(i),
|
||||
viewport: width < 60 ? $( window ) : true,
|
||||
adjust : {
|
||||
method: 'shift',
|
||||
scroll: false
|
||||
}
|
||||
},
|
||||
style : {
|
||||
def : false,
|
||||
classes: 'simcal-default-calendar simcal-event-bubble'
|
||||
},
|
||||
show : {
|
||||
solo : true,
|
||||
effect: false,
|
||||
event : bubbleTrigger == 'hover' ? 'mouseenter' : 'click'
|
||||
},
|
||||
hide : {
|
||||
fixed : true,
|
||||
effect: false,
|
||||
event : bubbleTrigger == 'click' ? 'unfocus' : 'mouseleave',
|
||||
delay: 100
|
||||
},
|
||||
events : {
|
||||
show: function( event, current ) {
|
||||
// Hide when another tooltip opens:
|
||||
if ( last && last.id ) {
|
||||
if ( last.id != current.id ) {
|
||||
last.hide();
|
||||
}
|
||||
}
|
||||
last = current;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
// Event bubbles and calendar UI triggers.
|
||||
gridCalendars.each( function( e, calendar ) {
|
||||
calendarBubbles( calendar );
|
||||
$( calendar ).on( 'change', function() {
|
||||
calendarBubbles( this );
|
||||
} );
|
||||
} );
|
||||
// Viewport changes might require triggering calendar mobile mode.
|
||||
window.onresize = function() {
|
||||
gridCalendars.each( function( e, calendar ) {
|
||||
calendarBubbles( calendar );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle to expand events.
|
||||
*/
|
||||
function expandEventsToggle() {
|
||||
$( '.simcal-events-toggle' ).each( function( e, button ) {
|
||||
|
||||
var list = $( button ).prev( '.simcal-events' ),
|
||||
toggled = list.find( '.simcal-event-toggled' ),
|
||||
arrow = $( button ).find( 'i' );
|
||||
|
||||
$( button ).on( 'click', function() {
|
||||
arrow.toggleClass( 'simcal-icon-rotate-180' );
|
||||
toggled.slideToggle();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
expandEventsToggle();
|
||||
|
||||
} );
|
||||
|
||||
} )( this );
|
||||
@@ -1,6 +0,0 @@
|
||||
/*! Simple Calendar - 3.1.2
|
||||
* https://simplecalendar.io
|
||||
* Copyright (c) Moonstone Media 2016
|
||||
* Licensed GPLv2+ */
|
||||
|
||||
!function(a,b){"use strict";jQuery(function(b){function c(a,c,d,e){a.each(function(a,f){var g=b(f),h=new Date(1e3*c);g.hasClass("simcal-prev")?(h=new Date(h.setMonth(h.getMonth(),1)),h.setDate(0),h.getTime()/1e3<=d?g.attr("disabled","disabled"):g.removeAttr("disabled")):(h=new Date(h.setMonth(h.getMonth()+1,1)),h.setDate(0),h.setHours(23),h.setMinutes(59),h.setSeconds(59),h.getTime()/1e3>=e?g.attr("disabled","disabled"):g.removeAttr("disabled"))})}function d(a,c,d,e,f,g){var h=c.find(".simcal-events-list-container"),i=h.data("prev"),j=h.data("next"),k=h.find("li.simcal-event:last").data("start");a.each(function(a,c){var h=b(c);f?("prev"==f&&h.hasClass("simcal-prev")?d>=i&&d>=g&&h.attr("disabled","disabled"):h.hasClass("simcal-prev")&&h.removeAttr("disabled"),"next"==f&&h.hasClass("simcal-next")?(j>=e&&g>=e||k>=e)&&h.attr("disabled","disabled"):b(h).hasClass("simcal-next")&&h.removeAttr("disabled")):(d>=i&&h.hasClass("simcal-prev")&&d>=g&&h.attr("disabled","disabled"),(j>=e&&h.hasClass("simcal-next")&&g>=e||k>=e)&&h.attr("disabled","disabled"))})}function e(a){var c=b(a).find(".simcal-current"),d=b(a).find(".simcal-events-list-container"),e=d.data("heading-small"),f=d.data("heading-large"),g=b("<h3 />");a.width()<400?g.text(e):g.text(f),c.html(g)}function f(c){var d=b(c).find("> table"),e=d.find("thead"),f=e.find("th.simcal-week-day"),g=d.find("td.simcal-day > div"),h=d.find("ul.simcal-events"),i=h.find("> li > .simcal-event-title"),j=d.find(".simcal-events-toggle"),k=d.find("span.simcal-events-dots"),l=d.find(".simcal-tooltip-content"),m=d.find(".simcal-event-toggled"),n=d.data("event-bubble-trigger"),o=g.first().width();if(60>o){f.each(function(a,c){b(c).text(b(c).data("screen-small"))}),h.hide(),i.hide(),"undefined"!=j&&(j.hide(),"undefined"!=m&&m.show()),k.show(),n="click";var p=o-10+"px";g.css("min-height",p),d.find("span.simcal-events-dots:not(:empty)").css("min-height",p)}else 240>=o?f.each(function(a,c){b(c).text(b(c).data("screen-medium"))}):f.each(function(a,c){b(c).text(b(c).data("screen-large"))}),h.show(),i.show(),"undefined"!=j&&(j.show(),"undefined"!=m&&m.hide()),k.hide(),g.css("min-height",o+"px");g.each(function(c,d){var e,f,g=b(d).find("span.simcal-events-dots"),h=b(d).find(".simcal-tooltip");60>o?(l.show(),e=g):(l.hide(),e=h),e.each(function(c,e){b(e).qtip({content:60>o?b(d).find("ul.simcal-events"):b(e).find("> .simcal-tooltip-content"),position:{my:"top center",at:"bottom center",target:b(e),viewport:60>o?b(a):!0,adjust:{method:"shift",scroll:!1}},style:{def:!1,classes:"simcal-default-calendar simcal-event-bubble"},show:{solo:!0,effect:!1,event:"hover"==n?"mouseenter":"click"},hide:{fixed:!0,effect:!1,event:"click"==n?"unfocus":"mouseleave",delay:100},events:{show:function(a,b){f&&f.id&&f.id!=b.id&&f.hide(),f=b}}})})})}function g(){b(".simcal-events-toggle").each(function(a,c){var d=b(c).prev(".simcal-events"),e=d.find(".simcal-event-toggled"),f=b(c).find("i");b(c).on("click",function(){f.toggleClass("simcal-icon-rotate-180"),e.slideToggle()})})}b(".simcal-default-calendar").each(function(a,h){var i,j,k=b(h),l=k.data("calendar-id"),m=k.data("offset"),n=k.data("events-first"),o=k.data("calendar-end"),p=k.find(".simcal-calendar-head"),q=p.find(".simcal-nav-button"),r=k.find(".simcal-ajax-loader"),s=p.find(".simcal-current"),t=s.data("calendar-current"),u=s.find("span.simcal-current-month"),v=s.find("span.simcal-current-year"),w=moment.tz(1e3*t,k.data("timezone"));k.hasClass("simcal-default-calendar-grid")?(j="simcal_default_calendar_draw_grid",i=new Date(w.year(),w.month()),c(q,i.getTime()/1e3,n,o)):(j="simcal_default_calendar_draw_list",d(q,k,n,o,!1,t),e(k)),q.on("click",function(){var a=b(this).hasClass("simcal-next")?"next":"prev";if("simcal_default_calendar_draw_grid"==j){var h,p,t,w=k.find(".simcal-month");"prev"==a?h=new Date(i.setMonth(i.getMonth()-1,1)):(h=new Date(i.setMonth(i.getMonth()+2,1)),h.setDate(0),h.setHours(23),h.setMinutes(59),h.setSeconds(59)),p=h.getMonth(),t=h.getFullYear(),b.ajax({url:simcal_default_calendar.ajax_url,method:"POST",dataType:"json",cache:!1,data:{action:j,month:p+1,year:t,id:l},beforeSend:function(){r.fadeToggle()},success:function(a){u.text(simcal_default_calendar.months.full[p]),v.text(t),s.attr("data-calendar-current",h.getTime()/1e3+m+1),c(q,h.getTime()/1e3,n,o),r.fadeToggle(),i=h,w.replaceWith(a.data),f(k,x),g()},error:function(a){console.log(a)}})}else{var x=k.find(".simcal-events-list-container"),y=x.data("prev"),z=x.data("next"),A="prev"==a?y:z;b.ajax({url:simcal_default_calendar.ajax_url,method:"POST",dataType:"json",cache:!1,data:{action:j,ts:A,id:l},beforeSend:function(){r.fadeToggle()},success:function(b){x.replaceWith(b.data),s.attr("data-calendar-current",A),e(k),d(q,k,n,o,a,A),r.fadeToggle(),g()},error:function(a){console.log(a)}})}})});var h=b(".simcal-default-calendar-grid");h.each(function(a,c){f(c),b(c).on("change",function(){f(this)})}),a.onresize=function(){h.each(function(a,b){f(b)})},g()})}(this);
|
||||
@@ -1,487 +0,0 @@
|
||||
/*!
|
||||
* imagesLoaded PACKAGED v4.1.0
|
||||
* JavaScript is all like "You images are done yet or what?"
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
/**
|
||||
* EvEmitter v1.0.1
|
||||
* Lil' event emitter
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
/* jshint unused: true, undef: true, strict: true */
|
||||
|
||||
( function( global, factory ) {
|
||||
// universal module definition
|
||||
/* jshint strict: false */ /* globals define, module */
|
||||
if ( typeof define == 'function' && define.amd ) {
|
||||
// AMD - RequireJS
|
||||
define( 'ev-emitter/ev-emitter',factory );
|
||||
} else if ( typeof module == 'object' && module.exports ) {
|
||||
// CommonJS - Browserify, Webpack
|
||||
module.exports = factory();
|
||||
} else {
|
||||
// Browser globals
|
||||
global.EvEmitter = factory();
|
||||
}
|
||||
|
||||
}( this, function() {
|
||||
|
||||
|
||||
|
||||
function EvEmitter() {}
|
||||
|
||||
var proto = EvEmitter.prototype;
|
||||
|
||||
proto.on = function( eventName, listener ) {
|
||||
if ( !eventName || !listener ) {
|
||||
return;
|
||||
}
|
||||
// set events hash
|
||||
var events = this._events = this._events || {};
|
||||
// set listeners array
|
||||
var listeners = events[ eventName ] = events[ eventName ] || [];
|
||||
// only add once
|
||||
if ( listeners.indexOf( listener ) == -1 ) {
|
||||
listeners.push( listener );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
proto.once = function( eventName, listener ) {
|
||||
if ( !eventName || !listener ) {
|
||||
return;
|
||||
}
|
||||
// add event
|
||||
this.on( eventName, listener );
|
||||
// set once flag
|
||||
// set onceEvents hash
|
||||
var onceEvents = this._onceEvents = this._onceEvents || {};
|
||||
// set onceListeners array
|
||||
var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || [];
|
||||
// set flag
|
||||
onceListeners[ listener ] = true;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
proto.off = function( eventName, listener ) {
|
||||
var listeners = this._events && this._events[ eventName ];
|
||||
if ( !listeners || !listeners.length ) {
|
||||
return;
|
||||
}
|
||||
var index = listeners.indexOf( listener );
|
||||
if ( index != -1 ) {
|
||||
listeners.splice( index, 1 );
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
proto.emitEvent = function( eventName, args ) {
|
||||
var listeners = this._events && this._events[ eventName ];
|
||||
if ( !listeners || !listeners.length ) {
|
||||
return;
|
||||
}
|
||||
var i = 0;
|
||||
var listener = listeners[i];
|
||||
args = args || [];
|
||||
// once stuff
|
||||
var onceListeners = this._onceEvents && this._onceEvents[ eventName ];
|
||||
|
||||
while ( listener ) {
|
||||
var isOnce = onceListeners && onceListeners[ listener ];
|
||||
if ( isOnce ) {
|
||||
// remove listener
|
||||
// remove before trigger to prevent recursion
|
||||
this.off( eventName, listener );
|
||||
// unset once flag
|
||||
delete onceListeners[ listener ];
|
||||
}
|
||||
// trigger listener
|
||||
listener.apply( this, args );
|
||||
// get next listener
|
||||
i += isOnce ? 0 : 1;
|
||||
listener = listeners[i];
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
return EvEmitter;
|
||||
|
||||
}));
|
||||
|
||||
/*!
|
||||
* imagesLoaded v4.1.0
|
||||
* JavaScript is all like "You images are done yet or what?"
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
( function( window, factory ) { 'use strict';
|
||||
// universal module definition
|
||||
|
||||
/*global define: false, module: false, require: false */
|
||||
|
||||
if ( typeof define == 'function' && define.amd ) {
|
||||
// AMD
|
||||
define( [
|
||||
'ev-emitter/ev-emitter'
|
||||
], function( EvEmitter ) {
|
||||
return factory( window, EvEmitter );
|
||||
});
|
||||
} else if ( typeof module == 'object' && module.exports ) {
|
||||
// CommonJS
|
||||
module.exports = factory(
|
||||
window,
|
||||
require('ev-emitter')
|
||||
);
|
||||
} else {
|
||||
// browser global
|
||||
window.imagesLoaded = factory(
|
||||
window,
|
||||
window.EvEmitter
|
||||
);
|
||||
}
|
||||
|
||||
})( window,
|
||||
|
||||
// -------------------------- factory -------------------------- //
|
||||
|
||||
function factory( window, EvEmitter ) {
|
||||
|
||||
|
||||
|
||||
var $ = window.jQuery;
|
||||
var console = window.console;
|
||||
|
||||
// -------------------------- helpers -------------------------- //
|
||||
|
||||
// extend objects
|
||||
function extend( a, b ) {
|
||||
for ( var prop in b ) {
|
||||
a[ prop ] = b[ prop ];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// turn element or nodeList into an array
|
||||
function makeArray( obj ) {
|
||||
var ary = [];
|
||||
if ( Array.isArray( obj ) ) {
|
||||
// use object if already an array
|
||||
ary = obj;
|
||||
} else if ( typeof obj.length == 'number' ) {
|
||||
// convert nodeList to array
|
||||
for ( var i=0; i < obj.length; i++ ) {
|
||||
ary.push( obj[i] );
|
||||
}
|
||||
} else {
|
||||
// array of single index
|
||||
ary.push( obj );
|
||||
}
|
||||
return ary;
|
||||
}
|
||||
|
||||
// -------------------------- imagesLoaded -------------------------- //
|
||||
|
||||
/**
|
||||
* @param {Array, Element, NodeList, String} elem
|
||||
* @param {Object or Function} options - if function, use as callback
|
||||
* @param {Function} onAlways - callback function
|
||||
*/
|
||||
function ImagesLoaded( elem, options, onAlways ) {
|
||||
// coerce ImagesLoaded() without new, to be new ImagesLoaded()
|
||||
if ( !( this instanceof ImagesLoaded ) ) {
|
||||
return new ImagesLoaded( elem, options, onAlways );
|
||||
}
|
||||
// use elem as selector string
|
||||
if ( typeof elem == 'string' ) {
|
||||
elem = document.querySelectorAll( elem );
|
||||
}
|
||||
|
||||
this.elements = makeArray( elem );
|
||||
this.options = extend( {}, this.options );
|
||||
|
||||
if ( typeof options == 'function' ) {
|
||||
onAlways = options;
|
||||
} else {
|
||||
extend( this.options, options );
|
||||
}
|
||||
|
||||
if ( onAlways ) {
|
||||
this.on( 'always', onAlways );
|
||||
}
|
||||
|
||||
this.getImages();
|
||||
|
||||
if ( $ ) {
|
||||
// add jQuery Deferred object
|
||||
this.jqDeferred = new $.Deferred();
|
||||
}
|
||||
|
||||
// HACK check async to allow time to bind listeners
|
||||
setTimeout( function() {
|
||||
this.check();
|
||||
}.bind( this ));
|
||||
}
|
||||
|
||||
ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
|
||||
|
||||
ImagesLoaded.prototype.options = {};
|
||||
|
||||
ImagesLoaded.prototype.getImages = function() {
|
||||
this.images = [];
|
||||
|
||||
// filter & find items if we have an item selector
|
||||
this.elements.forEach( this.addElementImages, this );
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} element
|
||||
*/
|
||||
ImagesLoaded.prototype.addElementImages = function( elem ) {
|
||||
// filter siblings
|
||||
if ( elem.nodeName == 'IMG' ) {
|
||||
this.addImage( elem );
|
||||
}
|
||||
// get background image on element
|
||||
if ( this.options.background === true ) {
|
||||
this.addElementBackgroundImages( elem );
|
||||
}
|
||||
|
||||
// find children
|
||||
// no non-element nodes, #143
|
||||
var nodeType = elem.nodeType;
|
||||
if ( !nodeType || !elementNodeTypes[ nodeType ] ) {
|
||||
return;
|
||||
}
|
||||
var childImgs = elem.querySelectorAll('img');
|
||||
// concat childElems to filterFound array
|
||||
for ( var i=0; i < childImgs.length; i++ ) {
|
||||
var img = childImgs[i];
|
||||
this.addImage( img );
|
||||
}
|
||||
|
||||
// get child background images
|
||||
if ( typeof this.options.background == 'string' ) {
|
||||
var children = elem.querySelectorAll( this.options.background );
|
||||
for ( i=0; i < children.length; i++ ) {
|
||||
var child = children[i];
|
||||
this.addElementBackgroundImages( child );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var elementNodeTypes = {
|
||||
1: true,
|
||||
9: true,
|
||||
11: true
|
||||
};
|
||||
|
||||
ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
|
||||
var style = getComputedStyle( elem );
|
||||
if ( !style ) {
|
||||
// Firefox returns null if in a hidden iframe https://bugzil.la/548397
|
||||
return;
|
||||
}
|
||||
// get url inside url("...")
|
||||
var reURL = /url\((['"])?(.*?)\1\)/gi;
|
||||
var matches = reURL.exec( style.backgroundImage );
|
||||
while ( matches !== null ) {
|
||||
var url = matches && matches[2];
|
||||
if ( url ) {
|
||||
this.addBackground( url, elem );
|
||||
}
|
||||
matches = reURL.exec( style.backgroundImage );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Image} img
|
||||
*/
|
||||
ImagesLoaded.prototype.addImage = function( img ) {
|
||||
var loadingImage = new LoadingImage( img );
|
||||
this.images.push( loadingImage );
|
||||
};
|
||||
|
||||
ImagesLoaded.prototype.addBackground = function( url, elem ) {
|
||||
var background = new Background( url, elem );
|
||||
this.images.push( background );
|
||||
};
|
||||
|
||||
ImagesLoaded.prototype.check = function() {
|
||||
var _this = this;
|
||||
this.progressedCount = 0;
|
||||
this.hasAnyBroken = false;
|
||||
// complete if no images
|
||||
if ( !this.images.length ) {
|
||||
this.complete();
|
||||
return;
|
||||
}
|
||||
|
||||
function onProgress( image, elem, message ) {
|
||||
// HACK - Chrome triggers event before object properties have changed. #83
|
||||
setTimeout( function() {
|
||||
_this.progress( image, elem, message );
|
||||
});
|
||||
}
|
||||
|
||||
this.images.forEach( function( loadingImage ) {
|
||||
loadingImage.once( 'progress', onProgress );
|
||||
loadingImage.check();
|
||||
});
|
||||
};
|
||||
|
||||
ImagesLoaded.prototype.progress = function( image, elem, message ) {
|
||||
this.progressedCount++;
|
||||
this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
|
||||
// progress event
|
||||
this.emitEvent( 'progress', [ this, image, elem ] );
|
||||
if ( this.jqDeferred && this.jqDeferred.notify ) {
|
||||
this.jqDeferred.notify( this, image );
|
||||
}
|
||||
// check if completed
|
||||
if ( this.progressedCount == this.images.length ) {
|
||||
this.complete();
|
||||
}
|
||||
|
||||
if ( this.options.debug && console ) {
|
||||
console.log( 'progress: ' + message, image, elem );
|
||||
}
|
||||
};
|
||||
|
||||
ImagesLoaded.prototype.complete = function() {
|
||||
var eventName = this.hasAnyBroken ? 'fail' : 'done';
|
||||
this.isComplete = true;
|
||||
this.emitEvent( eventName, [ this ] );
|
||||
this.emitEvent( 'always', [ this ] );
|
||||
if ( this.jqDeferred ) {
|
||||
var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
|
||||
this.jqDeferred[ jqMethod ]( this );
|
||||
}
|
||||
};
|
||||
|
||||
// -------------------------- -------------------------- //
|
||||
|
||||
function LoadingImage( img ) {
|
||||
this.img = img;
|
||||
}
|
||||
|
||||
LoadingImage.prototype = Object.create( EvEmitter.prototype );
|
||||
|
||||
LoadingImage.prototype.check = function() {
|
||||
// If complete is true and browser supports natural sizes,
|
||||
// try to check for image status manually.
|
||||
var isComplete = this.getIsImageComplete();
|
||||
if ( isComplete ) {
|
||||
// report based on naturalWidth
|
||||
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
|
||||
return;
|
||||
}
|
||||
|
||||
// If none of the checks above matched, simulate loading on detached element.
|
||||
this.proxyImage = new Image();
|
||||
this.proxyImage.addEventListener( 'load', this );
|
||||
this.proxyImage.addEventListener( 'error', this );
|
||||
// bind to image as well for Firefox. #191
|
||||
this.img.addEventListener( 'load', this );
|
||||
this.img.addEventListener( 'error', this );
|
||||
this.proxyImage.src = this.img.src;
|
||||
};
|
||||
|
||||
LoadingImage.prototype.getIsImageComplete = function() {
|
||||
return this.img.complete && this.img.naturalWidth !== undefined;
|
||||
};
|
||||
|
||||
LoadingImage.prototype.confirm = function( isLoaded, message ) {
|
||||
this.isLoaded = isLoaded;
|
||||
this.emitEvent( 'progress', [ this, this.img, message ] );
|
||||
};
|
||||
|
||||
// ----- events ----- //
|
||||
|
||||
// trigger specified handler for event type
|
||||
LoadingImage.prototype.handleEvent = function( event ) {
|
||||
var method = 'on' + event.type;
|
||||
if ( this[ method ] ) {
|
||||
this[ method ]( event );
|
||||
}
|
||||
};
|
||||
|
||||
LoadingImage.prototype.onload = function() {
|
||||
this.confirm( true, 'onload' );
|
||||
this.unbindEvents();
|
||||
};
|
||||
|
||||
LoadingImage.prototype.onerror = function() {
|
||||
this.confirm( false, 'onerror' );
|
||||
this.unbindEvents();
|
||||
};
|
||||
|
||||
LoadingImage.prototype.unbindEvents = function() {
|
||||
this.proxyImage.removeEventListener( 'load', this );
|
||||
this.proxyImage.removeEventListener( 'error', this );
|
||||
this.img.removeEventListener( 'load', this );
|
||||
this.img.removeEventListener( 'error', this );
|
||||
};
|
||||
|
||||
// -------------------------- Background -------------------------- //
|
||||
|
||||
function Background( url, element ) {
|
||||
this.url = url;
|
||||
this.element = element;
|
||||
this.img = new Image();
|
||||
}
|
||||
|
||||
// inherit LoadingImage prototype
|
||||
Background.prototype = Object.create( LoadingImage.prototype );
|
||||
|
||||
Background.prototype.check = function() {
|
||||
this.img.addEventListener( 'load', this );
|
||||
this.img.addEventListener( 'error', this );
|
||||
this.img.src = this.url;
|
||||
// check if image is already complete
|
||||
var isComplete = this.getIsImageComplete();
|
||||
if ( isComplete ) {
|
||||
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
|
||||
this.unbindEvents();
|
||||
}
|
||||
};
|
||||
|
||||
Background.prototype.unbindEvents = function() {
|
||||
this.img.removeEventListener( 'load', this );
|
||||
this.img.removeEventListener( 'error', this );
|
||||
};
|
||||
|
||||
Background.prototype.confirm = function( isLoaded, message ) {
|
||||
this.isLoaded = isLoaded;
|
||||
this.emitEvent( 'progress', [ this, this.element, message ] );
|
||||
};
|
||||
|
||||
// -------------------------- jQuery -------------------------- //
|
||||
|
||||
ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
|
||||
jQuery = jQuery || window.jQuery;
|
||||
if ( !jQuery ) {
|
||||
return;
|
||||
}
|
||||
// set local variable
|
||||
$ = jQuery;
|
||||
// $().imagesLoaded()
|
||||
$.fn.imagesLoaded = function( options, callback ) {
|
||||
var instance = new ImagesLoaded( this, options, callback );
|
||||
return instance.jqDeferred.promise( $(this) );
|
||||
};
|
||||
};
|
||||
// try making plugin
|
||||
ImagesLoaded.makeJQueryPlugin();
|
||||
|
||||
// -------------------------- -------------------------- //
|
||||
|
||||
return ImagesLoaded;
|
||||
|
||||
});
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/*!
|
||||
* imagesLoaded PACKAGED v4.1.0
|
||||
* JavaScript is all like "You images are done yet or what?"
|
||||
* MIT License
|
||||
*/
|
||||
|
||||
!function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||[];return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i];return t}function n(t){var e=[];if(Array.isArray(t))e=t;else if("number"==typeof t.length)for(var i=0;i<t.length;i++)e.push(t[i]);else e.push(t);return e}function o(t,e,r){return this instanceof o?("string"==typeof t&&(t=document.querySelectorAll(t)),this.elements=n(t),this.options=i({},this.options),"function"==typeof e?r=e:i(this.options,e),r&&this.on("always",r),this.getImages(),h&&(this.jqDeferred=new h.Deferred),void setTimeout(function(){this.check()}.bind(this))):new o(t,e,r)}function r(t){this.img=t}function s(t,e){this.url=t,this.element=e,this.img=new Image}var h=t.jQuery,a=t.console;o.prototype=Object.create(e.prototype),o.prototype.options={},o.prototype.getImages=function(){this.images=[],this.elements.forEach(this.addElementImages,this)},o.prototype.addElementImages=function(t){"IMG"==t.nodeName&&this.addImage(t),this.options.background===!0&&this.addElementBackgroundImages(t);var e=t.nodeType;if(e&&d[e]){for(var i=t.querySelectorAll("img"),n=0;n<i.length;n++){var o=i[n];this.addImage(o)}if("string"==typeof this.options.background){var r=t.querySelectorAll(this.options.background);for(n=0;n<r.length;n++){var s=r[n];this.addElementBackgroundImages(s)}}}};var d={1:!0,9:!0,11:!0};return o.prototype.addElementBackgroundImages=function(t){var e=getComputedStyle(t);if(e)for(var i=/url\((['"])?(.*?)\1\)/gi,n=i.exec(e.backgroundImage);null!==n;){var o=n&&n[2];o&&this.addBackground(o,t),n=i.exec(e.backgroundImage)}},o.prototype.addImage=function(t){var e=new r(t);this.images.push(e)},o.prototype.addBackground=function(t,e){var i=new s(t,e);this.images.push(i)},o.prototype.check=function(){function t(t,i,n){setTimeout(function(){e.progress(t,i,n)})}var e=this;return this.progressedCount=0,this.hasAnyBroken=!1,this.images.length?void this.images.forEach(function(e){e.once("progress",t),e.check()}):void this.complete()},o.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount==this.images.length&&this.complete(),this.options.debug&&a&&a.log("progress: "+i,t,e)},o.prototype.complete=function(){var t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){var e=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[e](this)}},r.prototype=Object.create(e.prototype),r.prototype.check=function(){var t=this.getIsImageComplete();return t?void this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),void(this.proxyImage.src=this.img.src))},r.prototype.getIsImageComplete=function(){return this.img.complete&&void 0!==this.img.naturalWidth},r.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.img,e])},r.prototype.handleEvent=function(t){var e="on"+t.type;this[e]&&this[e](t)},r.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},r.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},r.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},s.prototype=Object.create(r.prototype),s.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url;var t=this.getIsImageComplete();t&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},s.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListeLine truncated
|
||||
@@ -1,5 +0,0 @@
|
||||
/* qTip2 v2.2.1 | Plugins: tips viewport | Styles: core | qtip2.com | Licensed MIT | Wed Aug 12 2015 16:16:41 */
|
||||
|
||||
!function(a,b,c){!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):jQuery&&!jQuery.fn.qtip&&a(jQuery)}(function(d){"use strict";function e(a,b,c,e){this.id=c,this.target=a,this.tooltip=D,this.elements={target:a},this._id=Q+"-"+c,this.timers={img:{}},this.options=b,this.plugins={},this.cache={event:{},target:d(),disabled:C,attr:e,onTooltip:C,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=C}function f(a){return a===D||"object"!==d.type(a)}function g(a){return!(d.isFunction(a)||a&&a.attr||a.length||"object"===d.type(a)&&(a.jquery||a.then))}function h(a){var b,c,e,h;return f(a)?C:(f(a.metadata)&&(a.metadata={type:a.metadata}),"content"in a&&(b=a.content,f(b)||b.jquery||b.done?b=a.content={text:c=g(b)?C:b}:c=b.text,"ajax"in b&&(e=b.ajax,h=e&&e.once!==C,delete b.ajax,b.text=function(a,b){var f=c||d(this).attr(b.options.content.attr)||"Loading...",g=d.ajax(d.extend({},e,{context:b})).then(e.success,D,e.error).then(function(a){return a&&h&&b.set("content.text",a),a},function(a,c,d){b.destroyed||0===a.status||b.set("content.text",c+": "+d)});return h?f:(b.set("content.text",f),g)}),"title"in b&&(d.isPlainObject(b.title)&&(b.button=b.title.button,b.title=b.title.text),g(b.title||C)&&(b.title=C))),"position"in a&&f(a.position)&&(a.position={my:a.position,at:a.position}),"show"in a&&f(a.show)&&(a.show=a.show.jquery?{target:a.show}:a.show===B?{ready:B}:{event:a.show}),"hide"in a&&f(a.hide)&&(a.hide=a.hide.jquery?{target:a.hide}:{event:a.hide}),"style"in a&&f(a.style)&&(a.style={classes:a.style}),d.each(P,function(){this.sanitize&&this.sanitize(a)}),a)}function i(a,b){for(var c,d=0,e=a,f=b.split(".");e=e[f[d++]];)d<f.length&&(c=e);return[c||a,f.pop()]}function j(a,b){var c,d,e;for(c in this.checks)for(d in this.checks[c])(e=new RegExp(d,"i").exec(a))&&(b.push(e),("builtin"===c||this.plugins[c])&&this.checks[c][d].apply(this.plugins[c]||this,b))}function k(a){return T.concat("").join(a?"-"+a+" ":" ")}function l(a,b){return b>0?setTimeout(d.proxy(a,this),b):void a.call(this)}function m(a){this.tooltip.hasClass($)||(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=l.call(this,function(){this.toggle(B,a)},this.options.show.delay))}function n(a){if(!this.tooltip.hasClass($)&&!this.destroyed){var b=d(a.relatedTarget),c=b.closest(U)[0]===this.tooltip[0],e=b[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==b[0]&&"mouse"===this.options.position.target&&c||this.options.hide.fixed&&/mouse(out|leave|move)/.test(a.type)&&(c||e))try{a.preventDefault(),a.stopImmediatePropagation()}catch(f){}else this.timers.hide=l.call(this,function(){this.toggle(C,a)},this.options.hide.delay,this)}}function o(a){!this.tooltip.hasClass($)&&this.options.hide.inactive&&(clearTimeout(this.timers.inactive),this.timers.inactive=l.call(this,function(){this.hide(a)},this.options.hide.inactive))}function p(a){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(a)}function q(a,c,e){d(b.body).delegate(a,(c.split?c:c.join("."+Q+" "))+"."+Q,function(){var a=w.api[d.attr(this,S)];a&&!a.disabled&&e.apply(a,arguments)})}function r(a,c,f){var g,i,j,k,l,m=d(b.body),n=a[0]===b?m:a,o=a.metadata?a.metadata(f.metadata):D,p="html5"===f.metadata.type&&o?o[f.metadata.name]:D,q=a.data(f.metadata.name||"qtipopts");try{q="string"==typeof q?d.parseJSON(q):q}catch(r){}if(k=d.extend(B,{},w.defaults,f,"object"==typeof q?h(q):D,h(p||o)),i=k.position,k.id=c,"boolean"==typeof k.content.text){if(j=a.attr(k.content.attr),k.content.attr===C||!j)return C;k.content.text=j}if(i.container.length||(i.container=m),i.target===C&&(i.target=n),k.show.target===C&&(k.show.target=n),k.show.solo===B&&(k.show.solo=i.container.closest("body")),k.hide.target===C&&(k.hide.target=n),k.position.viewport===B&&(k.position.viewport=i.container),i.container=i.container.eq(0),i.at=new y(i.at,B),i.my=new y(i.my),a.data(Q))if(k.overwrite)a.qtip("destroy",!0);else if(k.overwrite===C)return C;return a.attr(R,c),k.suppress&&(l=a.attr("title"))&&a.removeAttr("title").attr(ab,l).attr("title",""),g=new e(a,k,c,!!j),a.data(Q,g),g}function s(a){return a.charAt(0).toUpperCase()+a.slice(1)}function t(a,b){var d,e,f=b.charAt(0).toUpperCase()+b.slice(1),g=(b+" "+pb.join(f+" ")+f).split(" "),h=0;if(ob[b])return a.css(ob[b]);for(;d=g[h++];)if((e=a.css(d))!==c)return ob[b]=d,e}function u(a,b){return Math.ceil(parseFloat(t(a,b)))}function v(a,b){this._ns="tip",this.options=b,this.offset=b.offset,this.size=[b.width,b.height],this.init(this.qtip=a)}var w,x,y,z,A,B=!0,C=!1,D=null,E="x",F="y",G="width",H="height",I="top",J="left",K="bottom",L="right",M="center",N="flipinvert",O="shift",P={},Q="qtip",R="data-hasqtip",S="data-qtip-id",T=["ui-widget","ui-tooltip"],U="."+Q,V="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),W=Q+"-fixed",X=Q+"-default",Y=Q+"-focus",Z=Q+"-hover",$=Q+"-disabled",_="_replaceLine truncated
|
||||
}),j[a[c]]-=b[c===E?0:1],h.css({margin:"",top:"",bottom:"",left:"",right:""}).css(j),j},reposition:function(a,b,d){function e(a,b,c,d,e){a===O&&j.precedance===b&&k[d]&&j[c]!==M?j.precedance=j.precedance===E?F:E:a!==O&&k[d]&&(j[b]=j[b]===M?k[d]>0?d:e:j[b]===d?e:d)}function f(a,b,e){j[a]===M?p[gb+"-"+b]=o[a]=g[gb+"-"+b]-k[b]:(h=g[e]!==c?[k[b],-g[b]]:[-k[b],g[b]],(o[a]=Math.max(h[0],h[1]))>h[0]&&(d[b]-=k[b],o[b]=C),p[g[e]!==c?e:b]=o[a])}if(this.enabled){var g,h,i=b.cache,j=this.corner.clone(),k=d.adjusted,l=b.options.position.adjust.method.split(" "),m=l[0],n=l[1]||l[0],o={left:C,top:C,x:0,y:0},p={};this.corner.fixed!==B&&(e(m,E,F,J,L),e(n,F,E,I,K),(j.string()!==i.corner.string()||i.cornerTop!==k.top||i.cornerLeft!==k.left)&&this.update(j,C)),g=this.calculate(j),g.right!==c&&(g.left=-g.right),g.bottom!==c&&(g.top=-g.bottom),g.user=this.offset,(o.left=m===O&&!!k.left)&&f(E,J,L),(o.top=n===O&&!!k.top)&&f(F,I,K),this.element.css(p).toggle(!(o.x&&o.y||j.x===M&&o.y||j.y===M&&o.x)),d.left-=g.left.charAt?g.user:m!==O||o.top||!o.left&&!o.top?g.left+this.border:0,d.top-=g.top.charAt?g.user:n!==O||o.left||!o.left&&!o.top?g.top+this.border:0,i.cornerLeft=k.left,i.cornerTop=k.top,i.corner=j.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),fb=P.tip=function(a){return new v(a,a.options.style.tip)},fb.initialize="render",fb.sanitize=function(a){if(a.style&&"tip"in a.style){var b=a.style.tip;"object"!=typeof b&&(b=a.style.tip={corner:b}),/string|boolean/i.test(typeof b.corner)||(b.corner=B)}},z.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(a){this.size=[a.width,a.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},d.extend(B,w.defaults,{style:{tip:{corner:B,mimic:C,width:6,height:6,border:B,offset:0}}}),P.viewport=function(c,d,e,f,g,h,i){function j(a,b,c,e,f,g,h,i,j){var k=d[f],s=u[a],t=v[a],w=c===O,x=s===f?j:s===g?-j:-j/2,y=t===f?i:t===g?-i:-i/2,z=q[f]+r[f]-(n?0:m[f]),A=z-k,B=k+j-(h===G?o:p)-z,C=x-(u.precedance===a||s===u[b]?y:0)-(t===M?i/2:0);return w?(C=(s===f?1:-1)*x,d[f]+=A>0?A:B>0?-B:0,d[f]=Math.max(-m[f]+r[f],k-C,Math.min(Math.max(-m[f]+r[f]+(h===G?o:p),k+C),d[f],"center"===s?k-x:1e9))):(e*=c===N?2:0,A>0&&(s!==f||B>0)?(d[f]-=C+e,l.invert(a,f)):B>0&&(s!==g||A>0)&&(d[f]-=(s===M?-C:C)+e,l.invert(a,g)),d[f]<q&&-d[f]>B&&(d[f]=k,l=u.clone())),d[f]-k}var k,l,m,n,o,p,q,r,s=e.target,t=c.elements.tooltip,u=e.my,v=e.at,w=e.adjust,x=w.method.split(" "),y=x[0],z=x[1]||x[0],A=e.viewport,B=e.container,D=(c.cache,{left:0,top:0});return A.jquery&&s[0]!==a&&s[0]!==b.body&&"none"!==w.method?(m=B.offset()||D,n="static"===B.css("position"),k="fixed"===t.css("position"),o=A[0]===a?A.width():A.outerWidth(C),p=A[0]===a?A.height():A.outerHeight(C),q={left:k?0:A.scrollLeft(),top:k?0:A.scrollTop()},r=A.offset()||D,("shift"!==y||"shift"!==z)&&(l=u.clone()),D={left:"none"!==y?j(E,F,y,w.x,J,L,G,f,h):0,top:"none"!==z?j(F,E,z,w.y,I,K,H,g,i):0,my:l}):D}})}(window,document);
|
||||
//# sourceMappingURL=jquery.qtip.min.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"jquery.qtip.min.js","sources":["jquery.qtip.js"],"names":["window","document","undefined","factory","define","amd","jQuery","fn","qtip","$","QTip","target","options","id","attr","this","tooltip","NULL","elements","_id","NAMESPACE","timers","img","plugins","cache","event","disabled","FALSE","onTooltip","lastClass","rendered","destroyed","waiting","hiddenDuringWait","positioning","triggering","invalidOpt","a","type","invalidContent","c","isFunction","length","jquery","then","sanitizeOptions","opts","content","text","ajax","once","metadata","done","api","loading","deferred","extend","context","success","error","set","xhr","status","isPlainObject","title","button","position","my","at","show","TRUE","ready","hide","style","classes","each","PLUGINS","sanitize","convertNotation","notation","obj","i","option","levels","split","pop","setCallback","args","category","rule","match","checks","RegExp","exec","push","apply","createWidgetClass","cls","WIDGET","concat","join","delay","callback","duration","setTimeout","proxy","call","showMethod","hasClass","CLASS_DISABLED","clearTimeout","toggle","hideMethod","relatedTarget","ontoTooltip","closest","SELECTOR","ontoTarget","fixed","test","preventDefault","stopImmediatePropagation","e","inactiveMethod","inactive","repositionMethod","offsetWidth","reposition","delegate","selector","events","method","body","QTIP","ATTR_ID","arguments","init","elem","posOptions","config","docBody","newTarget","metadata5","name","html5","data","parseJSON","defaults","container","solo","viewport","eq","CORNER","overwrite","ATTR_HAS","suppress","removeAttr","oldtitle","camel","s","charAt","toUpperCase","slice","vendorCss","prop","cur","val","ucProp","props","cssPrefixes","cssProps","css","intCss","Math","ceil","parseFloat","Tip","_ns","offset","size","width","height","Modal","Ie6","PROTOTYPE","CHECKS","trackingBound","X","Y","WIDTH","HEIGHT","TOP","LEFT","BOTTOM","RIGHT","CENTER","FLIPINVERT","SHIFT","INACTIVE_EVENTS","CLASS_FIXED","CLASS_DEFAULT","CLASS_FOCUS","CLASS_HOVER","replaceSuffix","BROWSER","ie","v","createElement","innerHTML","getElementsByTagName","NaN","iOS","navigator","userAgent","replace","prototype","_when","deferreds","when","render","self","posClass","_createPosClass","class","tracking","adjust","mouse","role","aria-live","aria-atomic","aria-describedby","aria-hidden","toggleClass","appendTo","append","_createTitle","_updateTitle","_createButton","_updateContent","_setWidget","instance","initialize","_unassignEvents","_assignEvents","_trigger","destroy","immediate","process","timer","stop","find","remove","end","removeData","one","builtin","^id$","o","prev","nextid","new_id","^prerender","^content.text$","^content.attr$","^content.title$","_removeTitle","^content.button$","_updateButton","^content.title.(text|button)$","^position.(my|at)$","^position.container$","^show.ready$","^style.classes$","p","removeClass","addClass","^style.(width|height)","^style.widget|content.title","^style.def","^events.(render|show|move|hide|focus|blur)$","^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)","get","toLowerCase","result","precedance","string","rmove","rrender","value","previous","nodeType","_update","element","empty","display","visibility","html","_waitForContent","images","imagesLoaded","Deferred","resolve","promise","titlebar","widget","insertBefore","substr","abbrev","effect","pluginCalculations","adjusted","newClass","tooltipWidth","outerWidth","tooltipHeight","outerHeight","targetWidth","targetHeight","left","top","visible","isScroll","win","doc","ownerDocument","isArray","x","y","distance","origin","pageX","innerWidth","documentElement","clientWidth","pageY","scrollX","scrollLeft","scrollY","scrollTop","innerHeight","imagemap","is","svg","ownerSVGElement","adjustable","isNaN","queue","next","opacity","removeAttribute","pos","scroll","scrolled","parentOffset","overflow","quirks","compatMode","parent","getBoundingClientRect","offsetParent","C","Corner","corner","forceY","f","invert","z","center","clone","state","add","has","fix","identicalState","allow","after","contentOptions","animate","sameTarget","search","focus","bind","_storeMouse","not","Event","unbind","blur","autofocus","trigger","n","fadeTo","qtips","curIndex","parseInt","zIndex","newIndex","zindex","filter","disable","enable","isString","close","aria-label","prepend","click","on","def","_bind","targets","suffix","ns","_unbind","originalEvent","isDefaultPrevented","_bindEvents","showEvents","hideEvents","showTargets","hideTargets","similarTargets","toggleEvents","showIndex","inArray","splice","_assignInitialEvents","hoverIntent","prerender","showTarget","hideTarget","trim","onTarget","containerTarget","viewportTarget","documentTarget","windowTarget","leave","nodeName","indexOf","enabled","isAncestor","parents","inactiveEvents","limit","abs","resize","special","grep","toArray","currentTarget","newValue","command","returned","makeArray","timeStamp","keepData","elems","funLine truncated
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* TipTip
|
||||
* Copyright 2010 Drew Wilson
|
||||
* www.drewwilson.com
|
||||
* code.drewwilson.com/entry/tiptip-jquery-plugin
|
||||
*
|
||||
* Version 1.3 - Updated: Mar. 23, 2010
|
||||
*
|
||||
* This Plug-In will create a custom tooltip to replace the default
|
||||
* browser tooltip. It is extremely lightweight and very smart in
|
||||
* that it detects the edges of the browser window and will make sure
|
||||
* the tooltip stays within the current window size. As a result the
|
||||
* tooltip will adjust itself to be displayed above, below, to the left
|
||||
* or to the right depending on what is necessary to stay within the
|
||||
* browser window. It is completely customizable as well via CSS.
|
||||
*
|
||||
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
|
||||
(function($){
|
||||
$.fn.tipTip = function(options) {
|
||||
var defaults = {
|
||||
activation: "hover",
|
||||
keepAlive: false,
|
||||
maxWidth: "200px",
|
||||
edgeOffset: 3,
|
||||
defaultPosition: "bottom",
|
||||
delay: 400,
|
||||
fadeIn: 200,
|
||||
fadeOut: 200,
|
||||
attribute: "title",
|
||||
content: false, // HTML or String to fill TipTIp with
|
||||
enter: function(){},
|
||||
exit: function(){}
|
||||
};
|
||||
var opts = $.extend(defaults, options);
|
||||
|
||||
// Setup tip tip elements and render them to the DOM
|
||||
if($("#tiptip_holder").length <= 0){
|
||||
var tiptip_holder = $('<div id="tiptip_holder" style="max-width:'+ opts.maxWidth +';"></div>');
|
||||
var tiptip_content = $('<div id="tiptip_content"></div>');
|
||||
var tiptip_arrow = $('<div id="tiptip_arrow"></div>');
|
||||
$("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')));
|
||||
} else {
|
||||
var tiptip_holder = $("#tiptip_holder");
|
||||
var tiptip_content = $("#tiptip_content");
|
||||
var tiptip_arrow = $("#tiptip_arrow");
|
||||
}
|
||||
|
||||
return this.each(function(){
|
||||
var org_elem = $(this);
|
||||
if(opts.content){
|
||||
var org_title = opts.content;
|
||||
} else {
|
||||
var org_title = org_elem.attr(opts.attribute);
|
||||
}
|
||||
if(org_title != ""){
|
||||
if(!opts.content){
|
||||
org_elem.removeAttr(opts.attribute); //remove original Attribute
|
||||
}
|
||||
var timeout = false;
|
||||
|
||||
if(opts.activation == "hover"){
|
||||
org_elem.hover(function(){
|
||||
active_tiptip();
|
||||
}, function(){
|
||||
if(!opts.keepAlive){
|
||||
deactive_tiptip();
|
||||
}
|
||||
});
|
||||
if(opts.keepAlive){
|
||||
tiptip_holder.hover(function(){}, function(){
|
||||
deactive_tiptip();
|
||||
});
|
||||
}
|
||||
} else if(opts.activation == "focus"){
|
||||
org_elem.focus(function(){
|
||||
active_tiptip();
|
||||
}).blur(function(){
|
||||
deactive_tiptip();
|
||||
});
|
||||
} else if(opts.activation == "click"){
|
||||
org_elem.click(function(){
|
||||
active_tiptip();
|
||||
return false;
|
||||
}).hover(function(){},function(){
|
||||
if(!opts.keepAlive){
|
||||
deactive_tiptip();
|
||||
}
|
||||
});
|
||||
if(opts.keepAlive){
|
||||
tiptip_holder.hover(function(){}, function(){
|
||||
deactive_tiptip();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function active_tiptip(){
|
||||
opts.enter.call(this);
|
||||
tiptip_content.html(org_title);
|
||||
tiptip_holder.hide().removeAttr("class").css("margin","0");
|
||||
tiptip_arrow.removeAttr("style");
|
||||
|
||||
var top = parseInt(org_elem.offset()['top']);
|
||||
var left = parseInt(org_elem.offset()['left']);
|
||||
var org_width = parseInt(org_elem.outerWidth());
|
||||
var org_height = parseInt(org_elem.outerHeight());
|
||||
var tip_w = tiptip_holder.outerWidth();
|
||||
var tip_h = tiptip_holder.outerHeight();
|
||||
var w_compare = Math.round((org_width - tip_w) / 2);
|
||||
var h_compare = Math.round((org_height - tip_h) / 2);
|
||||
var marg_left = Math.round(left + w_compare);
|
||||
var marg_top = Math.round(top + org_height + opts.edgeOffset);
|
||||
var t_class = "";
|
||||
var arrow_top = "";
|
||||
var arrow_left = Math.round(tip_w - 12) / 2;
|
||||
|
||||
if(opts.defaultPosition == "bottom"){
|
||||
t_class = "_bottom";
|
||||
} else if(opts.defaultPosition == "top"){
|
||||
t_class = "_top";
|
||||
} else if(opts.defaultPosition == "left"){
|
||||
t_class = "_left";
|
||||
} else if(opts.defaultPosition == "right"){
|
||||
t_class = "_right";
|
||||
}
|
||||
|
||||
var right_compare = (w_compare + left) < parseInt($(window).scrollLeft());
|
||||
var left_compare = (tip_w + left) > parseInt($(window).width());
|
||||
|
||||
if((right_compare && w_compare < 0) || (t_class == "_right" && !left_compare) || (t_class == "_left" && left < (tip_w + opts.edgeOffset + 5))){
|
||||
t_class = "_right";
|
||||
arrow_top = Math.round(tip_h - 13) / 2;
|
||||
arrow_left = -12;
|
||||
marg_left = Math.round(left + org_width + opts.edgeOffset);
|
||||
marg_top = Math.round(top + h_compare);
|
||||
} else if((left_compare && w_compare < 0) || (t_class == "_left" && !right_compare)){
|
||||
t_class = "_left";
|
||||
arrow_top = Math.round(tip_h - 13) / 2;
|
||||
arrow_left = Math.round(tip_w);
|
||||
marg_left = Math.round(left - (tip_w + opts.edgeOffset + 5));
|
||||
marg_top = Math.round(top + h_compare);
|
||||
}
|
||||
|
||||
var top_compare = (top + org_height + opts.edgeOffset + tip_h + 8) > parseInt($(window).height() + $(window).scrollTop());
|
||||
var bottom_compare = ((top + org_height) - (opts.edgeOffset + tip_h + 8)) < 0;
|
||||
|
||||
if(top_compare || (t_class == "_bottom" && top_compare) || (t_class == "_top" && !bottom_compare)){
|
||||
if(t_class == "_top" || t_class == "_bottom"){
|
||||
t_class = "_top";
|
||||
} else {
|
||||
t_class = t_class+"_top";
|
||||
}
|
||||
arrow_top = tip_h;
|
||||
marg_top = Math.round(top - (tip_h + 5 + opts.edgeOffset));
|
||||
} else if(bottom_compare | (t_class == "_top" && bottom_compare) || (t_class == "_bottom" && !top_compare)){
|
||||
if(t_class == "_top" || t_class == "_bottom"){
|
||||
t_class = "_bottom";
|
||||
} else {
|
||||
t_class = t_class+"_bottom";
|
||||
}
|
||||
arrow_top = -12;
|
||||
marg_top = Math.round(top + org_height + opts.edgeOffset);
|
||||
}
|
||||
|
||||
if(t_class == "_right_top" || t_class == "_left_top"){
|
||||
marg_top = marg_top + 5;
|
||||
} else if(t_class == "_right_bottom" || t_class == "_left_bottom"){
|
||||
marg_top = marg_top - 5;
|
||||
}
|
||||
if(t_class == "_left_top" || t_class == "_left_bottom"){
|
||||
marg_left = marg_left + 5;
|
||||
}
|
||||
tiptip_arrow.css({"margin-left": arrow_left+"px", "margin-top": arrow_top+"px"});
|
||||
tiptip_holder.css({"margin-left": marg_left+"px", "margin-top": marg_top+"px"}).attr("class","tip"+t_class);
|
||||
|
||||
if (timeout){ clearTimeout(timeout); }
|
||||
timeout = setTimeout(function(){ tiptip_holder.stop(true,true).fadeIn(opts.fadeIn); }, opts.delay);
|
||||
}
|
||||
|
||||
function deactive_tiptip(){
|
||||
opts.exit.call(this);
|
||||
if (timeout){ clearTimeout(timeout); }
|
||||
tiptip_holder.fadeOut(opts.fadeOut);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
@@ -1,21 +0,0 @@
|
||||
/*
|
||||
* TipTip
|
||||
* Copyright 2010 Drew Wilson
|
||||
* www.drewwilson.com
|
||||
* code.drewwilson.com/entry/tiptip-jquery-plugin
|
||||
*
|
||||
* Version 1.3 - Updated: Mar. 23, 2010
|
||||
*
|
||||
* This Plug-In will create a custom tooltip to replace the default
|
||||
* browser tooltip. It is extremely lightweight and very smart in
|
||||
* that it detects the edges of the browser window and will make sure
|
||||
* the tooltip stays within the current window size. As a result the
|
||||
* tooltip will adjust itself to be displayed above, below, to the left
|
||||
* or to the right depending on what is necessary to stay within the
|
||||
* browser window. It is completely customizable as well via CSS.
|
||||
*
|
||||
* This TipTip jQuery plug-in is dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*/
|
||||
(function($){$.fn.tipTip=function(options){var defaults={activation:"hover",keepAlive:false,maxWidth:"200px",edgeOffset:3,defaultPosition:"bottom",delay:400,fadeIn:200,fadeOut:200,attribute:"title",content:false,enter:function(){},exit:function(){}};var opts=$.extend(defaults,options);if($("#tiptip_holder").length<=0){var tiptip_holder=$('<div id="tiptip_holder" style="max-width:'+opts.maxWidth+';"></div>');var tiptip_content=$('<div id="tiptip_content"></div>');var tiptip_arrow=$('<div id="tiptip_arrow"></div>');$("body").append(tiptip_holder.html(tiptip_content).prepend(tiptip_arrow.html('<div id="tiptip_arrow_inner"></div>')))}else{var tiptip_holder=$("#tiptip_holder");var tiptip_content=$("#tiptip_content");var tiptip_arrow=$("#tiptip_arrow")}return this.each(function(){var org_elem=$(this);if(opts.content){var org_title=opts.content}else{var org_title=org_elem.attr(opts.attribute)}if(org_title!=""){if(!opts.content){org_elem.removeAttr(opts.attribute)}var timeout=false;if(opts.activation=="hover"){org_elem.hover(function(){active_tiptip()},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}else if(opts.activation=="focus"){org_elem.focus(function(){active_tiptip()}).blur(function(){deactive_tiptip()})}else if(opts.activation=="click"){org_elem.click(function(){active_tiptip();return false}).hover(function(){},function(){if(!opts.keepAlive){deactive_tiptip()}});if(opts.keepAlive){tiptip_holder.hover(function(){},function(){deactive_tiptip()})}}function active_tiptip(){opts.enter.call(this);tiptip_content.html(org_title);tiptip_holder.hide().removeAttr("class").css("margin","0");tiptip_arrow.removeAttr("style");var top=parseInt(org_elem.offset()['top']);var left=parseInt(org_elem.offset()['left']);var org_width=parseInt(org_elem.outerWidth());var org_height=parseInt(org_elem.outerHeight());var tip_w=tiptip_holder.outerWidth();var tip_h=tiptip_holder.outerHeight();var w_compare=Math.round((org_width-tip_w)/2);var h_compare=Math.round((org_height-tip_h)/2);var marg_left=Math.round(left+w_compare);var marg_top=Math.round(top+org_height+opts.edgeOffset);var t_class="";var arrow_top="";var arrow_left=Math.round(tip_w-12)/2;if(opts.defaultPosition=="bottom"){t_class="_bottom"}else if(opts.defaultPosition=="top"){t_class="_top"}else if(opts.defaultPosition=="left"){t_class="_left"}else if(opts.defaultPosition=="right"){t_class="_right"}var right_compare=(w_compare+left)<parseInt($(window).scrollLeft());var left_compare=(tip_w+left)>parseInt($(window).width());if((right_compare&&w_compare<0)||(t_class=="_right"&&!left_compare)||(t_class=="_left"&&left<(tip_w+opts.edgeOffset+5))){t_class="_right";arrow_top=Math.round(tip_h-13)/2;arrow_left=-12;marg_left=Math.round(left+org_width+opts.edgeOffset);marg_top=Math.round(top+h_compare)}else if((left_compare&&w_compare<0)||(t_class=="_left"&&!right_compare)){t_class="_left";arrow_top=Math.round(tip_h-13)/2;arrow_left=Math.round(tip_w);marg_left=Math.round(left-(tip_w+opts.edgeOffset+5));marg_top=Math.round(top+h_compare)}var top_compare=(top+org_height+opts.edgeOffset+tip_h+8)>parseInt($(window).height()+$(window).scrollTop());var bottom_compare=((top+org_height)-(opts.edgeOffset+tip_h+8))<0;if(top_compare||(t_class=="_bottom"&&top_compare)||(t_class=="_top"&&!bottom_compare)){if(t_class=="_top"||t_class=="_bottom"){t_class="_top"}else{t_class=t_class+"_top"}arrow_top=tip_h;marg_top=Math.round(top-(tip_h+5+opts.edgeOffset))}else if(bottom_compare|(t_class=="_top"&&bottom_compare)||(t_class=="_bottom"&&!top_compare)){if(t_class=="_top"||t_class=="_bottom"){t_class="_bottom"}else{t_class=t_class+"_bottom"}arrow_top=-12;marg_top=Math.round(top+org_height+opts.edgeOffset)}if(t_class=="_right_top"||t_class=="_left_top"){marg_top=marg_top+5}else if(t_class=="_right_bottom"||t_class=="_left_bottom"){marg_top=marg_top-5}if(t_class=="_left_top"||t_class=="_left_bottom"){marg_left=marg_left+5}tiptip_arrow.css({"margin-left":arrow_left+"px","margin-top":arrow_top+"px"});tiptip_holder.css({"margin-left":marg_left+"px","margin-top":marg_top+"px"}).attr("class","tip"+t_class);if(timeout){clearTimeout(timeout)}timeout=setTimeout(function(){tiptip_holder.stop(true,true).fadeIn(opts.fadeIn)},opts.delay)}function deactive_tiptip(){opts.exit.call(this);if(timeout){clearTimeout(timeout)}tiptip_holder.fadeOut(opts.fadeOut)}}})}})(jQuery);
|
||||
@@ -1,7 +0,0 @@
|
||||
//! moment-timezone.js
|
||||
//! version : 0.5.4
|
||||
//! author : Tim Wood
|
||||
//! license : MIT
|
||||
//! github.com/moment/moment-timezone
|
||||
!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["moment"],b):"object"==typeof module&&module.exports?module.exports=b(require("moment")):b(a.moment)}(this,function(a){"use strict";function b(a){return a>96?a-87:a>64?a-29:a-48}function c(a){var c,d=0,e=a.split("."),f=e[0],g=e[1]||"",h=1,i=0,j=1;for(45===a.charCodeAt(0)&&(d=1,j=-1),d;d<f.length;d++)c=b(f.charCodeAt(d)),i=60*i+c;for(d=0;d<g.length;d++)h/=60,c=b(g.charCodeAt(d)),i+=c*h;return i*j}function d(a){for(var b=0;b<a.length;b++)a[b]=c(a[b])}function e(a,b){for(var c=0;b>c;c++)a[c]=Math.round((a[c-1]||0)+6e4*a[c]);a[b-1]=1/0}function f(a,b){var c,d=[];for(c=0;c<b.length;c++)d[c]=a[b[c]];return d}function g(a){var b=a.split("|"),c=b[2].split(" "),g=b[3].split(""),h=b[4].split(" ");return d(c),d(g),d(h),e(h,g.length),{name:b[0],abbrs:f(b[1].split(" "),g),offsets:f(c,g),untils:h,population:0|b[5]}}function h(a){a&&this._set(g(a))}function i(a){var b=a.toTimeString(),c=b.match(/\([a-z ]+\)/i);c&&c[0]?(c=c[0].match(/[A-Z]/g),c=c?c.join(""):void 0):(c=b.match(/[A-Z]{3,5}/g),c=c?c[0]:void 0),"GMT"===c&&(c=void 0),this.at=+a,this.abbr=c,this.offset=a.getTimezoneOffset()}function j(a){this.zone=a,this.offsetScore=0,this.abbrScore=0}function k(a,b){for(var c,d;d=6e4*((b.at-a.at)/12e4|0);)c=new i(new Date(a.at+d)),c.offset===a.offset?a=c:b=c;return a}function l(){var a,b,c,d=(new Date).getFullYear()-2,e=new i(new Date(d,0,1)),f=[e];for(c=1;48>c;c++)b=new i(new Date(d,c,1)),b.offset!==e.offset&&(a=k(e,b),f.push(a),f.push(new i(new Date(a.at+6e4)))),e=b;for(c=0;4>c;c++)f.push(new i(new Date(d+c,0,1))),f.push(new i(new Date(d+c,6,1)));return f}function m(a,b){return a.offsetScore!==b.offsetScore?a.offsetScore-b.offsetScore:a.abbrScore!==b.abbrScore?a.abbrScore-b.abbrScore:b.zone.population-a.zone.population}function n(a,b){var c,e;for(d(b),c=0;c<b.length;c++)e=b[c],I[e]=I[e]||{},I[e][a]=!0}function o(a){var b,c,d,e=a.length,f={},g=[];for(b=0;e>b;b++){d=I[a[b].offset]||{};for(c in d)d.hasOwnProperty(c)&&(f[c]=!0)}for(b in f)f.hasOwnProperty(b)&&g.push(H[b]);return g}function p(){try{var a=Intl.DateTimeFormat().resolvedOptions().timeZone;if(a){var b=H[r(a)];if(b)return b;z("Moment Timezone found "+a+" from the Intl api, but did not have that data loaded.")}}catch(c){}var d,e,f,g=l(),h=g.length,i=o(g),k=[];for(e=0;e<i.length;e++){for(d=new j(t(i[e]),h),f=0;h>f;f++)d.scoreOffsetAt(g[f]);k.push(d)}return k.sort(m),k.length>0?k[0].zone.name:void 0}function q(a){return D&&!a||(D=p()),D}function r(a){return(a||"").toLowerCase().replace(/\//g,"_")}function s(a){var b,c,d,e;for("string"==typeof a&&(a=[a]),b=0;b<a.length;b++)d=a[b].split("|"),c=d[0],e=r(c),F[e]=a[b],H[e]=c,d[5]&&n(e,d[2].split(" "))}function t(a,b){a=r(a);var c,d=F[a];return d instanceof h?d:"string"==typeof d?(d=new h(d),F[a]=d,d):G[a]&&b!==t&&(c=t(G[a],t))?(d=F[a]=new h,d._set(c),d.name=H[a],d):null}function u(){var a,b=[];for(a in H)H.hasOwnProperty(a)&&(F[a]||F[G[a]])&&H[a]&&b.push(H[a]);return b.sort()}function v(a){var b,c,d,e;for("string"==typeof a&&(a=[a]),b=0;b<a.length;b++)c=a[b].split("|"),d=r(c[0]),e=r(c[1]),G[d]=e,H[d]=c[0],G[e]=d,H[e]=c[1]}function w(a){s(a.zones),v(a.links),A.dataVersion=a.version}function x(a){return x.didShowError||(x.didShowError=!0,z("moment.tz.zoneExists('"+a+"') has been deprecated in favor of !moment.tz.zone('"+a+"')")),!!t(a)}function y(a){return!(!a._a||void 0!==a._tzm)}function z(a){"undefined"!=typeof console&&"function"==typeof console.error&&console.error(a)}function A(b){var c=Array.prototype.slice.call(arguments,0,-1),d=arguments[arguments.length-1],e=t(d),f=a.utc.apply(null,c);return e&&!a.isMoment(b)&&y(f)&&f.add(e.parse(f),"minutes"),f.tz(d),f}function B(a){return function(){return this._z?this._z.abbr(this):a.call(this)}}function C(a){return function(){return this._z=null,a.apply(this,arguments)}}if(void 0!==a.tz)return z("Moment Timezone "+a.tz.version+" was already loaded "+(a.tz.dataVersion?"with data from ":"without any data")+a.tz.dataVersion),a;var D,E="0.5.4",F={},G={},H={},I={},J=a.version.split("."),K=+J[0],L=+J[1];(2>K||2===K&&6>L)&&z("Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js "+a.version+". See momentjs.com"),h.prototype={_set:function(a){this.name=a.name,this.abbrs=a.abbrs,this.untils=a.untils,this.offsets=a.offsets,this.population=a.population},_index:function(a){var b,c=+a,d=this.untils;for(b=0;b<d.length;b++)if(c<d[b])return b},parse:function(a){var b,c,d,e,f=+a,g=this.offsets,h=this.untils,i=h.length-1;for(e=0;i>e;e++)if(b=g[e],c=g[e+1],d=g[e?e-1:e],c>b&&A.moveAmbiguousForward?b=c:b>d&&A.moveInvalidForward&&(b=d),f<h[e]-6e4*b)return g[e];return g[i]},abbr:function(a){return this.abbrs[this._index(a)]},offset:function(a){return this.offsets[this._index(a)]}},j.prototype.scoreOffsetAt=function(a){this.offsetScore+=Math.abs(this.zone.offset(a.at)-a.offset),this.zone.abbr(a.at).replace(/[^A-Z]/g,"")!==a.abbr&&this.abbrScore++},A.version=E,A.dataVersion="",A._zones=F,A._links=G,A._names=H,A.add=s,Line truncated
|
||||
links:["Africa/Abidjan|Africa/Bamako","Africa/Abidjan|Africa/Banjul","Africa/Abidjan|Africa/Conakry","Africa/Abidjan|Africa/Dakar","Africa/Abidjan|Africa/Freetown","Africa/Abidjan|Africa/Lome","Africa/Abidjan|Africa/Nouakchott","Africa/Abidjan|Africa/Ouagadougou","Africa/Abidjan|Africa/Sao_Tome","Africa/Abidjan|Africa/Timbuktu","Africa/Abidjan|Atlantic/St_Helena","Africa/Cairo|Egypt","Africa/Johannesburg|Africa/Maseru","Africa/Johannesburg|Africa/Mbabane","Africa/Khartoum|Africa/Juba","Africa/Lagos|Africa/Bangui","Africa/Lagos|Africa/Brazzaville","Africa/Lagos|Africa/Douala","Africa/Lagos|Africa/Kinshasa","Africa/Lagos|Africa/Libreville","Africa/Lagos|Africa/Luanda","Africa/Lagos|Africa/Malabo","Africa/Lagos|Africa/Niamey","Africa/Lagos|Africa/Porto-Novo","Africa/Maputo|Africa/Blantyre","Africa/Maputo|Africa/Bujumbura","Africa/Maputo|Africa/Gaborone","Africa/Maputo|Africa/Harare","Africa/Maputo|Africa/Kigali","Africa/Maputo|Africa/Lubumbashi","Africa/Maputo|Africa/Lusaka","Africa/Nairobi|Africa/Addis_Ababa","Africa/Nairobi|Africa/Asmara","Africa/Nairobi|Africa/Asmera","Africa/Nairobi|Africa/Dar_es_Salaam","Africa/Nairobi|Africa/Djibouti","Africa/Nairobi|Africa/Kampala","Africa/Nairobi|Africa/Mogadishu","Africa/Nairobi|Indian/Antananarivo","Africa/Nairobi|Indian/Comoro","Africa/Nairobi|Indian/Mayotte","Africa/Tripoli|Libya","America/Adak|America/Atka","America/Adak|US/Aleutian","America/Anchorage|US/Alaska","America/Argentina/Buenos_Aires|America/Buenos_Aires","America/Argentina/Catamarca|America/Argentina/ComodRivadavia","America/Argentina/Catamarca|America/Catamarca","America/Argentina/Cordoba|America/Cordoba","America/Argentina/Cordoba|America/Rosario","America/Argentina/Jujuy|America/Jujuy","America/Argentina/Mendoza|America/Mendoza","America/Atikokan|America/Coral_Harbour","America/Chicago|US/Central","America/Curacao|America/Aruba","America/Curacao|America/Kralendijk","America/Curacao|America/Lower_Princes","America/Denver|America/Shiprock","America/Denver|Navajo","America/Denver|US/Mountain","America/Detroit|US/Michigan","America/Edmonton|Canada/Mountain","America/Fort_Wayne|America/Indiana/Indianapolis","America/Fort_Wayne|America/Indianapolis","America/Fort_Wayne|US/East-Indiana","America/Halifax|Canada/Atlantic","America/Havana|Cuba","America/Indiana/Knox|America/Knox_IN","America/Indiana/Knox|US/Indiana-Starke","America/Jamaica|Jamaica","America/Kentucky/Louisville|America/Louisville","America/Los_Angeles|US/Pacific","America/Los_Angeles|US/Pacific-New","America/Manaus|Brazil/West","America/Mazatlan|Mexico/BajaSur","America/Mexico_City|Mexico/General","America/New_York|US/Eastern","America/Noronha|Brazil/DeNoronha","America/Panama|America/Cayman","America/Phoenix|US/Arizona","America/Port_of_Spain|America/Anguilla","America/Port_of_Spain|America/Antigua","America/Port_of_Spain|America/Dominica","America/Port_of_Spain|America/Grenada","America/Port_of_Spain|America/Guadeloupe","America/Port_of_Spain|America/Marigot","America/Port_of_Spain|America/Montserrat","America/Port_of_Spain|America/St_Barthelemy","America/Port_of_Spain|America/St_Kitts","America/Port_of_Spain|America/St_Lucia","America/Port_of_Spain|America/St_Thomas","America/Port_of_Spain|America/St_Vincent","America/Port_of_Spain|America/Tortola","America/Port_of_Spain|America/Virgin","America/Regina|Canada/East-Saskatchewan","America/Regina|Canada/Saskatchewan","America/Rio_Branco|America/Porto_Acre","America/Rio_Branco|Brazil/Acre","America/Santiago|Chile/Continental","America/Sao_Paulo|Brazil/East","America/St_Johns|Canada/Newfoundland","America/Tijuana|America/Ensenada","America/Tijuana|America/Santa_Isabel","America/Tijuana|Mexico/BajaNorte","America/Toronto|America/Montreal","America/Toronto|Canada/Eastern","America/Vancouver|Canada/Pacific","America/Whitehorse|Canada/Yukon","America/Winnipeg|Canada/Central","Asia/Ashgabat|Asia/Ashkhabad","Asia/Bangkok|Asia/Phnom_Penh","Asia/Bangkok|Asia/Vientiane","Asia/Dhaka|Asia/Dacca","Asia/Dubai|Asia/Muscat","Asia/Ho_Chi_Minh|Asia/Saigon","Asia/Hong_Kong|Hongkong","Asia/Jerusalem|Asia/Tel_Aviv","Asia/Jerusalem|Israel","Asia/Kathmandu|Asia/Katmandu","Asia/Kolkata|Asia/Calcutta","Asia/Macau|Asia/Macao","Asia/Makassar|Asia/Ujung_Pandang","Asia/Nicosia|Europe/Nicosia","Asia/Qatar|Asia/Bahrain","Asia/Riyadh|Asia/Aden","Asia/Riyadh|Asia/Kuwait","Asia/Seoul|ROK","Asia/Shanghai|Asia/Chongqing","Asia/Shanghai|Asia/Chungking","Asia/Shanghai|Asia/Harbin","Asia/Shanghai|PRC","Asia/Singapore|Singapore","Asia/Taipei|ROC","Asia/Tehran|Iran","Asia/Thimphu|Asia/Thimbu","Asia/Tokyo|Japan","Asia/Ulaanbaatar|Asia/Ulan_Bator","Asia/Urumqi|Asia/Kashgar","Atlantic/Faroe|Atlantic/Faeroe","Atlantic/Reykjavik|Iceland","Australia/Adelaide|Australia/South","Australia/Brisbane|Australia/Queensland","Australia/Broken_Hill|Australia/Yancowinna","Australia/Darwin|Australia/North","Australia/Hobart|Australia/Tasmania","Australia/Lord_Howe|Australia/LHI","Australia/Melbourne|Australia/Victoria","Australia/Perth|Australia/West"Line truncated
|
||||
@@ -1,601 +0,0 @@
|
||||
//! moment-timezone.js
|
||||
//! version : 0.5.4
|
||||
//! author : Tim Wood
|
||||
//! license : MIT
|
||||
//! github.com/moment/moment-timezone
|
||||
|
||||
(function (root, factory) {
|
||||
"use strict";
|
||||
|
||||
/*global define*/
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['moment'], factory); // AMD
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = factory(require('moment')); // Node
|
||||
} else {
|
||||
factory(root.moment); // Browser
|
||||
}
|
||||
}(this, function (moment) {
|
||||
"use strict";
|
||||
|
||||
// Do not load moment-timezone a second time.
|
||||
if (moment.tz !== undefined) {
|
||||
logError('Moment Timezone ' + moment.tz.version + ' was already loaded ' + (moment.tz.dataVersion ? 'with data from ' : 'without any data') + moment.tz.dataVersion);
|
||||
return moment;
|
||||
}
|
||||
|
||||
var VERSION = "0.5.4",
|
||||
zones = {},
|
||||
links = {},
|
||||
names = {},
|
||||
guesses = {},
|
||||
cachedGuess,
|
||||
|
||||
momentVersion = moment.version.split('.'),
|
||||
major = +momentVersion[0],
|
||||
minor = +momentVersion[1];
|
||||
|
||||
// Moment.js version check
|
||||
if (major < 2 || (major === 2 && minor < 6)) {
|
||||
logError('Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js ' + moment.version + '. See momentjs.com');
|
||||
}
|
||||
|
||||
/************************************
|
||||
Unpacking
|
||||
************************************/
|
||||
|
||||
function charCodeToInt(charCode) {
|
||||
if (charCode > 96) {
|
||||
return charCode - 87;
|
||||
} else if (charCode > 64) {
|
||||
return charCode - 29;
|
||||
}
|
||||
return charCode - 48;
|
||||
}
|
||||
|
||||
function unpackBase60(string) {
|
||||
var i = 0,
|
||||
parts = string.split('.'),
|
||||
whole = parts[0],
|
||||
fractional = parts[1] || '',
|
||||
multiplier = 1,
|
||||
num,
|
||||
out = 0,
|
||||
sign = 1;
|
||||
|
||||
// handle negative numbers
|
||||
if (string.charCodeAt(0) === 45) {
|
||||
i = 1;
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
// handle digits before the decimal
|
||||
for (i; i < whole.length; i++) {
|
||||
num = charCodeToInt(whole.charCodeAt(i));
|
||||
out = 60 * out + num;
|
||||
}
|
||||
|
||||
// handle digits after the decimal
|
||||
for (i = 0; i < fractional.length; i++) {
|
||||
multiplier = multiplier / 60;
|
||||
num = charCodeToInt(fractional.charCodeAt(i));
|
||||
out += num * multiplier;
|
||||
}
|
||||
|
||||
return out * sign;
|
||||
}
|
||||
|
||||
function arrayToInt (array) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
array[i] = unpackBase60(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function intToUntil (array, length) {
|
||||
for (var i = 0; i < length; i++) {
|
||||
array[i] = Math.round((array[i - 1] || 0) + (array[i] * 60000)); // minutes to milliseconds
|
||||
}
|
||||
|
||||
array[length - 1] = Infinity;
|
||||
}
|
||||
|
||||
function mapIndices (source, indices) {
|
||||
var out = [], i;
|
||||
|
||||
for (i = 0; i < indices.length; i++) {
|
||||
out[i] = source[indices[i]];
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function unpack (string) {
|
||||
var data = string.split('|'),
|
||||
offsets = data[2].split(' '),
|
||||
indices = data[3].split(''),
|
||||
untils = data[4].split(' ');
|
||||
|
||||
arrayToInt(offsets);
|
||||
arrayToInt(indices);
|
||||
arrayToInt(untils);
|
||||
|
||||
intToUntil(untils, indices.length);
|
||||
|
||||
return {
|
||||
name : data[0],
|
||||
abbrs : mapIndices(data[1].split(' '), indices),
|
||||
offsets : mapIndices(offsets, indices),
|
||||
untils : untils,
|
||||
population : data[5] | 0
|
||||
};
|
||||
}
|
||||
|
||||
/************************************
|
||||
Zone object
|
||||
************************************/
|
||||
|
||||
function Zone (packedString) {
|
||||
if (packedString) {
|
||||
this._set(unpack(packedString));
|
||||
}
|
||||
}
|
||||
|
||||
Zone.prototype = {
|
||||
_set : function (unpacked) {
|
||||
this.name = unpacked.name;
|
||||
this.abbrs = unpacked.abbrs;
|
||||
this.untils = unpacked.untils;
|
||||
this.offsets = unpacked.offsets;
|
||||
this.population = unpacked.population;
|
||||
},
|
||||
|
||||
_index : function (timestamp) {
|
||||
var target = +timestamp,
|
||||
untils = this.untils,
|
||||
i;
|
||||
|
||||
for (i = 0; i < untils.length; i++) {
|
||||
if (target < untils[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
parse : function (timestamp) {
|
||||
var target = +timestamp,
|
||||
offsets = this.offsets,
|
||||
untils = this.untils,
|
||||
max = untils.length - 1,
|
||||
offset, offsetNext, offsetPrev, i;
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
offset = offsets[i];
|
||||
offsetNext = offsets[i + 1];
|
||||
offsetPrev = offsets[i ? i - 1 : i];
|
||||
|
||||
if (offset < offsetNext && tz.moveAmbiguousForward) {
|
||||
offset = offsetNext;
|
||||
} else if (offset > offsetPrev && tz.moveInvalidForward) {
|
||||
offset = offsetPrev;
|
||||
}
|
||||
|
||||
if (target < untils[i] - (offset * 60000)) {
|
||||
return offsets[i];
|
||||
}
|
||||
}
|
||||
|
||||
return offsets[max];
|
||||
},
|
||||
|
||||
abbr : function (mom) {
|
||||
return this.abbrs[this._index(mom)];
|
||||
},
|
||||
|
||||
offset : function (mom) {
|
||||
return this.offsets[this._index(mom)];
|
||||
}
|
||||
};
|
||||
|
||||
/************************************
|
||||
Current Timezone
|
||||
************************************/
|
||||
|
||||
function OffsetAt(at) {
|
||||
var timeString = at.toTimeString();
|
||||
var abbr = timeString.match(/\([a-z ]+\)/i);
|
||||
if (abbr && abbr[0]) {
|
||||
// 17:56:31 GMT-0600 (CST)
|
||||
// 17:56:31 GMT-0600 (Central Standard Time)
|
||||
abbr = abbr[0].match(/[A-Z]/g);
|
||||
abbr = abbr ? abbr.join('') : undefined;
|
||||
} else {
|
||||
// 17:56:31 CST
|
||||
// 17:56:31 GMT+0800 (台北標準時間)
|
||||
abbr = timeString.match(/[A-Z]{3,5}/g);
|
||||
abbr = abbr ? abbr[0] : undefined;
|
||||
}
|
||||
|
||||
if (abbr === 'GMT') {
|
||||
abbr = undefined;
|
||||
}
|
||||
|
||||
this.at = +at;
|
||||
this.abbr = abbr;
|
||||
this.offset = at.getTimezoneOffset();
|
||||
}
|
||||
|
||||
function ZoneScore(zone) {
|
||||
this.zone = zone;
|
||||
this.offsetScore = 0;
|
||||
this.abbrScore = 0;
|
||||
}
|
||||
|
||||
ZoneScore.prototype.scoreOffsetAt = function (offsetAt) {
|
||||
this.offsetScore += Math.abs(this.zone.offset(offsetAt.at) - offsetAt.offset);
|
||||
if (this.zone.abbr(offsetAt.at).replace(/[^A-Z]/g, '') !== offsetAt.abbr) {
|
||||
this.abbrScore++;
|
||||
}
|
||||
};
|
||||
|
||||
function findChange(low, high) {
|
||||
var mid, diff;
|
||||
|
||||
while ((diff = ((high.at - low.at) / 12e4 | 0) * 6e4)) {
|
||||
mid = new OffsetAt(new Date(low.at + diff));
|
||||
if (mid.offset === low.offset) {
|
||||
low = mid;
|
||||
} else {
|
||||
high = mid;
|
||||
}
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
function userOffsets() {
|
||||
var startYear = new Date().getFullYear() - 2,
|
||||
last = new OffsetAt(new Date(startYear, 0, 1)),
|
||||
offsets = [last],
|
||||
change, next, i;
|
||||
|
||||
for (i = 1; i < 48; i++) {
|
||||
next = new OffsetAt(new Date(startYear, i, 1));
|
||||
if (next.offset !== last.offset) {
|
||||
change = findChange(last, next);
|
||||
offsets.push(change);
|
||||
offsets.push(new OffsetAt(new Date(change.at + 6e4)));
|
||||
}
|
||||
last = next;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
offsets.push(new OffsetAt(new Date(startYear + i, 0, 1)));
|
||||
offsets.push(new OffsetAt(new Date(startYear + i, 6, 1)));
|
||||
}
|
||||
|
||||
return offsets;
|
||||
}
|
||||
|
||||
function sortZoneScores (a, b) {
|
||||
if (a.offsetScore !== b.offsetScore) {
|
||||
return a.offsetScore - b.offsetScore;
|
||||
}
|
||||
if (a.abbrScore !== b.abbrScore) {
|
||||
return a.abbrScore - b.abbrScore;
|
||||
}
|
||||
return b.zone.population - a.zone.population;
|
||||
}
|
||||
|
||||
function addToGuesses (name, offsets) {
|
||||
var i, offset;
|
||||
arrayToInt(offsets);
|
||||
for (i = 0; i < offsets.length; i++) {
|
||||
offset = offsets[i];
|
||||
guesses[offset] = guesses[offset] || {};
|
||||
guesses[offset][name] = true;
|
||||
}
|
||||
}
|
||||
|
||||
function guessesForUserOffsets (offsets) {
|
||||
var offsetsLength = offsets.length,
|
||||
filteredGuesses = {},
|
||||
out = [],
|
||||
i, j, guessesOffset;
|
||||
|
||||
for (i = 0; i < offsetsLength; i++) {
|
||||
guessesOffset = guesses[offsets[i].offset] || {};
|
||||
for (j in guessesOffset) {
|
||||
if (guessesOffset.hasOwnProperty(j)) {
|
||||
filteredGuesses[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i in filteredGuesses) {
|
||||
if (filteredGuesses.hasOwnProperty(i)) {
|
||||
out.push(names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function rebuildGuess () {
|
||||
|
||||
// use Intl API when available and returning valid time zone
|
||||
try {
|
||||
var intlName = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
if (intlName){
|
||||
var name = names[normalizeName(intlName)];
|
||||
if (name) {
|
||||
return name;
|
||||
}
|
||||
logError("Moment Timezone found " + intlName + " from the Intl api, but did not have that data loaded.");
|
||||
}
|
||||
} catch (e) {
|
||||
// Intl unavailable, fall back to manual guessing.
|
||||
}
|
||||
|
||||
var offsets = userOffsets(),
|
||||
offsetsLength = offsets.length,
|
||||
guesses = guessesForUserOffsets(offsets),
|
||||
zoneScores = [],
|
||||
zoneScore, i, j;
|
||||
|
||||
for (i = 0; i < guesses.length; i++) {
|
||||
zoneScore = new ZoneScore(getZone(guesses[i]), offsetsLength);
|
||||
for (j = 0; j < offsetsLength; j++) {
|
||||
zoneScore.scoreOffsetAt(offsets[j]);
|
||||
}
|
||||
zoneScores.push(zoneScore);
|
||||
}
|
||||
|
||||
zoneScores.sort(sortZoneScores);
|
||||
|
||||
return zoneScores.length > 0 ? zoneScores[0].zone.name : undefined;
|
||||
}
|
||||
|
||||
function guess (ignoreCache) {
|
||||
if (!cachedGuess || ignoreCache) {
|
||||
cachedGuess = rebuildGuess();
|
||||
}
|
||||
return cachedGuess;
|
||||
}
|
||||
|
||||
/************************************
|
||||
Global Methods
|
||||
************************************/
|
||||
|
||||
function normalizeName (name) {
|
||||
return (name || '').toLowerCase().replace(/\//g, '_');
|
||||
}
|
||||
|
||||
function addZone (packed) {
|
||||
var i, name, split, normalized;
|
||||
|
||||
if (typeof packed === "string") {
|
||||
packed = [packed];
|
||||
}
|
||||
|
||||
for (i = 0; i < packed.length; i++) {
|
||||
split = packed[i].split('|');
|
||||
name = split[0];
|
||||
normalized = normalizeName(name);
|
||||
zones[normalized] = packed[i];
|
||||
names[normalized] = name;
|
||||
if (split[5]) {
|
||||
addToGuesses(normalized, split[2].split(' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getZone (name, caller) {
|
||||
name = normalizeName(name);
|
||||
|
||||
var zone = zones[name];
|
||||
var link;
|
||||
|
||||
if (zone instanceof Zone) {
|
||||
return zone;
|
||||
}
|
||||
|
||||
if (typeof zone === 'string') {
|
||||
zone = new Zone(zone);
|
||||
zones[name] = zone;
|
||||
return zone;
|
||||
}
|
||||
|
||||
// Pass getZone to prevent recursion more than 1 level deep
|
||||
if (links[name] && caller !== getZone && (link = getZone(links[name], getZone))) {
|
||||
zone = zones[name] = new Zone();
|
||||
zone._set(link);
|
||||
zone.name = names[name];
|
||||
return zone;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function getNames () {
|
||||
var i, out = [];
|
||||
|
||||
for (i in names) {
|
||||
if (names.hasOwnProperty(i) && (zones[i] || zones[links[i]]) && names[i]) {
|
||||
out.push(names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return out.sort();
|
||||
}
|
||||
|
||||
function addLink (aliases) {
|
||||
var i, alias, normal0, normal1;
|
||||
|
||||
if (typeof aliases === "string") {
|
||||
aliases = [aliases];
|
||||
}
|
||||
|
||||
for (i = 0; i < aliases.length; i++) {
|
||||
alias = aliases[i].split('|');
|
||||
|
||||
normal0 = normalizeName(alias[0]);
|
||||
normal1 = normalizeName(alias[1]);
|
||||
|
||||
links[normal0] = normal1;
|
||||
names[normal0] = alias[0];
|
||||
|
||||
links[normal1] = normal0;
|
||||
names[normal1] = alias[1];
|
||||
}
|
||||
}
|
||||
|
||||
function loadData (data) {
|
||||
addZone(data.zones);
|
||||
addLink(data.links);
|
||||
tz.dataVersion = data.version;
|
||||
}
|
||||
|
||||
function zoneExists (name) {
|
||||
if (!zoneExists.didShowError) {
|
||||
zoneExists.didShowError = true;
|
||||
logError("moment.tz.zoneExists('" + name + "') has been deprecated in favor of !moment.tz.zone('" + name + "')");
|
||||
}
|
||||
return !!getZone(name);
|
||||
}
|
||||
|
||||
function needsOffset (m) {
|
||||
return !!(m._a && (m._tzm === undefined));
|
||||
}
|
||||
|
||||
function logError (message) {
|
||||
if (typeof console !== 'undefined' && typeof console.error === 'function') {
|
||||
console.error(message);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************
|
||||
moment.tz namespace
|
||||
************************************/
|
||||
|
||||
function tz (input) {
|
||||
var args = Array.prototype.slice.call(arguments, 0, -1),
|
||||
name = arguments[arguments.length - 1],
|
||||
zone = getZone(name),
|
||||
out = moment.utc.apply(null, args);
|
||||
|
||||
if (zone && !moment.isMoment(input) && needsOffset(out)) {
|
||||
out.add(zone.parse(out), 'minutes');
|
||||
}
|
||||
|
||||
out.tz(name);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
tz.version = VERSION;
|
||||
tz.dataVersion = '';
|
||||
tz._zones = zones;
|
||||
tz._links = links;
|
||||
tz._names = names;
|
||||
tz.add = addZone;
|
||||
tz.link = addLink;
|
||||
tz.load = loadData;
|
||||
tz.zone = getZone;
|
||||
tz.zoneExists = zoneExists; // deprecated in 0.1.0
|
||||
tz.guess = guess;
|
||||
tz.names = getNames;
|
||||
tz.Zone = Zone;
|
||||
tz.unpack = unpack;
|
||||
tz.unpackBase60 = unpackBase60;
|
||||
tz.needsOffset = needsOffset;
|
||||
tz.moveInvalidForward = true;
|
||||
tz.moveAmbiguousForward = false;
|
||||
|
||||
/************************************
|
||||
Interface with Moment.js
|
||||
************************************/
|
||||
|
||||
var fn = moment.fn;
|
||||
|
||||
moment.tz = tz;
|
||||
|
||||
moment.defaultZone = null;
|
||||
|
||||
moment.updateOffset = function (mom, keepTime) {
|
||||
var zone = moment.defaultZone,
|
||||
offset;
|
||||
|
||||
if (mom._z === undefined) {
|
||||
if (zone && needsOffset(mom) && !mom._isUTC) {
|
||||
mom._d = moment.utc(mom._a)._d;
|
||||
mom.utc().add(zone.parse(mom), 'minutes');
|
||||
}
|
||||
mom._z = zone;
|
||||
}
|
||||
if (mom._z) {
|
||||
offset = mom._z.offset(mom);
|
||||
if (Math.abs(offset) < 16) {
|
||||
offset = offset / 60;
|
||||
}
|
||||
if (mom.utcOffset !== undefined) {
|
||||
mom.utcOffset(-offset, keepTime);
|
||||
} else {
|
||||
mom.zone(offset, keepTime);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fn.tz = function (name) {
|
||||
if (name) {
|
||||
this._z = getZone(name);
|
||||
if (this._z) {
|
||||
moment.updateOffset(this);
|
||||
} else {
|
||||
logError("Moment Timezone has no data for " + name + ". See http://momentjs.com/timezone/docs/#/data-loading/.");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (this._z) { return this._z.name; }
|
||||
};
|
||||
|
||||
function abbrWrap (old) {
|
||||
return function () {
|
||||
if (this._z) { return this._z.abbr(this); }
|
||||
return old.call(this);
|
||||
};
|
||||
}
|
||||
|
||||
function resetZoneWrap (old) {
|
||||
return function () {
|
||||
this._z = null;
|
||||
return old.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
|
||||
fn.zoneName = abbrWrap(fn.zoneName);
|
||||
fn.zoneAbbr = abbrWrap(fn.zoneAbbr);
|
||||
fn.utc = resetZoneWrap(fn.utc);
|
||||
|
||||
moment.tz.setDefault = function(name) {
|
||||
if (major < 2 || (major === 2 && minor < 9)) {
|
||||
logError('Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js ' + moment.version + '.');
|
||||
}
|
||||
moment.defaultZone = name ? getZone(name) : null;
|
||||
return moment;
|
||||
};
|
||||
|
||||
// Cloning a moment should include the _z property.
|
||||
var momentProperties = moment.momentProperties;
|
||||
if (Object.prototype.toString.call(momentProperties) === '[object Array]') {
|
||||
// moment 2.8.1+
|
||||
momentProperties.push('_z');
|
||||
momentProperties.push('_a');
|
||||
} else if (momentProperties) {
|
||||
// moment 2.7.0
|
||||
momentProperties._z = null;
|
||||
}
|
||||
|
||||
// INJECT DATA
|
||||
|
||||
return moment;
|
||||
}));
|
||||
@@ -1,492 +0,0 @@
|
||||
//! moment.js
|
||||
//! version : 2.14.1
|
||||
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
|
||||
//! license : MIT
|
||||
//! momentjs.com
|
||||
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return md.apply(null,arguments)}
|
||||
// This is done to register the method called with moment()
|
||||
// without creating circular dependencies.
|
||||
function b(a){md=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a)
|
||||
// even if its not own property I'd still call it non-empty
|
||||
return!1;return!0}function f(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function g(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function h(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function i(a,b){for(var c in b)h(b,c)&&(a[c]=b[c]);return h(b,"toString")&&(a.toString=b.toString),h(b,"valueOf")&&(a.valueOf=b.valueOf),a}function j(a,b,c,d){return qb(a,b,c,d,!0).utc()}function k(){
|
||||
// We need to deep clone this object.
|
||||
return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function l(a){return null==a._pf&&(a._pf=k()),a._pf}function m(a){if(null==a._isValid){var b=l(a),c=nd.call(b.parsedDateParts,function(a){return null!=a});a._isValid=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c),a._strict&&(a._isValid=a._isValid&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour)}return a._isValid}function n(a){var b=j(NaN);return null!=a?i(l(b),a):l(b).userInvalidated=!0,b}function o(a){return void 0===a}function p(a,b){var c,d,e;if(o(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),o(b._i)||(a._i=b._i),o(b._f)||(a._f=b._f),o(b._l)||(a._l=b._l),o(b._strict)||(a._strict=b._strict),o(b._tzm)||(a._tzm=b._tzm),o(b._isUTC)||(a._isUTC=b._isUTC),o(b._offset)||(a._offset=b._offset),o(b._pf)||(a._pf=l(b)),o(b._locale)||(a._locale=b._locale),od.length>0)for(c in od)d=od[c],e=b[d],o(e)||(a[d]=e);return a}
|
||||
// Moment prototype object
|
||||
function q(b){p(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),pd===!1&&(pd=!0,a.updateOffset(this),pd=!1)}function r(a){return a instanceof q||null!=a&&null!=a._isAMomentObject}function s(a){return 0>a?Math.ceil(a)||0:Math.floor(a)}function t(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=s(b)),c}
|
||||
// compare two arrays, return the number of differences
|
||||
function u(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&t(a[d])!==t(b[d]))&&g++;return g+f}function v(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function w(b,c){var d=!0;return i(function(){return null!=a.deprecationHandler&&a.deprecationHandler(null,b),d&&(v(b+"\nArguments: "+Array.prototype.slice.call(arguments).join(", ")+"\n"+(new Error).stack),d=!1),c.apply(this,arguments)},c)}function x(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),qd[b]||(v(c),qd[b]=!0)}function y(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function z(a){var b,c;for(c in a)b=a[c],y(b)?this[c]=b:this["_"+c]=b;this._config=a,
|
||||
// Lenient ordinal parsing accepts just a number in addition to
|
||||
// number + (possibly) stuff coming from _ordinalParseLenient.
|
||||
this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function A(a,b){var c,e=i({},a);for(c in b)h(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},i(e[c],a[c]),i(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);for(c in a)h(a,c)&&!h(b,c)&&d(a[c])&&(
|
||||
// make sure changes to properties don't modify parent config
|
||||
e[c]=i({},e[c]));return e}function B(a){null!=a&&this.set(a)}function C(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return y(d)?d.call(b,c):d}function D(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function E(){return this._invalidDate}function F(a){return this._ordinal.replace("%d",a)}function G(a,b,c,d){var e=this._relativeTime[c];return y(e)?e(a,b,c,d):e.replace(/%d/i,a)}function H(a,b){var c=this._relativeTime[a>0?"future":"past"];return y(c)?c(b):c.replace(/%s/i,b)}function I(a,b){var c=a.toLowerCase();zd[c]=zd[c+"s"]=zd[b]=a}function J(a){return"string"==typeof a?zd[a]||zd[a.toLowerCase()]:void 0}function K(a){var b,c,d={};for(c in a)h(a,c)&&(b=J(c),b&&(d[b]=a[c]));return d}function L(a,b){Ad[a]=b}function M(a){var b=[];for(var c in a)b.push({unit:c,priority:Ad[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function N(b,c){return function(d){return null!=d?(P(this,b,d),a.updateOffset(this,c),this):O(this,b)}}function O(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function P(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}
|
||||
// MOMENTS
|
||||
function Q(a){return a=J(a),y(this[a])?this[a]():this}function R(a,b){if("object"==typeof a){a=K(a);for(var c=M(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=J(a),y(this[a]))return this[a](b);return this}function S(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}
|
||||
// token: 'M'
|
||||
// padded: ['MM', 2]
|
||||
// ordinal: 'Mo'
|
||||
// callback: function () { this.month() + 1 }
|
||||
function T(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Ed[a]=e),b&&(Ed[b[0]]=function(){return S(e.apply(this,arguments),b[1],b[2])}),c&&(Ed[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function U(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function V(a){var b,c,d=a.match(Bd);for(b=0,c=d.length;c>b;b++)Ed[d[b]]?d[b]=Ed[d[b]]:d[b]=U(d[b]);return function(b){var e,f="";for(e=0;c>e;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}
|
||||
// format date using native date object
|
||||
function W(a,b){return a.isValid()?(b=X(b,a.localeData()),Dd[b]=Dd[b]||V(b),Dd[b](a)):a.localeData().invalidDate()}function X(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Cd.lastIndex=0;d>=0&&Cd.test(a);)a=a.replace(Cd,c),Cd.lastIndex=0,d-=1;return a}function Y(a,b,c){Wd[a]=y(b)?b:function(a,d){return a&&c?c:b}}function Z(a,b){return h(Wd,a)?Wd[a](b._strict,b._locale):new RegExp($(a))}
|
||||
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
|
||||
function $(a){return _(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function _(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function aa(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=t(a)}),c=0;c<a.length;c++)Xd[a[c]]=d}function ba(a,b){aa(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function ca(a,b,c){null!=b&&h(Xd,a)&&Xd[a](b,c._a,c,a)}function da(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ea(a,b){return c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||fe).test(b)?"format":"standalone"][a.month()]}function fa(a,b){return c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[fe.test(b)?"format":"standalone"][a.month()]}function ga(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(
|
||||
// this is not used
|
||||
this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;12>d;++d)f=j([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=sd.call(this._shortMonthsParse,g),-1!==e?e:null):(e=sd.call(this._longMonthsParse,g),-1!==e?e:null):"MMM"===b?(e=sd.call(this._shortMonthsParse,g),-1!==e?e:(e=sd.call(this._longMonthsParse,g),-1!==e?e:null)):(e=sd.call(this._longMonthsParse,g),-1!==e?e:(e=sd.call(this._shortMonthsParse,g),-1!==e?e:null))}function ha(a,b,c){var d,e,f;if(this._monthsParseExact)return ga.call(this,a,b,c);
|
||||
// TODO: add sorting
|
||||
// Sorting makes sure if one month (or abbr) is a prefix of another
|
||||
// see sorting in computeMonthsParse
|
||||
for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;12>d;d++){
|
||||
// test the regex
|
||||
if(e=j([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}
|
||||
// MOMENTS
|
||||
function ia(a,b){var c;if(!a.isValid())
|
||||
// No op
|
||||
return a;if("string"==typeof b)if(/^\d+$/.test(b))b=t(b);else
|
||||
// TODO: Another silent failure?
|
||||
if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),da(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ja(b){return null!=b?(ia(this,b),a.updateOffset(this,!0),this):O(this,"Month")}function ka(){return da(this.year(),this.month())}function la(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=ie),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function ma(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=je),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function na(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;12>b;b++)c=j([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(
|
||||
// Sorting makes sure if one month (or abbr) is a prefix of another it
|
||||
// will match the longer piece.
|
||||
d.sort(a),e.sort(a),f.sort(a),b=0;12>b;b++)d[b]=_(d[b]),e[b]=_(e[b]);for(b=0;24>b;b++)f[b]=_(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}
|
||||
// HELPERS
|
||||
function oa(a){return pa(a)?366:365}function pa(a){return a%4===0&&a%100!==0||a%400===0}function qa(){return pa(this.year())}function ra(a,b,c,d,e,f,g){
|
||||
//can't just apply() to create a date:
|
||||
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
|
||||
var h=new Date(a,b,c,d,e,f,g);
|
||||
//the date constructor remaps years 0-99 to 1900-1999
|
||||
return 100>a&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function sa(a){var b=new Date(Date.UTC.apply(null,arguments));
|
||||
//the Date.UTC function remaps years 0-99 to 1900-1999
|
||||
return 100>a&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}
|
||||
// start-of-first-week - start-of-year
|
||||
function ta(a,b,c){var// first-week day -- which january is always in the first week (4 for iso, 1 for other)
|
||||
d=7+b-c,
|
||||
// first-week day local weekday -- which local weekday is fwd
|
||||
e=(7+sa(a,0,d).getUTCDay()-b)%7;return-e+d-1}
|
||||
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
|
||||
function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;return 0>=j?(f=a-1,g=oa(f)+j):j>oa(a)?(f=a+1,g=j-oa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return 1>g?(e=a.year()-1,d=g+wa(e,b,c)):g>wa(a.year(),b,c)?(d=g-wa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(oa(a)-d+e)/7}
|
||||
// HELPERS
|
||||
// LOCALES
|
||||
function xa(a){return va(a,this._week.dow,this._week.doy).week}function ya(){return this._week.dow}function za(){return this._week.doy}
|
||||
// MOMENTS
|
||||
function Aa(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ba(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}
|
||||
// HELPERS
|
||||
function Ca(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Da(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Ea(a,b){return c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]}function Fa(a){return this._weekdaysShort[a.day()]}function Ga(a){return this._weekdaysMin[a.day()]}function Ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;7>d;++d)f=j([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=sd.call(this._weekdaysParse,g),-1!==e?e:null):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:null):(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:null):"dddd"===b?(e=sd.call(this._weekdaysParse,g),-1!==e?e:(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:null))):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:(e=sd.call(this._weekdaysParse,g),-1!==e?e:(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:null))):(e=sd.call(this._minWeekdaysParse,g),-1!==e?e:(e=sd.call(this._weekdaysParse,g),-1!==e?e:(e=sd.call(this._shortWeekdaysParse,g),-1!==e?e:null)))}function Ia(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ha.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;7>d;d++){
|
||||
// test the regex
|
||||
if(e=j([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}
|
||||
// MOMENTS
|
||||
function Ja(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Ca(a,this.localeData()),this.add(a-b,"d")):b}function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function La(a){if(!this.isValid())return null!=a?this:NaN;
|
||||
// behaves the same as moment#day except
|
||||
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
|
||||
// as a setter, sunday should belong to the previous week.
|
||||
if(null!=a){var b=Da(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Ma(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=pe),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Na(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Oa(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=re),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Pa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],k=[];for(b=0;7>b;b++)c=j([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),k.push(d),k.push(e),k.push(f);for(
|
||||
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
|
||||
// will match the longer piece.
|
||||
g.sort(a),h.sort(a),i.sort(a),k.sort(a),b=0;7>b;b++)h[b]=_(h[b]),i[b]=_(i[b]),k[b]=_(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}
|
||||
// FORMATTING
|
||||
function Qa(){return this.hours()%12||12}function Ra(){return this.hours()||24}function Sa(a,b){T(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}
|
||||
// PARSING
|
||||
function Ta(a,b){return b._meridiemParse}
|
||||
// LOCALES
|
||||
function Ua(a){
|
||||
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
|
||||
// Using charAt should be more compatible.
|
||||
return"p"===(a+"").toLowerCase().charAt(0)}function Va(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wa(a){return a?a.toLowerCase().replace("_","-"):a}
|
||||
// pick the locale from the array
|
||||
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
|
||||
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
|
||||
function Xa(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Wa(a[f]).split("-"),b=e.length,c=Wa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Ya(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&u(e,c,!0)>=b-1)
|
||||
//the next array item is better than a shallower substring of this one
|
||||
break;b--}f++}return null}function Ya(a){var b=null;
|
||||
// TODO: Find a better way to register and load all the locales in Node
|
||||
if(!we[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=se._abbr,require("./locale/"+a),
|
||||
// because defineLocale currently also sets the global locale, we
|
||||
// want to undo that for lazy loaded locales
|
||||
Za(b)}catch(c){}return we[a]}
|
||||
// This function will load locale and then set the global locale. If
|
||||
// no arguments are passed in, it will simply return the current global
|
||||
// locale key.
|
||||
function Za(a,b){var c;
|
||||
// moment.duration._locale = moment._locale = data;
|
||||
return a&&(c=o(b)?ab(a):$a(a,b),c&&(se=c)),se._abbr}function $a(a,b){if(null!==b){var c=ve;
|
||||
// treat as if there is no base config
|
||||
// backwards compat for now: also set the locale
|
||||
return b.abbr=a,null!=we[a]?(x("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=we[a]._config):null!=b.parentLocale&&(null!=we[b.parentLocale]?c=we[b.parentLocale]._config:x("parentLocaleUndefined","specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/")),we[a]=new B(A(c,b)),Za(a),we[a]}
|
||||
// useful for testing
|
||||
return delete we[a],null}function _a(a,b){if(null!=b){var c,d=ve;
|
||||
// MERGE
|
||||
null!=we[a]&&(d=we[a]._config),b=A(d,b),c=new B(b),c.parentLocale=we[a],we[a]=c,
|
||||
// backwards compat for now: also set the locale
|
||||
Za(a)}else
|
||||
// pass null for config to unupdate, useful for tests
|
||||
null!=we[a]&&(null!=we[a].parentLocale?we[a]=we[a].parentLocale:null!=we[a]&&delete we[a]);return we[a]}
|
||||
// returns locale data
|
||||
function ab(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return se;if(!c(a)){if(b=Ya(a))return b;a=[a]}return Xa(a)}function bb(){return rd(we)}function cb(a){var b,c=a._a;return c&&-2===l(a).overflow&&(b=c[Zd]<0||c[Zd]>11?Zd:c[$d]<1||c[$d]>da(c[Yd],c[Zd])?$d:c[_d]<0||c[_d]>24||24===c[_d]&&(0!==c[ae]||0!==c[be]||0!==c[ce])?_d:c[ae]<0||c[ae]>59?ae:c[be]<0||c[be]>59?be:c[ce]<0||c[ce]>999?ce:-1,l(a)._overflowDayOfYear&&(Yd>b||b>$d)&&(b=$d),l(a)._overflowWeeks&&-1===b&&(b=de),l(a)._overflowWeekday&&-1===b&&(b=ee),l(a).overflow=b),a}
|
||||
// date from iso format
|
||||
function db(a){var b,c,d,e,f,g,h=a._i,i=xe.exec(h)||ye.exec(h);if(i){for(l(a).iso=!0,b=0,c=Ae.length;c>b;b++)if(Ae[b][1].exec(i[1])){e=Ae[b][0],d=Ae[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=Be.length;c>b;b++)if(Be[b][1].exec(i[3])){
|
||||
// match[2] should be 'T' or space
|
||||
f=(i[2]||" ")+Be[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ze.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),jb(a)}else a._isValid=!1}
|
||||
// date from iso format or fallback
|
||||
function eb(b){var c=Ce.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(db(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}
|
||||
// Pick the first defined of two or three arguments.
|
||||
function fb(a,b,c){return null!=a?a:null!=b?b:c}function gb(b){
|
||||
// hooks is actually the exported moment object
|
||||
var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}
|
||||
// convert an array to a date.
|
||||
// the array should mirror the parameters below
|
||||
// note: all values past the year are optional and will default to the lowest possible value.
|
||||
// [year, month, day , hour, minute, second, millisecond]
|
||||
function hb(a){var b,c,d,e,f=[];if(!a._d){
|
||||
// Default to current date.
|
||||
// * if no year, month, day of month are given, default to today
|
||||
// * if day of month is given, default month and year
|
||||
// * if month is given, default only year
|
||||
// * if year is given, don't default anything
|
||||
for(d=gb(a),a._w&&null==a._a[$d]&&null==a._a[Zd]&&ib(a),a._dayOfYear&&(e=fb(a._a[Yd],d[Yd]),a._dayOfYear>oa(e)&&(l(a)._overflowDayOfYear=!0),c=sa(e,0,a._dayOfYear),a._a[Zd]=c.getUTCMonth(),a._a[$d]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=f[b]=d[b];
|
||||
// Zero out whatever was not defaulted, including time
|
||||
for(;7>b;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];
|
||||
// Check for 24:00:00.000
|
||||
24===a._a[_d]&&0===a._a[ae]&&0===a._a[be]&&0===a._a[ce]&&(a._nextDay=!0,a._a[_d]=0),a._d=(a._useUTC?sa:ra).apply(null,f),
|
||||
// Apply timezone offset from input. The actual utcOffset can be changed
|
||||
// with parseZone.
|
||||
null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[_d]=24)}}function ib(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,c=fb(b.GG,a._a[Yd],va(rb(),1,4).year),d=fb(b.W,1),e=fb(b.E,1),(1>e||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=fb(b.gg,a._a[Yd],va(rb(),f,g).year),d=fb(b.w,1),null!=b.d?(e=b.d,(0>e||e>6)&&(i=!0)):null!=b.e?(e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):e=f),1>d||d>wa(c,f,g)?l(a)._overflowWeeks=!0:null!=i?l(a)._overflowWeekday=!0:(h=ua(c,d,e,f,g),a._a[Yd]=h.year,a._dayOfYear=h.dayOfYear)}
|
||||
// date from string and format string
|
||||
function jb(b){
|
||||
// TODO: Move this to another part of the creation flow to prevent circular deps
|
||||
if(b._f===a.ISO_8601)return void db(b);b._a=[],l(b).empty=!0;
|
||||
// This array is used to make a Date, either with `new Date` or `Date.UTC`
|
||||
var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=X(b._f,b._locale).match(Bd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(Z(f,b))||[])[0],d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&l(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),Ed[f]?(d?l(b).empty=!1:l(b).unusedTokens.push(f),ca(f,d,b)):b._strict&&!d&&l(b).unusedTokens.push(f);
|
||||
// add remaining unparsed input length to the string
|
||||
l(b).charsLeftOver=i-j,h.length>0&&l(b).unusedInput.push(h),
|
||||
// clear _12h flag if hour is <= 12
|
||||
b._a[_d]<=12&&l(b).bigHour===!0&&b._a[_d]>0&&(l(b).bigHour=void 0),l(b).parsedDateParts=b._a.slice(0),l(b).meridiem=b._meridiem,
|
||||
// handle meridiem
|
||||
b._a[_d]=kb(b._locale,b._a[_d],b._meridiem),hb(b),cb(b)}function kb(a,b,c){var d;
|
||||
// Fallback
|
||||
return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&12>b&&(b+=12),d||12!==b||(b=0),b):b}
|
||||
// date from string and array of format strings
|
||||
function lb(a){var b,c,d,e,f;if(0===a._f.length)return l(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=p({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],jb(b),m(b)&&(f+=l(b).charsLeftOver,f+=10*l(b).unusedTokens.length,l(b).score=f,(null==d||d>f)&&(d=f,c=b));i(a,c||b)}function mb(a){if(!a._d){var b=K(a._i);a._a=g([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),hb(a)}}function nb(a){var b=new q(cb(ob(a)));
|
||||
// Adding is smart enough around DST
|
||||
return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function ob(a){var b=a._i,d=a._f;return a._locale=a._locale||ab(a._l),null===b||void 0===d&&""===b?n({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),r(b)?new q(cb(b)):(c(d)?lb(a):f(b)?a._d=b:d?jb(a):pb(a),m(a)||(a._d=null),a))}function pb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):f(d)?b._d=new Date(d.valueOf()):"string"==typeof d?eb(b):c(d)?(b._a=g(d.slice(0),function(a){return parseInt(a,10)}),hb(b)):"object"==typeof d?mb(b):"number"==typeof d?
|
||||
// from milliseconds
|
||||
b._d=new Date(d):a.createFromInputFallback(b)}function qb(a,b,f,g,h){var i={};
|
||||
// object construction must be done this way.
|
||||
// https://github.com/moment/moment/issues/1423
|
||||
return"boolean"==typeof f&&(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,nb(i)}function rb(a,b,c,d){return qb(a,b,c,d,!1)}
|
||||
// Pick a moment m from moments so that m[fn](other) is true for all
|
||||
// other. This relies on the function fn to be transitive.
|
||||
//
|
||||
// moments should either be an array of moment objects or an array, whose
|
||||
// first element is an array of moment objects.
|
||||
function sb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return rb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d}
|
||||
// TODO: Use [].sort instead?
|
||||
function tb(){var a=[].slice.call(arguments,0);return sb("isBefore",a)}function ub(){var a=[].slice.call(arguments,0);return sb("isAfter",a)}function vb(a){var b=K(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;
|
||||
// representation for dateAddRemove
|
||||
this._milliseconds=+k+1e3*j+// 1000
|
||||
6e4*i+// 1000 * 60
|
||||
1e3*h*60*60,//using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
|
||||
// Because of dateAddRemove treats 24 hours as different from a
|
||||
// day when working around DST, we need to store them separately
|
||||
this._days=+g+7*f,
|
||||
// It is impossible translate months into days without knowing
|
||||
// which months you are are talking about, so we have to store
|
||||
// it separately.
|
||||
this._months=+e+3*d+12*c,this._data={},this._locale=ab(),this._bubble()}function wb(a){return a instanceof vb}
|
||||
// FORMATTING
|
||||
function xb(a,b){T(a,0,0,function(){var a=this.utcOffset(),c="+";return 0>a&&(a=-a,c="-"),c+S(~~(a/60),2)+b+S(~~a%60,2)})}function yb(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(Ge)||["-",0,0],f=+(60*e[1])+t(e[2]);return"+"===e[0]?f:-f}
|
||||
// Return a moment from input, that is local/utc/zone equivalent to model.
|
||||
function zb(b,c){var d,e;
|
||||
// Use low-level api, because this fn is low-level api.
|
||||
return c._isUTC?(d=c.clone(),e=(r(b)||f(b)?b.valueOf():rb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):rb(b).local()}function Ab(a){
|
||||
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
|
||||
// https://github.com/moment/moment/pull/1871
|
||||
return 15*-Math.round(a._d.getTimezoneOffset()/15)}
|
||||
// MOMENTS
|
||||
// keepLocalTime = true means only change the timezone, without
|
||||
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
|
||||
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
|
||||
// +0200, so we adjust the time as needed, to be valid.
|
||||
//
|
||||
// Keeping the time actually adds/subtracts (one hour)
|
||||
// from the actual represented time. That is why we call updateOffset
|
||||
// a second time. In case it wants us to change the offset again
|
||||
// _changeInProgress == true case, then we have to adjust, because
|
||||
// there is no such time in the given timezone.
|
||||
function Bb(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=yb(Td,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Ab(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Sb(this,Mb(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Ab(this):null!=b?this:NaN}function Cb(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Db(a){return this.utcOffset(0,a)}function Eb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Ab(this),"m")),this}function Fb(){return this._tzm?this.utcOffset(this._tzm):"string"==typeof this._i&&this.utcOffset(yb(Sd,this._i)),this}function Gb(a){return this.isValid()?(a=a?rb(a).utcOffset():0,(this.utcOffset()-a)%60===0):!1}function Hb(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Ib(){if(!o(this._isDSTShifted))return this._isDSTShifted;var a={};if(p(a,this),a=ob(a),a._a){var b=a._isUTC?j(a._a):rb(a._a);this._isDSTShifted=this.isValid()&&u(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Jb(){return this.isValid()?!this._isUTC:!1}function Kb(){return this.isValid()?this._isUTC:!1}function Lb(){return this.isValid()?this._isUTC&&0===this._offset:!1}function Mb(a,b){var c,d,e,f=a,
|
||||
// matching against regexp is expensive, do it on demand
|
||||
g=null;// checks for null or undefined
|
||||
return wb(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(g=He.exec(a))?(c="-"===g[1]?-1:1,f={y:0,d:t(g[$d])*c,h:t(g[_d])*c,m:t(g[ae])*c,s:t(g[be])*c,ms:t(g[ce])*c}):(g=Ie.exec(a))?(c="-"===g[1]?-1:1,f={y:Nb(g[2],c),M:Nb(g[3],c),w:Nb(g[4],c),d:Nb(g[5],c),h:Nb(g[6],c),m:Nb(g[7],c),s:Nb(g[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Pb(rb(f.from),rb(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new vb(f),wb(a)&&h(a,"_locale")&&(d._locale=a._locale),d}function Nb(a,b){
|
||||
// We'd normally use ~~inp for this, but unfortunately it also
|
||||
// converts floats to ints.
|
||||
// inp may be undefined, so careful calling replace on it.
|
||||
var c=a&&parseFloat(a.replace(",","."));
|
||||
// apply sign while we're at it
|
||||
return(isNaN(c)?0:c)*b}function Ob(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Pb(a,b){var c;return a.isValid()&&b.isValid()?(b=zb(b,a),a.isBefore(b)?c=Ob(a,b):(c=Ob(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}function Qb(a){return 0>a?-1*Math.round(-1*a):Math.round(a)}
|
||||
// TODO: remove 'name' arg after deprecation is removed
|
||||
function Rb(a,b){return function(c,d){var e,f;
|
||||
//invert the arguments, but complain about it
|
||||
return null===d||isNaN(+d)||(x(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Mb(c,d),Sb(this,e,a),this}}function Sb(b,c,d,e){var f=c._milliseconds,g=Qb(c._days),h=Qb(c._months);b.isValid()&&(e=null==e?!0:e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&P(b,"Date",O(b,"Date")+g*d),h&&ia(b,O(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Tb(a,b){var c=a.diff(b,"days",!0);return-6>c?"sameElse":-1>c?"lastWeek":0>c?"lastDay":1>c?"sameDay":2>c?"nextDay":7>c?"nextWeek":"sameElse"}function Ub(b,c){
|
||||
// We want to compare the start of today, vs this.
|
||||
// Getting start-of-today depends on whether we're local/utc/offset or not.
|
||||
var d=b||rb(),e=zb(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(y(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,rb(d)))}function Vb(){return new q(this)}function Wb(a,b){var c=r(a)?a:rb(a);return this.isValid()&&c.isValid()?(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf()):!1}function Xb(a,b){var c=r(a)?a:rb(a);return this.isValid()&&c.isValid()?(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf()):!1}function Yb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function Zb(a,b){var c,d=r(a)?a:rb(a);return this.isValid()&&d.isValid()?(b=J(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf())):!1}function $b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function _b(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function ac(a,b,c){var d,e,f,g;// 1000
|
||||
// 1000 * 60
|
||||
// 1000 * 60 * 60
|
||||
// 1000 * 60 * 60 * 24, negate dst
|
||||
// 1000 * 60 * 60 * 24 * 7, negate dst
|
||||
return this.isValid()?(d=zb(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=J(b),"year"===b||"month"===b||"quarter"===b?(g=bc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:s(g)):NaN):NaN}function bc(a,b){
|
||||
// difference in months
|
||||
var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),
|
||||
// b is in (anchor - 1 month, anchor + 1 month)
|
||||
f=a.clone().add(e,"months");
|
||||
//check for negative zero, return zero if negative zero
|
||||
// linear across the month
|
||||
// linear across the month
|
||||
return 0>b-f?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function cc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function dc(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?y(Date.prototype.toISOString)?this.toDate().toISOString():W(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):W(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function ec(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=W(this,b);return this.localeData().postformat(c)}function fc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Mb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function gc(a){return this.from(rb(),a)}function hc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Mb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ic(a){return this.to(rb(),a)}
|
||||
// If passed a locale key, it will set the locale for this
|
||||
// instance. Otherwise, it will return the locale configuration
|
||||
// variables for this instance.
|
||||
function jc(a){var b;return void 0===a?this._locale._abbr:(b=ab(a),null!=b&&(this._locale=b),this)}function kc(){return this._locale}function lc(a){
|
||||
// the following switch intentionally omits break keywords
|
||||
// to utilize falling through the cases.
|
||||
switch(a=J(a)){case"year":this.month(0);/* falls through */
|
||||
case"quarter":case"month":this.date(1);/* falls through */
|
||||
case"week":case"isoWeek":case"day":case"date":this.hours(0);/* falls through */
|
||||
case"hour":this.minutes(0);/* falls through */
|
||||
case"minute":this.seconds(0);/* falls through */
|
||||
case"second":this.milliseconds(0)}
|
||||
// weeks are a special case
|
||||
// quarters are also special
|
||||
return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function mc(a){
|
||||
// 'date' is an alias for 'day', so it should be considered as such.
|
||||
return a=J(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function nc(){return this._d.valueOf()-6e4*(this._offset||0)}function oc(){return Math.floor(this.valueOf()/1e3)}function pc(){return new Date(this.valueOf())}function qc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function rc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function sc(){
|
||||
// new Date(NaN).toJSON() === null
|
||||
return this.isValid()?this.toISOString():null}function tc(){return m(this)}function uc(){return i({},l(this))}function vc(){return l(this).overflow}function wc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function xc(a,b){T(0,[a,a.length],0,b)}
|
||||
// MOMENTS
|
||||
function yc(a){return Cc.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function zc(a){return Cc.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Ac(){return wa(this.year(),1,4)}function Bc(){var a=this.localeData()._week;return wa(this.year(),a.dow,a.doy)}function Cc(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,e),b>f&&(b=f),Dc.call(this,a,b,c,d,e))}function Dc(a,b,c,d,e){var f=ua(a,b,c,d,e),g=sa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}
|
||||
// MOMENTS
|
||||
function Ec(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}
|
||||
// HELPERS
|
||||
// MOMENTS
|
||||
function Fc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Gc(a,b){b[ce]=t(1e3*("0."+a))}
|
||||
// MOMENTS
|
||||
function Hc(){return this._isUTC?"UTC":""}function Ic(){return this._isUTC?"Coordinated Universal Time":""}function Jc(a){return rb(1e3*a)}function Kc(){return rb.apply(null,arguments).parseZone()}function Lc(a){return a}function Mc(a,b,c,d){var e=ab(),f=j().set(d,b);return e[c](f,a)}function Nc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Mc(a,b,c,"month");var d,e=[];for(d=0;12>d;d++)e[d]=Mc(a,d,c,"month");return e}
|
||||
// ()
|
||||
// (5)
|
||||
// (fmt, 5)
|
||||
// (fmt)
|
||||
// (true)
|
||||
// (true, 5)
|
||||
// (true, fmt, 5)
|
||||
// (true, fmt)
|
||||
function Oc(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=ab(),f=a?e._week.dow:0;if(null!=c)return Mc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;7>g;g++)h[g]=Mc(b,(g+f)%7,d,"day");return h}function Pc(a,b){return Nc(a,b,"months")}function Qc(a,b){return Nc(a,b,"monthsShort")}function Rc(a,b,c){return Oc(a,b,c,"weekdays")}function Sc(a,b,c){return Oc(a,b,c,"weekdaysShort")}function Tc(a,b,c){return Oc(a,b,c,"weekdaysMin")}function Uc(){var a=this._data;return this._milliseconds=Ue(this._milliseconds),this._days=Ue(this._days),this._months=Ue(this._months),a.milliseconds=Ue(a.milliseconds),a.seconds=Ue(a.seconds),a.minutes=Ue(a.minutes),a.hours=Ue(a.hours),a.months=Ue(a.months),a.years=Ue(a.years),this}function Vc(a,b,c,d){var e=Mb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}
|
||||
// supports only 2.0-style add(1, 's') or add(duration)
|
||||
function Wc(a,b){return Vc(this,a,b,1)}
|
||||
// supports only 2.0-style subtract(1, 's') or subtract(duration)
|
||||
function Xc(a,b){return Vc(this,a,b,-1)}function Yc(a){return 0>a?Math.floor(a):Math.ceil(a)}function Zc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;
|
||||
// if we have a mix of positive and negative values, bubble down first
|
||||
// check: https://github.com/moment/moment/issues/2166
|
||||
// The following code bubbles up values, see the tests for
|
||||
// examples of what that means.
|
||||
// convert days to months
|
||||
// 12 months -> 1 year
|
||||
return f>=0&&g>=0&&h>=0||0>=f&&0>=g&&0>=h||(f+=864e5*Yc(_c(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=s(f/1e3),i.seconds=a%60,b=s(a/60),i.minutes=b%60,c=s(b/60),i.hours=c%24,g+=s(c/24),e=s($c(g)),h+=e,g-=Yc(_c(e)),d=s(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function $c(a){
|
||||
// 400 years have 146097 days (taking into account leap year rules)
|
||||
// 400 years have 12 months === 4800
|
||||
return 4800*a/146097}function _c(a){
|
||||
// the reverse of daysToMonths
|
||||
return 146097*a/4800}function ad(a){var b,c,d=this._milliseconds;if(a=J(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+$c(b),"month"===a?c:c/12;switch(b=this._days+Math.round(_c(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;
|
||||
// Math.floor prevents floating point math errors here
|
||||
case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}
|
||||
// TODO: Use this.as('ms')?
|
||||
function bd(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*t(this._months/12)}function cd(a){return function(){return this.as(a)}}function dd(a){return a=J(a),this[a+"s"]()}function ed(a){return function(){return this._data[a]}}function fd(){return s(this.days()/7)}
|
||||
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
|
||||
function gd(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function hd(a,b,c){var d=Mb(a).abs(),e=jf(d.as("s")),f=jf(d.as("m")),g=jf(d.as("h")),h=jf(d.as("d")),i=jf(d.as("M")),j=jf(d.as("y")),k=e<kf.s&&["s",e]||1>=f&&["m"]||f<kf.m&&["mm",f]||1>=g&&["h"]||g<kf.h&&["hh",g]||1>=h&&["d"]||h<kf.d&&["dd",h]||1>=i&&["M"]||i<kf.M&&["MM",i]||1>=j&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,gd.apply(null,k)}
|
||||
// This function allows you to set the rounding function for relative time strings
|
||||
function id(a){return void 0===a?jf:"function"==typeof a?(jf=a,!0):!1}
|
||||
// This function allows you to set a threshold for relative time strings
|
||||
function jd(a,b){return void 0===kf[a]?!1:void 0===b?kf[a]:(kf[a]=b,!0)}function kd(a){var b=this.localeData(),c=hd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ld(){
|
||||
// for ISO strings we do not use the normal bubbling rules:
|
||||
// * milliseconds bubble up until they become hours
|
||||
// * days do not bubble at all
|
||||
// * months bubble up until they become years
|
||||
// This is because there is no context-free conversion between hours and days
|
||||
// (think of clock changes)
|
||||
// and also not between days and months (28-31 days per month)
|
||||
var a,b,c,d=lf(this._milliseconds)/1e3,e=lf(this._days),f=lf(this._months);a=s(d/60),b=s(a/60),d%=60,a%=60,c=s(f/12),f%=12;
|
||||
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
|
||||
var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(0>m?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var md,nd;nd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;c>d;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};
|
||||
// Plugins that add properties should also add the key here (null value),
|
||||
// so we can properly clone ourselves.
|
||||
var od=a.momentProperties=[],pd=!1,qd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var rd;rd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)h(a,b)&&c.push(b);return c};var sd,td={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},ud={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},vd="Invalid date",wd="%d",xd=/\d{1,2}/,yd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},zd={},Ad={},Bd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Cd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Dd={},Ed={},Fd=/\d/,Gd=/\d\d/,Hd=/\d{3}/,Id=/\d{4}/,Jd=/[+-]?\d{6}/,Kd=/\d\d?/,Ld=/\d\d\d\d?/,Md=/\d\d\d\d\d\d?/,Nd=/\d{1,3}/,Od=/\d{1,4}/,Pd=/[+-]?\d{1,6}/,Qd=/\d+/,Rd=/[+-]?\d+/,Sd=/Z|[+-]\d\d:?\d\d/gi,Td=/Z|[+-]\d\d(?::?\d\d)?/gi,Ud=/[+-]?\d+(\.\d{1,3})?/,Vd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Wd={},Xd={},Yd=0,Zd=1,$d=2,_d=3,ae=4,be=5,ce=6,de=7,ee=8;sd=Array.prototype.indexOf?Array.prototype.indexOf:function(a){
|
||||
// I know
|
||||
var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},T("M",["MM",2],"Mo",function(){return this.month()+1}),T("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),T("MMMM",0,0,function(a){return this.localeData().months(this,a)}),I("month","M"),L("month",8),Y("M",Kd),Y("MM",Kd,Gd),Y("MMM",function(a,b){return b.monthsShortRegex(a)}),Y("MMMM",function(a,b){return b.monthsRegex(a)}),aa(["M","MM"],function(a,b){b[Zd]=t(a)-1}),aa(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);null!=e?b[Zd]=e:l(c).invalidMonth=a});
|
||||
// LOCALES
|
||||
var fe=/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/,ge="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),he="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),ie=Vd,je=Vd;
|
||||
// FORMATTING
|
||||
T("Y",0,0,function(){var a=this.year();return 9999>=a?""+a:"+"+a}),T(0,["YY",2],0,function(){return this.year()%100}),T(0,["YYYY",4],0,"year"),T(0,["YYYYY",5],0,"year"),T(0,["YYYYYY",6,!0],0,"year"),
|
||||
// ALIASES
|
||||
I("year","y"),
|
||||
// PRIORITIES
|
||||
L("year",1),
|
||||
// PARSING
|
||||
Y("Y",Rd),Y("YY",Kd,Gd),Y("YYYY",Od,Id),Y("YYYYY",Pd,Jd),Y("YYYYYY",Pd,Jd),aa(["YYYYY","YYYYYY"],Yd),aa("YYYY",function(b,c){c[Yd]=2===b.length?a.parseTwoDigitYear(b):t(b)}),aa("YY",function(b,c){c[Yd]=a.parseTwoDigitYear(b)}),aa("Y",function(a,b){b[Yd]=parseInt(a,10)}),
|
||||
// HOOKS
|
||||
a.parseTwoDigitYear=function(a){return t(a)+(t(a)>68?1900:2e3)};
|
||||
// MOMENTS
|
||||
var ke=N("FullYear",!0);
|
||||
// FORMATTING
|
||||
T("w",["ww",2],"wo","week"),T("W",["WW",2],"Wo","isoWeek"),
|
||||
// ALIASES
|
||||
I("week","w"),I("isoWeek","W"),
|
||||
// PRIORITIES
|
||||
L("week",5),L("isoWeek",5),
|
||||
// PARSING
|
||||
Y("w",Kd),Y("ww",Kd,Gd),Y("W",Kd),Y("WW",Kd,Gd),ba(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=t(a)});var le={dow:0,// Sunday is the first day of the week.
|
||||
doy:6};
|
||||
// FORMATTING
|
||||
T("d",0,"do","day"),T("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),T("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),T("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),T("e",0,0,"weekday"),T("E",0,0,"isoWeekday"),
|
||||
// ALIASES
|
||||
I("day","d"),I("weekday","e"),I("isoWeekday","E"),
|
||||
// PRIORITY
|
||||
L("day",11),L("weekday",11),L("isoWeekday",11),
|
||||
// PARSING
|
||||
Y("d",Kd),Y("e",Kd),Y("E",Kd),Y("dd",function(a,b){return b.weekdaysMinRegex(a)}),Y("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Y("dddd",function(a,b){return b.weekdaysRegex(a)}),ba(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);
|
||||
// if we didn't get a weekday name, mark the date as invalid
|
||||
null!=e?b.d=e:l(c).invalidWeekday=a}),ba(["d","e","E"],function(a,b,c,d){b[d]=t(a)});
|
||||
// LOCALES
|
||||
var me="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),oe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),pe=Vd,qe=Vd,re=Vd;T("H",["HH",2],0,"hour"),T("h",["hh",2],0,Qa),T("k",["kk",2],0,Ra),T("hmm",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)}),T("hmmss",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)+S(this.seconds(),2)}),T("Hmm",0,0,function(){return""+this.hours()+S(this.minutes(),2)}),T("Hmmss",0,0,function(){return""+this.hours()+S(this.minutes(),2)+S(this.seconds(),2)}),Sa("a",!0),Sa("A",!1),
|
||||
// ALIASES
|
||||
I("hour","h"),
|
||||
// PRIORITY
|
||||
L("hour",13),Y("a",Ta),Y("A",Ta),Y("H",Kd),Y("h",Kd),Y("HH",Kd,Gd),Y("hh",Kd,Gd),Y("hmm",Ld),Y("hmmss",Md),Y("Hmm",Ld),Y("Hmmss",Md),aa(["H","HH"],_d),aa(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),aa(["h","hh"],function(a,b,c){b[_d]=t(a),l(c).bigHour=!0}),aa("hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d)),l(c).bigHour=!0}),aa("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e)),l(c).bigHour=!0}),aa("Hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d))}),aa("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e))});var se,te=/[ap]\.?m?\.?/i,ue=N("Hours",!0),ve={calendar:td,longDateFormat:ud,invalidDate:vd,ordinal:wd,ordinalParse:xd,relativeTime:yd,months:ge,monthsShort:he,week:le,weekdays:me,weekdaysMin:oe,weekdaysShort:ne,meridiemParse:te},we={},xe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ye=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ze=/Z|[+-]\d\d(?::?\d\d)?/,Ae=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],
|
||||
// YYYYMM is NOT allowed by the standard
|
||||
["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Be=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ce=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=w("moment construction falls back to js Date. This is discouraged and will be removed in upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),
|
||||
// constant that refers to the ISO standard
|
||||
a.ISO_8601=function(){};var De=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?this>a?this:a:n()}),Ee=w("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:n()}),Fe=function(){return Date.now?Date.now():+new Date};xb("Z",":"),xb("ZZ",""),
|
||||
// PARSING
|
||||
Y("Z",Td),Y("ZZ",Td),aa(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=yb(Td,a)});
|
||||
// HELPERS
|
||||
// timezone chunker
|
||||
// '+10:00' > ['10', '00']
|
||||
// '-1530' > ['-15', '30']
|
||||
var Ge=/([\+\-]|\d\d)/gi;
|
||||
// HOOKS
|
||||
// This function will be called whenever a moment is mutated.
|
||||
// It is intended to keep the offset in sync with the timezone.
|
||||
a.updateOffset=function(){};
|
||||
// ASP.NET json date format regex
|
||||
var He=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/,Ie=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Mb.fn=vb.prototype;var Je=Rb(1,"add"),Ke=Rb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Le=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});
|
||||
// FORMATTING
|
||||
T(0,["gg",2],0,function(){return this.weekYear()%100}),T(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xc("gggg","weekYear"),xc("ggggg","weekYear"),xc("GGGG","isoWeekYear"),xc("GGGGG","isoWeekYear"),
|
||||
// ALIASES
|
||||
I("weekYear","gg"),I("isoWeekYear","GG"),
|
||||
// PRIORITY
|
||||
L("weekYear",1),L("isoWeekYear",1),
|
||||
// PARSING
|
||||
Y("G",Rd),Y("g",Rd),Y("GG",Kd,Gd),Y("gg",Kd,Gd),Y("GGGG",Od,Id),Y("gggg",Od,Id),Y("GGGGG",Pd,Jd),Y("ggggg",Pd,Jd),ba(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=t(a)}),ba(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),
|
||||
// FORMATTING
|
||||
T("Q",0,"Qo","quarter"),
|
||||
// ALIASES
|
||||
I("quarter","Q"),
|
||||
// PRIORITY
|
||||
L("quarter",7),
|
||||
// PARSING
|
||||
Y("Q",Fd),aa("Q",function(a,b){b[Zd]=3*(t(a)-1)}),
|
||||
// FORMATTING
|
||||
T("D",["DD",2],"Do","date"),
|
||||
// ALIASES
|
||||
I("date","D"),
|
||||
// PRIOROITY
|
||||
L("date",9),
|
||||
// PARSING
|
||||
Y("D",Kd),Y("DD",Kd,Gd),Y("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),aa(["D","DD"],$d),aa("Do",function(a,b){b[$d]=t(a.match(Kd)[0],10)});
|
||||
// MOMENTS
|
||||
var Me=N("Date",!0);
|
||||
// FORMATTING
|
||||
T("DDD",["DDDD",3],"DDDo","dayOfYear"),
|
||||
// ALIASES
|
||||
I("dayOfYear","DDD"),
|
||||
// PRIORITY
|
||||
L("dayOfYear",4),
|
||||
// PARSING
|
||||
Y("DDD",Nd),Y("DDDD",Hd),aa(["DDD","DDDD"],function(a,b,c){c._dayOfYear=t(a)}),
|
||||
// FORMATTING
|
||||
T("m",["mm",2],0,"minute"),
|
||||
// ALIASES
|
||||
I("minute","m"),
|
||||
// PRIORITY
|
||||
L("minute",14),
|
||||
// PARSING
|
||||
Y("m",Kd),Y("mm",Kd,Gd),aa(["m","mm"],ae);
|
||||
// MOMENTS
|
||||
var Ne=N("Minutes",!1);
|
||||
// FORMATTING
|
||||
T("s",["ss",2],0,"second"),
|
||||
// ALIASES
|
||||
I("second","s"),
|
||||
// PRIORITY
|
||||
L("second",15),
|
||||
// PARSING
|
||||
Y("s",Kd),Y("ss",Kd,Gd),aa(["s","ss"],be);
|
||||
// MOMENTS
|
||||
var Oe=N("Seconds",!1);
|
||||
// FORMATTING
|
||||
T("S",0,0,function(){return~~(this.millisecond()/100)}),T(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),T(0,["SSS",3],0,"millisecond"),T(0,["SSSS",4],0,function(){return 10*this.millisecond()}),T(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),T(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),T(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),T(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),T(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),
|
||||
// ALIASES
|
||||
I("millisecond","ms"),
|
||||
// PRIORITY
|
||||
L("millisecond",16),
|
||||
// PARSING
|
||||
Y("S",Nd,Fd),Y("SS",Nd,Gd),Y("SSS",Nd,Hd);var Pe;for(Pe="SSSS";Pe.length<=9;Pe+="S")Y(Pe,Qd);for(Pe="S";Pe.length<=9;Pe+="S")aa(Pe,Gc);
|
||||
// MOMENTS
|
||||
var Qe=N("Milliseconds",!1);
|
||||
// FORMATTING
|
||||
T("z",0,0,"zoneAbbr"),T("zz",0,0,"zoneName");var Re=q.prototype;Re.add=Je,Re.calendar=Ub,Re.clone=Vb,Re.diff=ac,Re.endOf=mc,Re.format=ec,Re.from=fc,Re.fromNow=gc,Re.to=hc,Re.toNow=ic,Re.get=Q,Re.invalidAt=vc,Re.isAfter=Wb,Re.isBefore=Xb,Re.isBetween=Yb,Re.isSame=Zb,Re.isSameOrAfter=$b,Re.isSameOrBefore=_b,Re.isValid=tc,Re.lang=Le,Re.locale=jc,Re.localeData=kc,Re.max=Ee,Re.min=De,Re.parsingFlags=uc,Re.set=R,Re.startOf=lc,Re.subtract=Ke,Re.toArray=qc,Re.toObject=rc,Re.toDate=pc,Re.toISOString=dc,Re.toJSON=sc,Re.toString=cc,Re.unix=oc,Re.valueOf=nc,Re.creationData=wc,
|
||||
// Year
|
||||
Re.year=ke,Re.isLeapYear=qa,
|
||||
// Week Year
|
||||
Re.weekYear=yc,Re.isoWeekYear=zc,
|
||||
// Quarter
|
||||
Re.quarter=Re.quarters=Ec,
|
||||
// Month
|
||||
Re.month=ja,Re.daysInMonth=ka,
|
||||
// Week
|
||||
Re.week=Re.weeks=Aa,Re.isoWeek=Re.isoWeeks=Ba,Re.weeksInYear=Bc,Re.isoWeeksInYear=Ac,
|
||||
// Day
|
||||
Re.date=Me,Re.day=Re.days=Ja,Re.weekday=Ka,Re.isoWeekday=La,Re.dayOfYear=Fc,
|
||||
// Hour
|
||||
Re.hour=Re.hours=ue,
|
||||
// Minute
|
||||
Re.minute=Re.minutes=Ne,
|
||||
// Second
|
||||
Re.second=Re.seconds=Oe,
|
||||
// Millisecond
|
||||
Re.millisecond=Re.milliseconds=Qe,
|
||||
// Offset
|
||||
Re.utcOffset=Bb,Re.utc=Db,Re.local=Eb,Re.parseZone=Fb,Re.hasAlignedHourOffset=Gb,Re.isDST=Hb,Re.isLocal=Jb,Re.isUtcOffset=Kb,Re.isUtc=Lb,Re.isUTC=Lb,
|
||||
// Timezone
|
||||
Re.zoneAbbr=Hc,Re.zoneName=Ic,
|
||||
// Deprecations
|
||||
Re.dates=w("dates accessor is deprecated. Use date instead.",Me),Re.months=w("months accessor is deprecated. Use month instead",ja),Re.years=w("years accessor is deprecated. Use year instead",ke),Re.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Cb),Re.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Ib);var Se=Re,Te=B.prototype;Te.calendar=C,Te.longDateFormat=D,Te.invalidDate=E,Te.ordinal=F,Te.preparse=Lc,Te.postformat=Lc,Te.relativeTime=G,Te.pastFuture=H,Te.set=z,
|
||||
// Month
|
||||
Te.months=ea,Te.monthsShort=fa,Te.monthsParse=ha,Te.monthsRegex=ma,Te.monthsShortRegex=la,
|
||||
// Week
|
||||
Te.week=xa,Te.firstDayOfYear=za,Te.firstDayOfWeek=ya,
|
||||
// Day of Week
|
||||
Te.weekdays=Ea,Te.weekdaysMin=Ga,Te.weekdaysShort=Fa,Te.weekdaysParse=Ia,Te.weekdaysRegex=Ma,Te.weekdaysShortRegex=Na,Te.weekdaysMinRegex=Oa,
|
||||
// Hours
|
||||
Te.isPM=Ua,Te.meridiem=Va,Za("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===t(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),
|
||||
// Side effect imports
|
||||
a.lang=w("moment.lang is deprecated. Use moment.locale instead.",Za),a.langData=w("moment.langData is deprecated. Use moment.localeData instead.",ab);var Ue=Math.abs,Ve=cd("ms"),We=cd("s"),Xe=cd("m"),Ye=cd("h"),Ze=cd("d"),$e=cd("w"),_e=cd("M"),af=cd("y"),bf=ed("milliseconds"),cf=ed("seconds"),df=ed("minutes"),ef=ed("hours"),ff=ed("days"),gf=ed("months"),hf=ed("years"),jf=Math.round,kf={s:45,// seconds to minute
|
||||
m:45,// minutes to hour
|
||||
h:22,// hours to day
|
||||
d:26,// days to month
|
||||
M:11},lf=Math.abs,mf=vb.prototype;mf.abs=Uc,mf.add=Wc,mf.subtract=Xc,mf.as=ad,mf.asMilliseconds=Ve,mf.asSeconds=We,mf.asMinutes=Xe,mf.asHours=Ye,mf.asDays=Ze,mf.asWeeks=$e,mf.asMonths=_e,mf.asYears=af,mf.valueOf=bd,mf._bubble=Zc,mf.get=dd,mf.milliseconds=bf,mf.seconds=cf,mf.minutes=df,mf.hours=ef,mf.days=ff,mf.weeks=fd,mf.months=gf,mf.years=hf,mf.humanize=kd,mf.toISOString=ld,mf.toString=ld,mf.toJSON=ld,mf.locale=jc,mf.localeData=kc,
|
||||
// Deprecations
|
||||
mf.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ld),mf.lang=Le,
|
||||
// Side effect imports
|
||||
// FORMATTING
|
||||
T("X",0,0,"unix"),T("x",0,0,"valueOf"),
|
||||
// PARSING
|
||||
Y("x",Rd),Y("X",Ud),aa("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),aa("x",function(a,b,c){c._d=new Date(t(a))}),
|
||||
// Side effect imports
|
||||
a.version="2.14.1",b(rb),a.fn=Se,a.min=tb,a.max=ub,a.now=Fe,a.utc=j,a.unix=Jc,a.months=Pc,a.isDate=f,a.locale=Za,a.invalid=n,a.duration=Mb,a.isMoment=r,a.weekdays=Rc,a.parseZone=Kc,a.localeData=ab,a.isDuration=wb,a.monthsShort=Qc,a.weekdaysMin=Tc,a.defineLocale=$a,a.updateLocale=_a,a.locales=bb,a.weekdaysShort=Sc,a.normalizeUnits=J,a.relativeTimeRounding=id,a.relativeTimeThreshold=jd,a.calendarFormat=Tb,a.prototype=Se;var nf=a;return nf});
|
||||
@@ -1,3 +0,0 @@
|
||||
/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){var b=function(){if(a&&a.fn&&a.fn.select2&&a.fn.select2.amd)var b=a.fn.select2.amd;var b;return function(){if(!b||!b.requirejs){b?c=b:b={};var a,c,d;!function(b){function e(a,b){return u.call(a,b)}function f(a,b){var c,d,e,f,g,h,i,j,k,l,m,n=b&&b.split("/"),o=s.map,p=o&&o["*"]||{};if(a&&"."===a.charAt(0))if(b){for(a=a.split("/"),g=a.length-1,s.nodeIdCompat&&w.test(a[g])&&(a[g]=a[g].replace(w,"")),a=n.slice(0,n.length-1).concat(a),k=0;k<a.length;k+=1)if(m=a[k],"."===m)a.splice(k,1),k-=1;else if(".."===m){if(1===k&&(".."===a[2]||".."===a[0]))break;k>0&&(a.splice(k-1,2),k-=2)}a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if((n||p)&&o){for(c=a.split("/"),k=c.length;k>0;k-=1){if(d=c.slice(0,k).join("/"),n)for(l=n.length;l>0;l-=1)if(e=o[n.slice(0,l).join("/")],e&&(e=e[d])){f=e,h=k;break}if(f)break;!i&&p&&p[d]&&(i=p[d],j=k)}!f&&i&&(f=i,h=j),f&&(c.splice(0,h,f),a=c.join("/"))}return a}function g(a,c){return function(){var d=v.call(arguments,0);return"string"!=typeof d[0]&&1===d.length&&d.push(null),n.apply(b,d.concat([a,c]))}}function h(a){return function(b){return f(b,a)}}function i(a){return function(b){q[a]=b}}function j(a){if(e(r,a)){var c=r[a];delete r[a],t[a]=!0,m.apply(b,c)}if(!e(q,a)&&!e(t,a))throw new Error("No "+a);return q[a]}function k(a){var b,c=a?a.indexOf("!"):-1;return c>-1&&(b=a.substring(0,c),a=a.substring(c+1,a.length)),[b,a]}function l(a){return function(){return s&&s.config&&s.config[a]||{}}}var m,n,o,p,q={},r={},s={},t={},u=Object.prototype.hasOwnProperty,v=[].slice,w=/\.js$/;o=function(a,b){var c,d=k(a),e=d[0];return a=d[1],e&&(e=f(e,b),c=j(e)),e?a=c&&c.normalize?c.normalize(a,h(b)):f(a,b):(a=f(a,b),d=k(a),e=d[0],a=d[1],e&&(c=j(e))),{f:e?e+"!"+a:a,n:a,pr:e,p:c}},p={require:function(a){return g(a)},exports:function(a){var b=q[a];return"undefined"!=typeof b?b:q[a]={}},module:function(a){return{id:a,uri:"",exports:q[a],config:l(a)}}},m=function(a,c,d,f){var h,k,l,m,n,s,u=[],v=typeof d;if(f=f||a,"undefined"===v||"function"===v){for(c=!c.length&&d.length?["require","exports","module"]:c,n=0;n<c.length;n+=1)if(m=o(c[n],f),k=m.f,"require"===k)u[n]=p.require(a);else if("exports"===k)u[n]=p.exports(a),s=!0;else if("module"===k)h=u[n]=p.module(a);else if(e(q,k)||e(r,k)||e(t,k))u[n]=j(k);else{if(!m.p)throw new Error(a+" missing "+k);m.p.load(m.n,g(f,!0),i(k),{}),u[n]=q[k]}l=d?d.apply(q[a],u):void 0,a&&(h&&h.exports!==b&&h.exports!==q[a]?q[a]=h.exports:l===b&&s||(q[a]=l))}else a&&(q[a]=d)},a=c=n=function(a,c,d,e,f){if("string"==typeof a)return p[a]?p[a](c):j(o(a,c).f);if(!a.splice){if(s=a,s.deps&&n(s.deps,s.callback),!c)return;c.splice?(a=c,c=d,d=null):a=b}return c=c||function(){},"function"==typeof d&&(d=e,e=f),e?m(b,a,c,d):setTimeout(function(){m(b,a,c,d)},4),n},n.config=function(a){return n(a)},a._defined=q,d=function(a,b,c){if("string"!=typeof a)throw new Error("See almond README: incorrect module build, no module name");b.splice||(c=b,b=[]),e(q,a)||e(r,a)||(r[a]=[a,b,c])},d.amd={jQuery:!0}}(),b.requirejs=a,b.require=c,b.define=d}}(),b.define("almond",function(){}),b.define("jquery",[],function(){var b=a||$;return null==b&&console&&console.error&&console.error("Select2: An instance of jQuery or a jQuery-compatible library was not found. Make sure that you are including jQuery before Select2 on your web page."),b}),b.define("select2/utils",["jquery"],function(a){function b(a){var b=a.prototype,c=[];for(var d in b){var e=b[d];"function"==typeof e&&"constructor"!==d&&c.push(d)}return c}var c={};c.Extend=function(a,b){function c(){this.constructor=a}var d={}.hasOwnProperty;for(var e in b)d.call(b,e)&&(a[e]=b[e]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a},c.Decorate=function(a,c){function d(){var b=Array.prototype.unshift,d=c.prototype.constructor.length,e=a.prototype.constructor;d>0&&(b.call(arguments,a.prototype.constructor),e=c.prototype.constructor),e.apply(this,arguments)}function e(){this.constructor=d}var f=b(c),g=b(a);c.displayName=a.displayName,d.prototype=new e;for(var h=0;h<g.length;h++){var i=g[h];d.prototype[i]=a.prototype[i]}for(var j=(function(a){var b=function(){};a in d.prototype&&(b=d.prototype[a]);var e=c.prototype[a];return function(){var a=Array.prototype.unshift;return a.call(arguments,b),e.apply(this,arguments)}}),k=0;k<f.length;k++){var l=f[k];d.prototype[l]=j(l)}return d};var d=function(){this.listeners={}};return d.prototype.on=function(a,b){this.listeners=this.listeners||{},a in this.listeners?this.listeners[a].push(b):this.listeners[a]=[b]},d.prototype.trigger=function(a){var b=Array.prototype.slice,c=b.call(arguments,1);this.listeners=this.listeners||{},null==c&&(c=[]),0===c.length&&c.push({}),c[0]._type=a,a in this.listeners&&this.invoke(this.listeners[a],b.call(arguments,1)),"*"in this.listeners&&this.invoke(this.liLine truncated
|
||||
if(this.$element.prop("multiple"))this.current(function(d){var e=[];a=[a],a.push.apply(a,d);for(var f=0;f<a.length;f++){var g=a[f].id;-1===c.inArray(g,e)&&e.push(g)}b.$element.val(e),b.$element.trigger("change")});else{var d=a.id;this.$element.val(d),this.$element.trigger("change")}},d.prototype.unselect=function(a){var b=this;if(this.$element.prop("multiple"))return a.selected=!1,c(a.element).is("option")?(a.element.selected=!1,void this.$element.trigger("change")):void this.current(function(d){for(var e=[],f=0;f<d.length;f++){var g=d[f].id;g!==a.id&&-1===c.inArray(g,e)&&e.push(g)}b.$element.val(e),b.$element.trigger("change")})},d.prototype.bind=function(a,b){var c=this;this.container=a,a.on("select",function(a){c.select(a.data)}),a.on("unselect",function(a){c.unselect(a.data)})},d.prototype.destroy=function(){this.$element.find("*").each(function(){c.removeData(this,"data")})},d.prototype.query=function(a,b){var d=[],e=this,f=this.$element.children();f.each(function(){var b=c(this);if(b.is("option")||b.is("optgroup")){var f=e.item(b),g=e.matches(a,f);null!==g&&d.push(g)}}),b({results:d})},d.prototype.addOptions=function(a){b.appendMany(this.$element,a)},d.prototype.option=function(a){var b;a.children?(b=document.createElement("optgroup"),b.label=a.text):(b=document.createElement("option"),void 0!==b.textContent?b.textContent=a.text:b.innerText=a.text),a.id&&(b.value=a.id),a.disabled&&(b.disabled=!0),a.selected&&(b.selected=!0),a.title&&(b.title=a.title);var d=c(b),e=this._normalizeItem(a);return e.element=b,c.data(b,"data",e),d},d.prototype.item=function(a){var b={};if(b=c.data(a[0],"data"),null!=b)return b;if(a.is("option"))b={id:a.val(),text:a.text(),disabled:a.prop("disabled"),selected:a.prop("selected"),title:a.prop("title")};else if(a.is("optgroup")){b={text:a.prop("label"),children:[],title:a.prop("title")};for(var d=a.children("option"),e=[],f=0;f<d.length;f++){var g=c(d[f]),h=this.item(g);e.push(h)}b.children=e}return b=this._normalizeItem(b),b.element=a[0],c.data(a[0],"data",b),b},d.prototype._normalizeItem=function(a){c.isPlainObject(a)||(a={id:a,text:a}),a=c.extend({},{text:""},a);var b={selected:!1,disabled:!1};return null!=a.id&&(a.id=a.id.toString()),null!=a.text&&(a.text=a.text.toString()),null==a._resultId&&a.id&&null!=this.container&&(a._resultId=this.generateResultId(this.container,a)),c.extend({},b,a)},d.prototype.matches=function(a,b){var c=this.options.get("matcher");return c(a,b)},d}),b.define("select2/data/array",["./select","../utils","jquery"],function(a,b,c){function d(a,b){var c=b.get("data")||[];d.__super__.constructor.call(this,a,b),this.addOptions(this.convertToOptions(c))}return b.Extend(d,a),d.prototype.select=function(a){var b=this.$element.find("option").filter(function(b,c){return c.value==a.id.toString()});0===b.length&&(b=this.option(a),this.addOptions(b)),d.__super__.select.call(this,a)},d.prototype.convertToOptions=function(a){function d(a){return function(){return c(this).val()==a.id}}for(var e=this,f=this.$element.find("option"),g=f.map(function(){return e.item(c(this)).id}).get(),h=[],i=0;i<a.length;i++){var j=this._normalizeItem(a[i]);if(c.inArray(j.id,g)>=0){var k=f.filter(d(j)),l=this.item(k),m=c.extend(!0,{},j,l),n=this.option(m);k.replaceWith(n)}else{var o=this.option(j);if(j.children){var p=this.convertToOptions(j.children);b.appendMany(o,p)}h.push(o)}}return h},d}),b.define("select2/data/ajax",["./array","../utils","jquery"],function(a,b,c){function d(a,b){this.ajaxOptions=this._applyDefaults(b.get("ajax")),null!=this.ajaxOptions.processResults&&(this.processResults=this.ajaxOptions.processResults),d.__super__.constructor.call(this,a,b)}return b.Extend(d,a),d.prototype._applyDefaults=function(a){var b={data:function(a){return c.extend({},a,{q:a.term})},transport:function(a,b,d){var e=c.ajax(a);return e.then(b),e.fail(d),e}};return c.extend({},b,a,!0)},d.prototype.processResults=function(a){return a},d.prototype.query=function(a,b){function d(){var d=f.transport(f,function(d){var f=e.processResults(d,a);e.options.get("debug")&&window.console&&console.error&&(f&&f.results&&c.isArray(f.results)||console.error("Select2: The AJAX results did not return an array in the `results` key of the response.")),b(f)},function(){d.status&&"0"===d.status||e.trigger("results:message",{message:"errorLoading"})});e._request=d}var e=this;null!=this._request&&(c.isFunction(this._request.abort)&&this._request.abort(),this._request=null);var f=c.extend({type:"GET"},this.ajaxOptions);"function"==typeof f.url&&(f.url=f.url.call(this.$element,a)),"function"==typeof f.data&&(f.data=f.data.call(this.$element,a)),this.ajaxOptions.delay&&null!=a.term?(this._queryTimeout&&window.clearTimeout(this._queryTimeout),this._queryTimeout=window.setTimeout(d,this.ajaxOptions.delay)):d()},d}),b.define("select2/data/tags",["jquery"],function(a){function b(b,c,d){var e=d.get("tags"),f=d.get("createTag");void 0!==f&&(this.createTag=f);var g=d.get("insertTag");if(void 0!==g&&(this.insertTag=g),b.callLine truncated
|
||||
},e.prototype.render=function(){var b=a('<span class="select2 select2-container"><span class="selection"></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>');return b.attr("dir",this.options.get("dir")),this.$container=b,this.$container.addClass("select2-container--"+this.options.get("theme")),b.data("element",this.$element),b},e}),b.define("jquery-mousewheel",["jquery"],function(a){return a}),b.define("jquery.select2",["jquery","jquery-mousewheel","./select2/core","./select2/defaults"],function(a,b,c,d){if(null==a.fn.select2){var e=["open","close","destroy"];a.fn.select2=function(b){if(b=b||{},"object"==typeof b)return this.each(function(){var d=a.extend(!0,{},b);new c(a(this),d)}),this;if("string"==typeof b){var d,f=Array.prototype.slice.call(arguments,1);return this.each(function(){var c=a(this).data("select2");null==c&&window.console&&console.error&&console.error("The select2('"+b+"') method was called on an element that is not using Select2."),d=c[b].apply(c,f)}),a.inArray(b,e)>-1?this:d}throw new Error("Invalid arguments for Select2: "+b)}}return null==a.fn.select2.defaults&&(a.fn.select2.defaults=d),c}),{define:b.define,require:b.require}}(),c=b.require("jquery.select2");return a.fn.select2.amd=b,c});
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: Simple Calendar
|
||||
* Plugin URI: https://simplecalendar.io
|
||||
* Description: Add Google Calendar events to your WordPress site in minutes. Beautiful calendar displays. Fully responsive.
|
||||
* Author: Moonstone Media
|
||||
* Author URI: https://simplecalendar.io
|
||||
* Version: 3.1.2
|
||||
* Text Domain: google-calendar-events
|
||||
* Domain Path: /i18n
|
||||
*
|
||||
* @copyright 2015-2016 Moonstone Media/Phil Derksen. All rights reserved.
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Plugin constants.
|
||||
$this_plugin_path = trailingslashit( dirname( __FILE__ ) );
|
||||
$this_plugin_dir = plugin_dir_url( __FILE__ );
|
||||
$this_plugin_constants = array(
|
||||
'SIMPLE_CALENDAR_VERSION' => '3.1.2',
|
||||
'SIMPLE_CALENDAR_MAIN_FILE' => __FILE__,
|
||||
'SIMPLE_CALENDAR_URL' => $this_plugin_dir,
|
||||
'SIMPLE_CALENDAR_ASSETS' => $this_plugin_dir . 'assets/',
|
||||
'SIMPLE_CALENDAR_PATH' => $this_plugin_path,
|
||||
'SIMPLE_CALENDAR_INC' => $this_plugin_path . 'includes/',
|
||||
);
|
||||
foreach ( $this_plugin_constants as $constant => $value ) {
|
||||
if ( ! defined( $constant ) ) {
|
||||
define( $constant, $value );
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin requirements
|
||||
|
||||
include_once 'includes/wp-requirements.php';
|
||||
|
||||
// Check plugin requirements before loading plugin.
|
||||
$this_plugin_checks = new SimCal_WP_Requirements( 'Simple Calendar', plugin_basename( __FILE__ ), array(
|
||||
'PHP' => '5.3.3',
|
||||
'WordPress' => '4.1',
|
||||
'Extensions' => array(
|
||||
'curl',
|
||||
'iconv',
|
||||
'json',
|
||||
'mbstring',
|
||||
),
|
||||
) );
|
||||
if ( $this_plugin_checks->pass() === false ) {
|
||||
$this_plugin_checks->halt();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
include_once 'vendor/autoload.php';
|
||||
|
||||
// Load plugin.
|
||||
include_once 'includes/main.php';
|
||||
@@ -1,11 +0,0 @@
|
||||
Interested in translating Simple Calendar to your language? Please use our WordPress.org translation page using a free account.
|
||||
|
||||
https://translate.wordpress.org/projects/wp-plugins/google-calendar-events
|
||||
|
||||
New to translating WordPress? Read through the Translator Handbook to get started.
|
||||
|
||||
https://make.wordpress.org/polyglots/handbook/tools/glotpress-translate-wordpress-org/
|
||||
|
||||
It is no longer necessary to generate and translate .po and .mo files manually. If you want to become a translation editor for your language please get in touch.
|
||||
|
||||
Thank you!
|
||||
@@ -1,195 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Settings Page
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Admin Page.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
abstract class Admin_Page {
|
||||
|
||||
/**
|
||||
* Admin page ID.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $id = '';
|
||||
|
||||
/**
|
||||
* Option group.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $option_group = '';
|
||||
|
||||
/**
|
||||
* Admin Page label.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $label = '';
|
||||
|
||||
/**
|
||||
* Admin Page description.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $description = '';
|
||||
|
||||
/**
|
||||
* Amdin Page settings sections.
|
||||
*
|
||||
* @access public
|
||||
* @var array Associative array with section id (key) and section name (value)
|
||||
*/
|
||||
public $sections;
|
||||
|
||||
/**
|
||||
* Admin Page settings fields.
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
public $fields;
|
||||
|
||||
/**
|
||||
* Saved values.
|
||||
*
|
||||
* @access protected
|
||||
* @var array
|
||||
*/
|
||||
protected $values = array();
|
||||
|
||||
/**
|
||||
* Get admin page settings.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_settings() {
|
||||
|
||||
$settings = array();
|
||||
|
||||
$settings[ $this->id ] = array(
|
||||
'label' => $this->label,
|
||||
'description' => $this->description,
|
||||
);
|
||||
|
||||
if ( ! empty( $this->sections ) && is_array( $this->sections ) ) {
|
||||
|
||||
foreach ( $this->sections as $section => $content ) {
|
||||
|
||||
$settings[ $this->id ]['sections'][ $section ] = array(
|
||||
'title' => isset( $content['title'] ) ? $content['title'] : '',
|
||||
'description' => isset( $content['description'] ) ? $content['description'] : '',
|
||||
'callback' => array( $this, 'add_settings_section_callback' ),
|
||||
'fields' => isset( $this->fields[ $section ] ) ? $this->fields[ $section ] : '',
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return apply_filters( 'simcal_get_' . $this->option_group . '_' . $this->id , $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get option value.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @param string $section
|
||||
* @param string $setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_option_value( $section, $setting ) {
|
||||
|
||||
$option = $this->values;
|
||||
|
||||
if ( ! empty( $option ) && is_array( $option ) ) {
|
||||
return isset( $option[ $section ][ $setting ] ) ? $option[ $section ][ $setting ] : '';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add sections for this page.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function add_sections();
|
||||
|
||||
/**
|
||||
* Get settings fields.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function add_fields();
|
||||
|
||||
/**
|
||||
* Default basic callback for page sections.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $section
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add_settings_section_callback( $section ) {
|
||||
|
||||
$callback = isset( $section['callback'][0] ) ? $section['callback'][0] : '';
|
||||
$sections = isset( $callback->sections ) ? $callback->sections : '';
|
||||
$description = isset( $sections[ $section['id'] ]['description'] ) ? $sections[ $section['id'] ]['description'] : '';
|
||||
$default = $description ? '<p>' . $description . '</p>' : '';
|
||||
|
||||
echo apply_filters( 'simcal_' . $this->option_group . '_' . $this->id . '_sections_callback', $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register setting callback.
|
||||
*
|
||||
* Callback function for sanitizing and validating options before they are updated.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $settings Settings inputs.
|
||||
*
|
||||
* @return array Sanitized settings.
|
||||
*/
|
||||
public function validate( $settings ) {
|
||||
|
||||
$sanitized = '';
|
||||
|
||||
if ( is_array( $settings ) ) {
|
||||
foreach ( $settings as $k => $v ) {
|
||||
$sanitized[ $k ] = simcal_sanitize_input( $v );
|
||||
}
|
||||
} else {
|
||||
$sanitized = simcal_sanitize_input( $settings );
|
||||
}
|
||||
|
||||
return $sanitized;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Calendar View
|
||||
*
|
||||
* @package SimpleCalendar/Calendars
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Calendar View.
|
||||
*
|
||||
* An individual view, handling assets and markup, of a specific Calendar.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface Calendar_View {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param mixed $args
|
||||
*/
|
||||
public function __construct( $args = '' );
|
||||
|
||||
/**
|
||||
* Return the parent calendar type.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_parent();
|
||||
|
||||
/**
|
||||
* Return the view type.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_type();
|
||||
|
||||
/**
|
||||
* Return the view name.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name();
|
||||
|
||||
/**
|
||||
* Add ajax actions.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_ajax_actions();
|
||||
|
||||
/**
|
||||
* Scripts.
|
||||
*
|
||||
* Returns the view scripts as associative array.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $min
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function scripts( $min = '' );
|
||||
|
||||
/**
|
||||
* Styles.
|
||||
*
|
||||
* Returns the view styles as associative array.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $min
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function styles( $min = '' );
|
||||
|
||||
/**
|
||||
* Print HTML.
|
||||
*
|
||||
* Echoes the view markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function html();
|
||||
|
||||
}
|
||||
@@ -1,804 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Calendar
|
||||
*
|
||||
* @package SimpleCalendar/Calendars
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use SimpleCalendar\Events\Event;
|
||||
use SimpleCalendar\Events\Event_Builder;
|
||||
use SimpleCalendar\Events\Events;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Calendar.
|
||||
*
|
||||
* Displays events from events feed.
|
||||
*/
|
||||
abstract class Calendar {
|
||||
|
||||
/**
|
||||
* Calendar Id.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $id = 0;
|
||||
|
||||
/**
|
||||
* Calendar post object.
|
||||
*
|
||||
* @access public
|
||||
* @var \WP_Post
|
||||
*/
|
||||
public $post = null;
|
||||
|
||||
/**
|
||||
* Calendar Type.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $type = '';
|
||||
|
||||
/**
|
||||
* Calendar Name.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
/**
|
||||
* Feed type.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $feed = '';
|
||||
|
||||
/**
|
||||
* Calendar start.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $start = 0;
|
||||
|
||||
/**
|
||||
* Calendar end.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $end = 0;
|
||||
|
||||
/**
|
||||
* Static calendar.
|
||||
*
|
||||
* @access public
|
||||
* @var bool
|
||||
*/
|
||||
public $static = false;
|
||||
|
||||
/**
|
||||
* Today.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $today = 0;
|
||||
|
||||
/**
|
||||
* Time now.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $now = 0;
|
||||
|
||||
/**
|
||||
* Timezone offset.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $offset = 0;
|
||||
|
||||
/**
|
||||
* Timezone
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $timezone = 'UTC';
|
||||
|
||||
/**
|
||||
* Site timezone.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $site_timezone = 'UTC';
|
||||
|
||||
/**
|
||||
* Date format.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $date_format = '';
|
||||
|
||||
/**
|
||||
* Time format.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $time_format = '';
|
||||
|
||||
/**
|
||||
* Date-time separator.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $datetime_separator = '@';
|
||||
|
||||
/**
|
||||
* First day of the week.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $week_starts = 0;
|
||||
|
||||
/**
|
||||
* Events to display.
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
public $events = array();
|
||||
|
||||
/**
|
||||
* Errors.
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
protected $errors = array();
|
||||
|
||||
/**
|
||||
* Earliest event.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $earliest_event = 0;
|
||||
|
||||
/**
|
||||
* Latest event.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $latest_event = 0;
|
||||
|
||||
/**
|
||||
* Event builder content.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $events_template = '';
|
||||
|
||||
/**
|
||||
* Calendar Views.
|
||||
*
|
||||
* The calendar available views.
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
public $views = array();
|
||||
|
||||
/**
|
||||
* Calendar View.
|
||||
*
|
||||
* The current view.
|
||||
*
|
||||
* @access public
|
||||
* @var Calendar_View
|
||||
*/
|
||||
public $view = null;
|
||||
|
||||
/**
|
||||
* Calendar settings.
|
||||
*
|
||||
* @access protected
|
||||
* @var array
|
||||
*/
|
||||
protected $settings = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int|object|\WP_Post|Calendar $calendar
|
||||
* @param string $view
|
||||
*/
|
||||
public function __construct( $calendar, $view = '' ) {
|
||||
|
||||
// Set the post object.
|
||||
$this->set_post_object( $calendar );
|
||||
|
||||
if ( ! is_null( $this->post ) ) {
|
||||
|
||||
// Set calendar type and events source.
|
||||
$this->set_taxonomies();
|
||||
|
||||
// Set calendar default datetime properties.
|
||||
$this->set_timezone();
|
||||
$this->set_start_of_week();
|
||||
$this->set_static();
|
||||
|
||||
// Set calendar start.
|
||||
$this->set_start();
|
||||
|
||||
// Set the events template.
|
||||
$this->set_events_template();
|
||||
|
||||
// Get events source data.
|
||||
$feed = simcal_get_feed( $this );
|
||||
if ( $feed instanceof Feed ) {
|
||||
if ( ! empty( $feed->events ) ) {
|
||||
if ( is_array( $feed->events ) ) {
|
||||
$this->set_events( $feed->events );
|
||||
if ( 'use_calendar' == get_post_meta( $this->id, '_feed_timezone_setting', true ) ) {
|
||||
$this->timezone = $feed->timezone;
|
||||
$this->set_start();
|
||||
}
|
||||
} elseif ( is_string( $feed->events ) ) {
|
||||
$this->errors[] = $feed->events;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set general purpose timestamps.
|
||||
$now = Carbon::now( $this->timezone );
|
||||
$this->now = $now->getTimestamp();
|
||||
$this->today = $now->startOfDay()->getTimestamp();
|
||||
$this->offset = $now->getOffset();
|
||||
|
||||
// Set date time formatting.
|
||||
$this->set_date_format();
|
||||
$this->set_time_format();
|
||||
$this->set_datetime_separator();
|
||||
|
||||
// Set earliest and latest event timestamps.
|
||||
if ( $this->events && is_array( $this->events ) ) {
|
||||
$this->earliest_event = intval( current( array_keys( $this->events ) ) );
|
||||
$this->latest_event = intval( key( array_slice( $this->events, -1, 1, true ) ) );
|
||||
}
|
||||
|
||||
// Set calendar end.
|
||||
$this->set_end();
|
||||
|
||||
// Set view.
|
||||
if ( ! $view ) {
|
||||
|
||||
$calendar_view = get_post_meta( $this->id, '_calendar_view', true );
|
||||
$calendar_view = isset( $calendar_view[ $this->type ] ) ? $calendar_view[ $this->type ] : '';
|
||||
|
||||
$view = esc_attr( $calendar_view );
|
||||
}
|
||||
}
|
||||
|
||||
// Get view.
|
||||
$this->view = $this->get_view( $view );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloading __isset function with post meta.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param mixed $key Post meta key.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset( $key ) {
|
||||
return metadata_exists( 'post', $this->id, '_' . $key );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloading __get function with post meta.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $key Post meta key.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get( $key ) {
|
||||
$value = get_post_meta( $this->id, '_' . $key, true );
|
||||
if ( ! empty( $value ) ) {
|
||||
$this->$key = $value;
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set post object and id.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int|object|\WP_Post|Calendar $calendar
|
||||
*/
|
||||
public function set_post_object( $calendar ) {
|
||||
if ( is_numeric( $calendar ) ) {
|
||||
$this->id = absint( $calendar );
|
||||
$this->post = get_post( $this->id );
|
||||
} elseif ( $calendar instanceof Calendar ) {
|
||||
$this->id = absint( $calendar->id );
|
||||
$this->post = $calendar->post;
|
||||
} elseif ( $calendar instanceof \WP_Post ) {
|
||||
$this->id = absint( $calendar->ID );
|
||||
$this->post = $calendar;
|
||||
} elseif ( isset( $calendar->id ) && isset( $calendar->post ) ) {
|
||||
$this->id = $calendar->id;
|
||||
$this->post = $calendar->post;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calendar title.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
$title = isset( $this->post->post_title ) ? $this->post->post_title : '';
|
||||
return apply_filters( 'simcal_calendar_title', $title );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the calendar post data.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return \WP_Post
|
||||
*/
|
||||
public function get_post_data() {
|
||||
return $this->post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set taxonomies.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function set_taxonomies() {
|
||||
// Set calendar type.
|
||||
if ( $type = wp_get_object_terms( $this->id, 'calendar_type' ) ) {
|
||||
$this->type = sanitize_title( current( $type )->name );
|
||||
} else {
|
||||
$this->type = apply_filters( 'simcal_calendar_default_type', 'default-calendar' );
|
||||
}
|
||||
// Set feed type.
|
||||
if ( $feed_type = wp_get_object_terms( $this->id, 'calendar_feed' ) ) {
|
||||
$this->feed = sanitize_title( current( $feed_type )->name );
|
||||
} else {
|
||||
$this->feed = apply_filters( 'simcal_calendar_default_feed', 'google' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get events.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return Events
|
||||
*/
|
||||
public function get_events() {
|
||||
return new Events( $this->events, $this->timezone );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set events.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $array
|
||||
*/
|
||||
public function set_events( array $array ) {
|
||||
|
||||
$events = array();
|
||||
|
||||
if ( ! empty( $array ) ) {
|
||||
foreach ( $array as $tz => $e ) {
|
||||
foreach ( $e as $event ) {
|
||||
$events[ $tz ][] = $event instanceof Event ? $event : new Event( $event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->events = $events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event builder template.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function set_events_template( $template = '' ) {
|
||||
if ( empty( $template ) ) {
|
||||
$template = isset( $this->post->post_content ) ? $this->post->post_content : '';
|
||||
}
|
||||
|
||||
// TODO: Removed wpautop() call.
|
||||
|
||||
$event_formatting = get_post_meta( $this->id, '_event_formatting', true );
|
||||
|
||||
switch( $event_formatting ) {
|
||||
case 'none':
|
||||
$this->events_template = wp_kses_post( trim( $template ) );
|
||||
break;
|
||||
case 'no_linebreaks':
|
||||
$this->events_template = wpautop( wp_kses_post( trim( $template ) ), false );
|
||||
break;
|
||||
default:
|
||||
$this->events_template = wpautop( wp_kses_post( trim( $template ) ), true );
|
||||
}
|
||||
|
||||
//$this->events_template = wpautop( wp_kses_post( trim( $template ) ), true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the timezone.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $tz Timezone.
|
||||
*/
|
||||
public function set_timezone( $tz = '' ) {
|
||||
|
||||
$site_tz = esc_attr( simcal_get_wp_timezone() );
|
||||
|
||||
if ( $this->feed === 'grouped-calendars' ) {
|
||||
$this->timezone = $site_tz;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( empty( $tz ) ) {
|
||||
|
||||
$timezone_setting = get_post_meta( $this->id, '_feed_timezone_setting', true );
|
||||
|
||||
if ( 'use_site' == $timezone_setting ) {
|
||||
$tz = $site_tz;
|
||||
} elseif ( 'use_custom' == $timezone_setting ) {
|
||||
$custom_timezone = esc_attr( get_post_meta( $this->id, '_feed_timezone', true ) );
|
||||
// One may be using a non standard timezone in GMT (UTC) offset format.
|
||||
if ( ( strpos( $custom_timezone, 'UTC+' ) === 0 ) || ( strpos( $custom_timezone, 'UTC-' ) === 0 ) ) {
|
||||
$tz = simcal_get_timezone_from_gmt_offset( substr( $custom_timezone, 3 ) );
|
||||
} else {
|
||||
$tz = ! empty( $custom_timezone ) ? $custom_timezone : 'UTC';
|
||||
}
|
||||
}
|
||||
|
||||
$this->timezone = empty( $tz ) ? 'UTC' : $tz;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->site_timezone = $site_tz;
|
||||
$this->timezone = simcal_esc_timezone( $tz, $this->timezone );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set date format.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $format PHP datetime format.
|
||||
*/
|
||||
public function set_date_format( $format = '' ) {
|
||||
|
||||
$date_format_custom = $date_format_default = $format;
|
||||
|
||||
if ( empty( $date_format_custom ) ) {
|
||||
|
||||
$date_format_option = esc_attr( get_post_meta( $this->id, '_calendar_date_format_setting', true ) );
|
||||
$date_format_default = esc_attr( get_option( 'date_format' ) );
|
||||
$date_format_custom = '';
|
||||
|
||||
if ( 'use_custom' == $date_format_option ) {
|
||||
$date_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_date_format', true ) );
|
||||
} elseif ( 'use_custom_php' == $date_format_option ) {
|
||||
$date_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_date_format_php', true ) );
|
||||
}
|
||||
}
|
||||
|
||||
$this->date_format = $date_format_custom ? $date_format_custom : $date_format_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time format.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $format PHP datetime format.
|
||||
*/
|
||||
public function set_time_format( $format = '' ) {
|
||||
|
||||
$time_format_custom = $time_format_default = $format;
|
||||
|
||||
if ( empty( $time_format_custom ) ) {
|
||||
|
||||
$time_format_option = esc_attr( get_post_meta( $this->id, '_calendar_time_format_setting', true ) );
|
||||
$time_format_default = esc_attr( get_option( 'time_format' ) );
|
||||
$time_format_custom = '';
|
||||
|
||||
if ( 'use_custom' == $time_format_option ) {
|
||||
$time_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_time_format', true ) );
|
||||
} elseif ( 'use_custom_php' == $time_format_option ) {
|
||||
$time_format_custom = esc_attr( get_post_meta( $this->id, '_calendar_time_format_php', true ) );
|
||||
}
|
||||
}
|
||||
|
||||
$this->time_format = $time_format_custom ? $time_format_custom : $time_format_default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set date-time separator.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $separator A UTF8 character used as separator.
|
||||
*/
|
||||
public function set_datetime_separator( $separator = '' ) {
|
||||
|
||||
if ( empty( $separator ) ) {
|
||||
$separator = get_post_meta( $this->id, '_calendar_datetime_separator', true );
|
||||
}
|
||||
|
||||
$this->datetime_separator = esc_attr( $separator );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set start of week.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $weekday From 0 (Sunday) to 6 (Friday).
|
||||
*/
|
||||
public function set_start_of_week( $weekday = -1 ) {
|
||||
|
||||
$week_starts = is_int( $weekday ) ? $weekday : -1;
|
||||
|
||||
if ( $week_starts < 0 || $week_starts > 6 ) {
|
||||
|
||||
$week_starts_setting = get_post_meta( $this->id, '_calendar_week_starts_on_setting', true );
|
||||
$week_starts = intval( get_option( 'start_of_week' ) );
|
||||
|
||||
if ( 'use_custom' == $week_starts_setting ) {
|
||||
$week_starts_on = get_post_meta( $this->id, '_calendar_week_starts_on', true );
|
||||
$week_starts = is_numeric( $week_starts_on ) ? intval( $week_starts_on ) : $week_starts;
|
||||
}
|
||||
}
|
||||
|
||||
$this->week_starts = $week_starts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set calendar start.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $timestamp
|
||||
*/
|
||||
public function set_start( $timestamp = 0 ) {
|
||||
|
||||
if ( is_int( $timestamp ) && $timestamp !== 0 ) {
|
||||
$this->start = $timestamp;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->start = Carbon::now( $this->timezone )->getTimestamp();
|
||||
|
||||
$calendar_begins = esc_attr( get_post_meta( $this->id, '_calendar_begins', true ) );
|
||||
$nth = max( absint( get_post_meta( $this->id, '_calendar_begins_nth', true ) ), 1 );
|
||||
|
||||
if ( 'today' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->getTimestamp();
|
||||
} elseif ( 'days_before' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->subDays( $nth )->getTimestamp();
|
||||
} elseif ( 'days_after' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->addDays( $nth )->getTimestamp();
|
||||
} elseif ( 'this_week' == $calendar_begins ) {
|
||||
$week = new Carbon( 'now', $this->timezone );
|
||||
$week->setWeekStartsAt( $this->week_starts );
|
||||
$this->start = $week->startOfWeek()->getTimestamp();
|
||||
} elseif ( 'weeks_before' == $calendar_begins ) {
|
||||
$week = new Carbon( 'now', $this->timezone );
|
||||
$week->setWeekStartsAt( $this->week_starts );
|
||||
$this->start = $week->startOfWeek()->subWeeks( $nth )->getTimestamp();
|
||||
} elseif ( 'weeks_after' == $calendar_begins ) {
|
||||
$week = new Carbon( 'now', $this->timezone );
|
||||
$week->setWeekStartsAt( $this->week_starts );
|
||||
$this->start = $week->startOfWeek()->addWeeks( $nth )->getTimestamp();
|
||||
} elseif ( 'this_month' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->startOfMonth()->getTimeStamp();
|
||||
} elseif ( 'months_before' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->subMonths( $nth )->startOfMonth()->getTimeStamp();
|
||||
} elseif ( 'months_after' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->addMonths( $nth )->startOfMonth()->getTimeStamp();
|
||||
} elseif ( 'this_year' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->startOfYear()->getTimestamp();
|
||||
} elseif ( 'years_before' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->subYears( $nth )->startOfYear()->getTimeStamp();
|
||||
} elseif ( 'years_after' == $calendar_begins ) {
|
||||
$this->start = Carbon::today( $this->timezone )->addYears( $nth )->startOfYear()->getTimeStamp();
|
||||
} elseif ( 'custom_date' == $calendar_begins ) {
|
||||
if ( $date = get_post_meta( $this->id, '_calendar_begins_custom_date', true ) ) {
|
||||
$this->start = Carbon::createFromFormat( 'Y-m-d', esc_attr( $date ), $this->timezone )->setTimezone( $this->timezone )->startOfDay()->getTimestamp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set calendar end.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $timestamp
|
||||
*/
|
||||
public function set_end( $timestamp = 0 ) {
|
||||
$latest = is_int( $timestamp ) && $timestamp !== 0 ? $timestamp : $this->latest_event;
|
||||
$this->end = $latest > $this->start ? $latest : $this->start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the calendar to static.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string|bool $static
|
||||
*/
|
||||
public function set_static( $static = '' ) {
|
||||
|
||||
if ( ! empty( $static ) && is_bool( $static ) ) {
|
||||
$this->static = $static;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 'yes' == get_post_meta( $this->id, '_calendar_is_static', true ) ) {
|
||||
$this->static = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->static = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Input fields for settings page.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function settings_fields() {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a calendar view.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $view
|
||||
*
|
||||
* @return Calendar_View
|
||||
*/
|
||||
abstract public function get_view( $view = '' );
|
||||
|
||||
/**
|
||||
* Get event HTML parsed by template.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param Event $event Event object to be parsed.
|
||||
* @param string $template (optional) To use another template or a partial.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_event_html( Event $event, $template = '' ) {
|
||||
$event_builder = new Event_Builder( $event, $this );
|
||||
// Use the event template to parse tags; if empty, fallback to calendar post content.
|
||||
$template = empty( $template ) ? ( empty( $event->template ) ? $this->events_template : $event->template ) : $template;
|
||||
return $event_builder->parse_event_template_tags( $template );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the calendar markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $view The calendar view to display.
|
||||
*/
|
||||
public function html( $view = '' ) {
|
||||
|
||||
$view = empty( $view ) ? $this->view : $this->get_view( $view );
|
||||
|
||||
if ( $view instanceof Calendar_View ) {
|
||||
|
||||
if ( ! empty( $this->errors ) ) {
|
||||
|
||||
if ( current_user_can( 'manage_options' ) ) {
|
||||
echo '<pre><code>';
|
||||
foreach ( $this->errors as $error ) { echo $error; }
|
||||
echo '</code></pre>';
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Get a CSS class from the class name of the calendar view (minus namespace part).
|
||||
$view_name = implode( '-', array_map( 'lcfirst', explode( '_', strtolower( get_class( $view ) ) ) ) );
|
||||
$view_class = substr( $view_name, strrpos( $view_name, '\\' ) + 1 );
|
||||
|
||||
$calendar_class = trim( implode( ' simcal-', apply_filters( 'simcal_calendar_class', array(
|
||||
'simcal-calendar',
|
||||
$this->type,
|
||||
$view_class,
|
||||
), $this->id ) ) );
|
||||
|
||||
echo '<div class="' . $calendar_class . '" '
|
||||
. 'data-calendar-id="' . $this->id . '" '
|
||||
. 'data-timezone="' . $this->timezone . '" '
|
||||
. 'data-offset="' . $this->offset . '" '
|
||||
. 'data-week-start="' . $this->week_starts . '" '
|
||||
. 'data-calendar-start="' . $this->start .'" '
|
||||
. 'data-calendar-end="' . $this->end . '" '
|
||||
. 'data-events-first="' . $this->earliest_event .'" '
|
||||
. 'data-events-last="' . $this->latest_event . '"'
|
||||
. '>';
|
||||
|
||||
date_default_timezone_set( $this->timezone );
|
||||
do_action( 'simcal_calendar_html_before', $this->id );
|
||||
|
||||
$view->html();
|
||||
|
||||
do_action( 'simcal_calendar_html_after', $this->id );
|
||||
date_default_timezone_set( $this->site_timezone );
|
||||
|
||||
//$settings = get_option( 'simple-calendar_settings_calendars' );
|
||||
$poweredby = get_post_meta( $this->id, '_poweredby', true );
|
||||
|
||||
if ( 'yes' == $poweredby ) {
|
||||
$align = is_rtl() ? 'left' : 'right';
|
||||
echo '<small class="simcal-powered simcal-align-' . $align .'">' .
|
||||
sprintf( __( 'Powered by <a href="%s" target="_blank">Simple Calendar</a>', 'google-calendar-events' ), simcal_get_url( 'home' ) ) .
|
||||
'</small>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,262 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Feed
|
||||
*
|
||||
* @package SimpleCalendar/Feeds
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Feed.
|
||||
*
|
||||
* Source of events supplied to calendars.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
abstract class Feed {
|
||||
|
||||
/**
|
||||
* Feed type.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $type = '';
|
||||
|
||||
/**
|
||||
* Feed name.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
/**
|
||||
* Calendar post id.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $post_id = 0;
|
||||
|
||||
/**
|
||||
* Calendar opening.
|
||||
*
|
||||
* @access protected
|
||||
* @var int
|
||||
*/
|
||||
protected $calendar_start = 0;
|
||||
|
||||
/**
|
||||
* Start of week.
|
||||
*
|
||||
* @access protected
|
||||
* @var int
|
||||
*/
|
||||
protected $week_starts = 0;
|
||||
|
||||
/**
|
||||
* Events.
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
public $events = array();
|
||||
|
||||
/**
|
||||
* Events template.
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $events_template = '';
|
||||
|
||||
/**
|
||||
* Timezone setting.
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $timezone_setting = '';
|
||||
|
||||
/**
|
||||
* Timezone.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $timezone = '';
|
||||
|
||||
/**
|
||||
* Earliest possible event.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $time_min = 0;
|
||||
|
||||
/**
|
||||
* Latest possible event.
|
||||
*
|
||||
* @access public
|
||||
* @var int
|
||||
*/
|
||||
public $time_max = 0;
|
||||
|
||||
/**
|
||||
* Feed cache interval.
|
||||
*
|
||||
* @access protected
|
||||
* @var int
|
||||
*/
|
||||
protected $cache = 7200;
|
||||
|
||||
/**
|
||||
* Feed settings.
|
||||
*
|
||||
* @access protected
|
||||
* @var array
|
||||
*/
|
||||
protected $settings = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string|Calendar $calendar
|
||||
*/
|
||||
public function __construct( $calendar = '' ) {
|
||||
|
||||
if ( $calendar instanceof Calendar ) {
|
||||
|
||||
if ( isset( $calendar->id ) ) {
|
||||
$this->post_id = $calendar->id;
|
||||
}
|
||||
if ( isset( $calendar->start ) ) {
|
||||
$this->calendar_start = $calendar->start;
|
||||
}
|
||||
$this->week_starts = isset( $calendar->week_starts ) ? $calendar->week_starts : get_option( 'start_of_week' );
|
||||
$this->events_template = ! empty( $calendar->events_template ) ? $calendar->events_template : simcal_default_event_template();
|
||||
|
||||
if ( $this->post_id > 0 ) {
|
||||
$this->set_cache();
|
||||
$this->timezone_setting = get_post_meta( $this->post_id, '_feed_timezone_setting', true );
|
||||
$this->timezone = $calendar->timezone;
|
||||
$this->set_earliest_event();
|
||||
$this->set_latest_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Input fields for settings page.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return false|array
|
||||
*/
|
||||
public function settings_fields() {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set earliest event.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $timestamp
|
||||
*/
|
||||
public function set_earliest_event( $timestamp = 0 ) {
|
||||
|
||||
$earliest = intval( $timestamp );
|
||||
|
||||
if ( $earliest === 0 ) {
|
||||
|
||||
$start = Carbon::createFromTimestamp( $this->calendar_start, $this->timezone );
|
||||
|
||||
$earliest_date = esc_attr( get_post_meta( $this->post_id, '_feed_earliest_event_date', true ) );
|
||||
$earliest_range = max( absint( get_post_meta( $this->post_id, '_feed_earliest_event_date_range', true ) ), 1 );
|
||||
|
||||
if ( 'days_before' == $earliest_date ) {
|
||||
$earliest = $start->subDays( $earliest_range )->getTimestamp();
|
||||
} elseif ( 'weeks_before' == $earliest_date ) {
|
||||
$earliest = $start->subWeeks( $earliest_range )->addDay()->getTimestamp();
|
||||
} elseif ( 'months_before' == $earliest_date ) {
|
||||
$earliest = $start->subMonths( $earliest_range )->addDay()->getTimestamp();
|
||||
} elseif ( 'years_before' == $earliest_date ) {
|
||||
$earliest = $start->subYears( $earliest_range )->addDay()->getTimestamp();
|
||||
} else {
|
||||
$earliest = $start->getTimestamp();
|
||||
}
|
||||
}
|
||||
|
||||
$this->time_min = $earliest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set latest event.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $timestamp
|
||||
*/
|
||||
public function set_latest_event( $timestamp = 0 ) {
|
||||
|
||||
$latest = intval( $timestamp );
|
||||
|
||||
if ( $latest === 0 ) {
|
||||
|
||||
$start = Carbon::createFromTimestamp( $this->calendar_start, $this->timezone )->endOfDay();
|
||||
|
||||
$latest_date = esc_attr( get_post_meta( $this->post_id, '_feed_latest_event_date', true ) );
|
||||
$latest_range = max( absint( get_post_meta( $this->post_id, '_feed_latest_event_date_range', true ) ), 1 );
|
||||
|
||||
if ( 'days_after' == $latest_date ) {
|
||||
$latest = $start->addDays( $latest_range )->getTimestamp();
|
||||
} elseif ( 'weeks_after' == $latest_date ) {
|
||||
$latest = $start->addWeeks( $latest_range )->subDay()->getTimestamp();
|
||||
} elseif ( 'months_after' == $latest_date ) {
|
||||
$latest = $start->addMonths( $latest_range )->subDay()->getTimestamp();
|
||||
} elseif ( 'years_after' == $latest_date ) {
|
||||
$latest = $start->addYears( $latest_range )->subDay()->getTimestamp();
|
||||
} else {
|
||||
$latest = $start->getTimestamp();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->time_max = $latest;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set cache.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $time
|
||||
*/
|
||||
public function set_cache( $time = 0 ) {
|
||||
if ( $time === 0 || ! is_numeric( $time ) ) {
|
||||
$cache = get_post_meta( $this->post_id, '_feed_cache', true );
|
||||
$time = is_numeric( $cache ) && $cache >= 0 ? absint( $cache ) : $this->cache;
|
||||
}
|
||||
$this->cache = absint( $time );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get events feed.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract public function get_events();
|
||||
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Input Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Field.
|
||||
*
|
||||
* Object for handling an input field in plugin back end.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
abstract class Field {
|
||||
|
||||
/**
|
||||
* Field type.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $type = '';
|
||||
|
||||
/**
|
||||
* Field name.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $name = '';
|
||||
|
||||
/**
|
||||
* Field Id.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $id = '';
|
||||
|
||||
/**
|
||||
* Field title (label).
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
/**
|
||||
* Field type class.
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $type_class = '';
|
||||
|
||||
/**
|
||||
* CSS classes.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $class = '';
|
||||
|
||||
/**
|
||||
* CSS styles.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $style = '';
|
||||
|
||||
/**
|
||||
* Description.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $description = '';
|
||||
|
||||
/**
|
||||
* Tooltip text.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $tooltip = '';
|
||||
|
||||
/**
|
||||
* Attributes.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $attributes = '';
|
||||
|
||||
/**
|
||||
* Placeholder.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $placeholder = '';
|
||||
|
||||
/**
|
||||
* Options.
|
||||
*
|
||||
* @access public
|
||||
* @var array
|
||||
*/
|
||||
public $options = array();
|
||||
|
||||
/**
|
||||
* Value.
|
||||
*
|
||||
* @access public
|
||||
* @var array|string
|
||||
*/
|
||||
public $value = '';
|
||||
|
||||
/**
|
||||
* Default value.
|
||||
*
|
||||
* @access public
|
||||
* @var array|string
|
||||
*/
|
||||
public $default = '';
|
||||
|
||||
public $text = '';
|
||||
|
||||
/**
|
||||
* Validation result.
|
||||
*
|
||||
* @access public
|
||||
* @var string|true
|
||||
*/
|
||||
public $validation = true;
|
||||
|
||||
/**
|
||||
* Construct the field.
|
||||
*
|
||||
* Escapes and sets every field property.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field Field data.
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
|
||||
// Field properties.
|
||||
if ( isset( $field['title'] ) ) {
|
||||
$this->title = esc_attr( $field['title'] );
|
||||
}
|
||||
if ( isset( $field['description'] ) ) {
|
||||
$this->description = wp_kses_post( $field['description'] );
|
||||
}
|
||||
if ( isset( $field['type'] ) ) {
|
||||
$this->type = esc_attr( $field['type'] );
|
||||
}
|
||||
if ( isset( $field['name'] ) ) {
|
||||
$this->name = esc_attr( $field['name'] );
|
||||
}
|
||||
if ( isset( $field['id'] ) ) {
|
||||
$this->id = esc_attr( $field['id'] );
|
||||
}
|
||||
if ( isset( $field['placeholder'] ) ) {
|
||||
$this->placeholder = esc_attr( $field['placeholder'] );
|
||||
}
|
||||
if ( isset( $field['options'] ) && is_array( $field['options'] ) ) {
|
||||
$this->options = array_map( 'esc_attr', $field['options'] );
|
||||
}
|
||||
if ( isset( $field['text'] ) ) {
|
||||
$this->text = $field['text'];
|
||||
}
|
||||
|
||||
// Escaping.
|
||||
if ( ! empty( $field['escaping'] ) && ( is_string( $field['escaping'] ) || is_array( $field['escaping'] ) ) ) {
|
||||
if ( isset( $field['default'] ) ) {
|
||||
$this->default = $this->escape_callback( $field['escaping'], $field['default'] );
|
||||
}
|
||||
if ( isset( $field['value'] ) ) {
|
||||
$this->value = $this->escape_callback( $field['escaping'], $field['value'] );
|
||||
}
|
||||
} else {
|
||||
if ( isset( $field['default'] ) ) {
|
||||
$this->default = $this->escape( $field['default'] );
|
||||
}
|
||||
if ( isset( $field['value'] ) ) {
|
||||
$this->value = $this->escape( $field['value'] );
|
||||
}
|
||||
}
|
||||
|
||||
// Validation.
|
||||
if ( ! empty( $field['validation'] ) ) {
|
||||
$this->validation = $this->validate( $field['validation'], $this->value );
|
||||
}
|
||||
|
||||
// CSS classes and styles.
|
||||
$classes = isset( $field['class'] ) ? $field['class'] : '';
|
||||
$this->set_class( $classes );
|
||||
if ( isset( $field['style'] ) ) {
|
||||
$this->set_style( $field['style'] );
|
||||
}
|
||||
|
||||
// Custom attributes.
|
||||
if ( isset( $field['attributes'] ) ) {
|
||||
$this->set_attributes( $field['attributes'] );
|
||||
}
|
||||
|
||||
// Tooltip markup.
|
||||
if ( isset( $field['tooltip'] ) ) {
|
||||
$this->tooltip = ' <i class="simcal-icon-help simcal-help-tip" data-tip="' . esc_attr( $field['tooltip'] ) . '"></i> ' ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom HTML attributes.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_attributes( $attributes ) {
|
||||
|
||||
$attr = '';
|
||||
|
||||
if ( ! empty( $attributes ) && is_array( $attributes ) ) {
|
||||
foreach ( $attributes as $k => $v ) {
|
||||
$attr .= esc_attr( $k ) . '="' . esc_attr( $v ) . '" ';
|
||||
}
|
||||
}
|
||||
|
||||
$this->attributes = $attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CSS styles.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $css
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_style( $css ) {
|
||||
|
||||
$styles = '';
|
||||
|
||||
if ( ! empty( $css ) && is_array( $css ) ) {
|
||||
foreach ( $css as $k => $v ) {
|
||||
$styles .= esc_attr( $k ) . ': ' . esc_attr( $v ) . '; ';
|
||||
}
|
||||
}
|
||||
|
||||
$this->style = $styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set classes.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $class
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set_class( $class ) {
|
||||
|
||||
$classes = '';
|
||||
$type_class = '';
|
||||
$error = '';
|
||||
|
||||
if ( ! empty( $class ) && is_array( $class ) ) {
|
||||
$classes = implode( ' ', array_map( 'esc_attr', $class ) );
|
||||
}
|
||||
if ( ! empty( $this->type_class ) ) {
|
||||
$type_class = esc_attr( $this->type_class );
|
||||
}
|
||||
if ( true !== $this->validation && ! empty( $this->validation ) ) {
|
||||
$error = 'simcal-field-error ';
|
||||
}
|
||||
|
||||
$this->class = trim( $error . 'simcal-field ' . $type_class . ' ' . $classes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape field value.
|
||||
*
|
||||
* Default escape function, a wrapper for esc_attr().
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @param array|string|int $value
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
protected function escape( $value ) {
|
||||
return ! empty( $value ) ? ( is_array( $value ) ? array_map( 'esc_attr', $value ) : esc_attr( $value ) ) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape callback.
|
||||
*
|
||||
* Custom escaping function set in field args.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @param array|string $callback
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function escape_callback( $callback, $value ) {
|
||||
if ( $callback && ( is_string( $callback ) || is_array( $callback ) ) ) {
|
||||
return call_user_func( $callback, $value );
|
||||
}
|
||||
return esc_attr( $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Validation callback.
|
||||
*
|
||||
* Custom field validation callback set in field args.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access protected
|
||||
*
|
||||
* @param array|string $callback
|
||||
* @param string $value
|
||||
*
|
||||
* @return true|string Expected to return bool (true) if passes, message string if not.
|
||||
*/
|
||||
protected function validate( $callback, $value ) {
|
||||
if ( $callback && ( is_string( $callback ) || is_array( $callback ) ) ) {
|
||||
$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : '';
|
||||
return call_user_func( $callback, $value, $screen );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
abstract public function html();
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Meta Box
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Meta Box.
|
||||
*
|
||||
* Basic interface for post meta boxes markup and post meta handling.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface Meta_Box {
|
||||
|
||||
/**
|
||||
* Output the meta box markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param \WP_Post $post
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function html( $post );
|
||||
|
||||
/**
|
||||
* Validate and save the meta box fields.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param int $post_id
|
||||
* @param \WP_Post $post
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function save( $post_id, $post );
|
||||
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Widget
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Abstracts;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Widget.
|
||||
*
|
||||
* Basic widget interface.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
interface Widget {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function __construct();
|
||||
|
||||
/**
|
||||
* Print the widget content.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $args Display arguments.
|
||||
* @param array $instance The settings for the particular instance of the widget.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function widget( $args, $instance );
|
||||
|
||||
/**
|
||||
* Update a particular instance of the widget.
|
||||
*
|
||||
* This function should check that $new_instance is set correctly.
|
||||
* The newly-calculated value of `$instance` should be returned.
|
||||
* If false is returned, the instance won't be saved/updated.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $new_instance New settings for this instance as input by the user via
|
||||
* @param array $old_instance Old settings for this instance.
|
||||
*
|
||||
* @return array Settings to save or bool false to cancel saving.
|
||||
*/
|
||||
public function update( $new_instance, $old_instance );
|
||||
|
||||
/**
|
||||
* Print the settings update form.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $instance Current settings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function form( $instance );
|
||||
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin Ajax
|
||||
*
|
||||
* @package SimpleCalendar\Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin ajax.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Ajax {
|
||||
|
||||
/**
|
||||
* Set up ajax hooks.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
// Set an option if the user rated the plugin.
|
||||
add_action( 'wp_ajax_simcal_rated', array( $this, 'rate_plugin' ) );
|
||||
|
||||
// Set an option if the user rated the plugin.
|
||||
add_action( 'wp_ajax_simcal_clear_cache', array( $this, 'clear_cache' ) );
|
||||
|
||||
// Convert a datetime format.
|
||||
add_action( 'wp_ajax_simcal_date_i18n_input_preview', array( $this, 'date_i18n' ) );
|
||||
|
||||
// Manage an add-on license activation or deactivation.
|
||||
add_action( 'wp_ajax_simcal_manage_add_on_license', array( $this, 'manage_add_on_license' ) );
|
||||
|
||||
// Reset add-ons licenses.
|
||||
add_action( 'wp_ajax_simcal_reset_add_ons_licenses', array( $this, 'reset_licenses' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear transients.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function clear_cache() {
|
||||
|
||||
$id = isset( $_POST['id'] ) ? ( is_array( $_POST['id'] ) ? array_map( 'intval', $_POST['id'] ) : intval( $_POST['id'] ) ) : '';
|
||||
|
||||
if ( ! empty( $id ) ) {
|
||||
simcal_delete_feed_transients( $id );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback when a user clicks on the rate plugin link.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function rate_plugin() {
|
||||
update_option( 'simple-calendar_admin_footer_text_rated', date( 'Y-m-d', time() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax callback to return a formatted datetime string.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function date_i18n() {
|
||||
|
||||
$value = isset( $_POST['value'] ) ? esc_attr( $_POST['value'] ) : ' ';
|
||||
$timestamp = isset( $_POST['timestamp'] ) ? absint( $_POST['timestamp'] ) : time();
|
||||
|
||||
wp_send_json_success( date_i18n( $value, $timestamp ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate add-on license.
|
||||
*
|
||||
* This code is run only when an add-on requiring a license is installed and active.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function manage_add_on_license() {
|
||||
|
||||
$addon = isset( $_POST['add_on'] ) ? sanitize_key( $_POST['add_on'] ) : false;
|
||||
$action = isset( $_POST['license_action'] ) ? esc_attr( $_POST['license_action'] ) : false;
|
||||
$key = isset( $_POST['license_key'] ) ? esc_attr( $_POST['license_key'] ) : '';
|
||||
$nonce = isset( $_POST['nonce'] ) ? esc_attr( $_POST['nonce'] ) : '';
|
||||
|
||||
// Verify that there are valid variables to process.
|
||||
if ( false === $addon || ! in_array( $action, array( 'activate_license', 'deactivate_license' ) ) ) {
|
||||
wp_send_json_error( __( 'Add-on unspecified or invalid action.', 'google-calendar-events' ) );
|
||||
}
|
||||
|
||||
// Verify this request comes from the add-ons licenses activation settings page.
|
||||
if ( ! wp_verify_nonce( $nonce, 'simcal_license_manager' ) ) {
|
||||
wp_send_json_error( sprintf( __( 'An error occurred: %s', 'google-calendar-events' ), 'Nonce verification failed.' ) );
|
||||
}
|
||||
|
||||
// Removes the prefix and converts simcal_{id_no} to {id_no}.
|
||||
$id = intval( substr( $addon, 7 ) );
|
||||
|
||||
// Data to send in API request.
|
||||
$api_request = array(
|
||||
'edd_action' => $action,
|
||||
'license' => $key,
|
||||
'item_id' => urlencode( $id ),
|
||||
'url' => home_url()
|
||||
);
|
||||
|
||||
// Call the custom API.
|
||||
$response = wp_remote_post(
|
||||
defined( 'SIMPLE_CALENDAR_STORE_URL' ) ? SIMPLE_CALENDAR_STORE_URL : simcal_get_url( 'home' ),
|
||||
array(
|
||||
'timeout' => 15,
|
||||
'sslverify' => false,
|
||||
'body' => $api_request
|
||||
)
|
||||
);
|
||||
|
||||
// Update license in db.
|
||||
$keys = get_option( 'simple-calendar_settings_licenses', array() );
|
||||
$keys['keys'][ $addon ] = $key;
|
||||
update_option( 'simple-calendar_settings_licenses', $keys );
|
||||
|
||||
// Make sure there is a response.
|
||||
if ( is_wp_error( $response ) ) {
|
||||
wp_send_json_error( sprintf( __( 'There was an error processing your request: %s', 'google-calendar-events' ), $response->get_error_message() ) );
|
||||
}
|
||||
|
||||
// Decode the license data and save.
|
||||
$license_data = json_decode( wp_remote_retrieve_body( $response ) );
|
||||
$status = simcal_get_license_status();
|
||||
|
||||
if ( ! empty( $license_data ) ) {
|
||||
if ('deactivated' == $license_data->license) {
|
||||
unset($status[$addon]);
|
||||
update_option('simple-calendar_licenses_status', $status);
|
||||
wp_send_json_success($license_data->license);
|
||||
} elseif (in_array($license_data->license, array('valid', 'invalid'))) {
|
||||
$status[$addon] = $license_data->license;
|
||||
update_option('simple-calendar_licenses_status', $status);
|
||||
$message = 'valid' == $license_data->license ? 'valid' : __('License key is invalid.', 'google-calendar-events');
|
||||
wp_send_json_success($message);
|
||||
} else {
|
||||
wp_send_json_error( '' );
|
||||
}
|
||||
} else {
|
||||
wp_send_json_error( __( 'An error has occurred, please try again.', 'google-calendar-events' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset licenses.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function reset_licenses() {
|
||||
|
||||
$nonce = isset( $_POST['nonce'] ) ? esc_attr( $_POST['nonce'] ) : '';
|
||||
|
||||
// Verify this request comes from the add-ons licenses activation settings page.
|
||||
if ( empty ( $nonce ) || ! wp_verify_nonce( $nonce, 'simcal_license_manager' ) ) {
|
||||
wp_send_json_error( sprintf( __( 'An error occurred: %s', 'google-calendar-events' ), 'Nonce verification failed.' ) );
|
||||
}
|
||||
|
||||
delete_option( 'simple-calendar_settings_licenses' );
|
||||
delete_option( 'simple-calendar_licenses_status' );
|
||||
|
||||
wp_send_json_success( 'success' );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin Assets
|
||||
*
|
||||
* @package SimpleCalendar\Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin scripts and styles.
|
||||
*
|
||||
* Handles the plugin scripts and styles for back end dashboard pages.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Assets {
|
||||
|
||||
/**
|
||||
* Load minified assets.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $min = '.min';
|
||||
|
||||
/**
|
||||
* Hook in tabs.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
$this->min = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG == true ) ? '' : '.min';
|
||||
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'load' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and styles.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function load() {
|
||||
|
||||
$css_path = SIMPLE_CALENDAR_ASSETS . 'css/';
|
||||
$css_path_vendor = $css_path . 'vendor/';
|
||||
$js_path = SIMPLE_CALENDAR_ASSETS . 'js/';
|
||||
$js_path_vendor = $js_path . 'vendor/';
|
||||
|
||||
/* ====================== *
|
||||
* Register Admin Scripts *
|
||||
* ====================== */
|
||||
|
||||
// TipTip uses ".minified.js" filename ending.
|
||||
wp_register_script(
|
||||
'simcal-tiptip',
|
||||
$js_path_vendor . 'jquery.tipTip' . ( ( $this->min !== '' ) ? '.minified' : '' ) . '.js',
|
||||
array( 'jquery' ),
|
||||
'1.3',
|
||||
true
|
||||
);
|
||||
wp_register_script(
|
||||
'simcal-select2',
|
||||
$js_path_vendor . 'select2' . $this->min . '.js',
|
||||
array(),
|
||||
'4.0',
|
||||
true
|
||||
);
|
||||
wp_register_script(
|
||||
'simcal-admin',
|
||||
$js_path . 'admin' . $this->min . '.js',
|
||||
array(
|
||||
'jquery',
|
||||
'jquery-ui-sortable',
|
||||
'jquery-ui-datepicker',
|
||||
'wp-color-picker',
|
||||
'simcal-tiptip',
|
||||
'simcal-select2',
|
||||
),
|
||||
SIMPLE_CALENDAR_VERSION,
|
||||
true
|
||||
);
|
||||
wp_register_script(
|
||||
'simcal-admin-add-calendar',
|
||||
$js_path . 'admin-add-calendar' . $this->min . '.js',
|
||||
array( 'simcal-select2' ),
|
||||
SIMPLE_CALENDAR_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
/* ===================== *
|
||||
* Register Admin Styles *
|
||||
* ===================== */
|
||||
|
||||
wp_register_style(
|
||||
'simcal-select2',
|
||||
$css_path_vendor . 'select2' . $this->min . '.css',
|
||||
array(),
|
||||
'4.0.0'
|
||||
);
|
||||
wp_register_style(
|
||||
'simcal-admin',
|
||||
$css_path . 'admin' . $this->min . '.css',
|
||||
array(
|
||||
'wp-color-picker',
|
||||
'simcal-select2',
|
||||
),
|
||||
SIMPLE_CALENDAR_VERSION
|
||||
);
|
||||
wp_register_style(
|
||||
'simcal-admin-add-calendar',
|
||||
$css_path . 'admin-add-calendar' . $this->min . '.css',
|
||||
array( 'simcal-select2' ),
|
||||
SIMPLE_CALENDAR_VERSION
|
||||
);
|
||||
|
||||
if ( simcal_is_admin_screen() !== false ) {
|
||||
|
||||
wp_enqueue_script( 'simcal-admin' );
|
||||
wp_localize_script(
|
||||
'simcal-admin',
|
||||
'simcal_admin',
|
||||
simcal_common_scripts_variables()
|
||||
);
|
||||
|
||||
wp_enqueue_style( 'simcal-admin' );
|
||||
|
||||
} else {
|
||||
|
||||
global $post_type;
|
||||
$screen = get_current_screen();
|
||||
|
||||
$post_types = array();
|
||||
$settings = get_option( 'simple-calendar_settings_calendars' );
|
||||
if ( isset( $settings['general']['attach_calendars_posts'] ) ) {
|
||||
$post_types = $settings['general']['attach_calendars_posts'];
|
||||
}
|
||||
|
||||
$conditions = array(
|
||||
in_array( $post_type, (array) $post_types ),
|
||||
$screen->id == 'widgets',
|
||||
);
|
||||
|
||||
if ( in_array( true, $conditions ) ) {
|
||||
|
||||
wp_enqueue_script( 'simcal-admin-add-calendar' );
|
||||
wp_localize_script( 'simcal-admin-add-calendar', 'simcal_admin', array(
|
||||
'locale' => get_locale(),
|
||||
'text_dir' => is_rtl() ? 'rtl' : 'ltr',
|
||||
) );
|
||||
|
||||
wp_enqueue_style( 'simcal-admin-add-calendar' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Admin Bulk Actions
|
||||
*
|
||||
* Add bulk actions to post types edit screens.
|
||||
* Based on https://github.com/Seravo/wp-custom-bulk-actions
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin bulk actions.
|
||||
*/
|
||||
class Bulk_Actions {
|
||||
|
||||
/**
|
||||
* Target post type.
|
||||
*
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $bulk_action_post_type = '';
|
||||
|
||||
/**
|
||||
* Bulk actions.
|
||||
*
|
||||
* @access private
|
||||
* @var array
|
||||
*/
|
||||
private $actions = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param string $post_type
|
||||
*/
|
||||
public function __construct( $post_type ) {
|
||||
$this->bulk_action_post_type = post_type_exists( $post_type ) ? $post_type : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Define all your custom bulk actions and corresponding callbacks
|
||||
* Define at least $menu_text and $callback parameters
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $args
|
||||
*/
|
||||
public function register_bulk_action( $args ) {
|
||||
|
||||
$func = array();
|
||||
$func['action_name'] = isset( $args['action_name'] ) ? sanitize_key( $args['action_name'] ) : '';
|
||||
$func['callback'] = isset( $args['callback'] ) ? $args['callback'] : '';
|
||||
$func['menu_text'] = isset( $args['menu_text'] ) ? esc_attr( $args['menu_text'] ) : '';
|
||||
$func['admin_notice'] = isset( $args['admin_notice'] ) ? esc_attr( $args['admin_notice'] ) : '';
|
||||
|
||||
if ( $func['action_name'] && $func['callback'] ) {
|
||||
$this->actions[ $func['action_name'] ] = $func;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init.
|
||||
*
|
||||
* Callbacks need to be registered before add_actions.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function init() {
|
||||
if ( is_admin() ) {
|
||||
add_action( 'admin_footer-edit.php', array( $this, 'custom_bulk_admin_footer' ) );
|
||||
add_action( 'load-edit.php', array( $this, 'custom_bulk_action' ) );
|
||||
add_action( 'admin_notices', array( $this, 'custom_bulk_admin_notices' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 1: add the custom Bulk Action to the select menus.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function custom_bulk_admin_footer() {
|
||||
|
||||
global $post_type;
|
||||
|
||||
// Only permit actions with defined post type.
|
||||
if ( $post_type == $this->bulk_action_post_type ) {
|
||||
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
jQuery( document ).ready( function() {
|
||||
<?php foreach ( $this->actions as $action_name => $action ) : ?>
|
||||
jQuery( '<option>' ).val( '<?php echo $action_name ?>' ).text( '<?php echo $action['menu_text'] ?>').appendTo( 'select[name="action"]' );
|
||||
jQuery( '<option>' ).val( '<?php echo $action_name ?>' ).text( '<?php echo $action['menu_text'] ?>').appendTo( 'select[name="action2"]' );
|
||||
<?php endforeach; ?>
|
||||
} );
|
||||
</script>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 2: handle the custom Bulk Action.
|
||||
*
|
||||
* Based on the post http://wordpress.stackexchange.com/questions/29822/custom-bulk-action
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function custom_bulk_action() {
|
||||
|
||||
global $typenow;
|
||||
$post_type = $typenow;
|
||||
|
||||
if ( $post_type == $this->bulk_action_post_type ) {
|
||||
|
||||
// Get the action.
|
||||
// Depending on your resource type this could be WP_Users_List_Table, WP_Comments_List_Table, etc.
|
||||
$wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
|
||||
$action = $wp_list_table->current_action();
|
||||
|
||||
// Allow only defined actions.
|
||||
$allowed_actions = array_keys( $this->actions );
|
||||
if ( ! in_array( $action, $allowed_actions ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Security check.
|
||||
check_admin_referer( 'bulk-posts' );
|
||||
|
||||
// Make sure ids are submitted.
|
||||
// Depending on the resource type, this may be 'media' or 'ids'.
|
||||
if ( isset( $_REQUEST['post'] ) ) {
|
||||
$post_ids = array_map( 'intval', $_REQUEST['post'] );
|
||||
}
|
||||
|
||||
if ( empty( $post_ids ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This is based on wp-admin/edit.php.
|
||||
$sendback = remove_query_arg(
|
||||
array( 'exported', 'untrashed', 'deleted', 'ids' ),
|
||||
wp_get_referer()
|
||||
);
|
||||
if ( ! $sendback ) {
|
||||
$sendback = admin_url( "edit.php?post_type=$post_type" );
|
||||
}
|
||||
|
||||
$pagenum = $wp_list_table->get_pagenum();
|
||||
$sendback = add_query_arg( 'paged', $pagenum, $sendback );
|
||||
|
||||
// Check that we have anonymous function as a callback.
|
||||
$anon_fns = array_filter( $this->actions[ $action ], function( $el ) {
|
||||
return $el instanceof \Closure;
|
||||
} );
|
||||
|
||||
if ( count( $anon_fns ) > 0 ) {
|
||||
$this->actions[ $action ]['callback']( $post_ids );
|
||||
} else {
|
||||
call_user_func( $this->actions[ $action ]['callback'], $post_ids );
|
||||
}
|
||||
|
||||
$sendback = add_query_arg(
|
||||
array( 'success_action' => $action, 'ids' => join( ',', $post_ids ) ),
|
||||
$sendback
|
||||
);
|
||||
$sendback = remove_query_arg(
|
||||
array( 'action', 'paged', 'mode', 'action2', 'tags_input', 'post_author', 'comment_status', 'ping_status', '_status', 'post', 'bulk_edit', 'post_view' ),
|
||||
$sendback
|
||||
);
|
||||
|
||||
wp_redirect( $sendback );
|
||||
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 3: display an admin notice after action.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function custom_bulk_admin_notices() {
|
||||
|
||||
global $post_type, $pagenow;
|
||||
|
||||
if ( isset( $_REQUEST['ids'] ) ) {
|
||||
$post_ids = explode( ',', $_REQUEST['ids'] );
|
||||
}
|
||||
|
||||
// Make sure ids are submitted.
|
||||
// Depending on the resource type, this may be 'media' or 'ids'.
|
||||
if ( empty( $post_ids ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$post_ids_count = is_array( $post_ids ) ? count( $post_ids ) : 1;
|
||||
|
||||
if ( $pagenow == 'edit.php' && $post_type == $this->bulk_action_post_type ) {
|
||||
|
||||
if ( isset( $_REQUEST['success_action'] ) ) {
|
||||
|
||||
// Print notice in admin bar.
|
||||
$message = $this->actions[ $_REQUEST['success_action'] ]['admin_notice'];
|
||||
|
||||
if ( is_array( $message ) ) {
|
||||
$message = sprintf( _n( $message['single'], $message['plural'], $post_ids_count, 'google-calendar-events' ), $post_ids_count );
|
||||
}
|
||||
|
||||
$class = 'updated notice is-dismissible above-h2';
|
||||
if ( ! empty( $message ) ) {
|
||||
echo "<div class=\"{$class}\"><p>{$message}</p></div>";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Checkbox Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkbox input field.
|
||||
*
|
||||
* Outputs one single checkbox or a fieldset of checkboxes for multiple choices.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Checkbox extends Field {
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
$this->type_class = 'simcal-field-checkboxes';
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
if ( ! empty( $this->options ) && count( (array) $this->options ) > 1 ) {
|
||||
|
||||
if ( ! empty( $this->description ) ) {
|
||||
echo '<p class="description">' . wp_kses_post( $this->description ) . ' ' . $this->tooltip . '</p>';
|
||||
}
|
||||
|
||||
?>
|
||||
<fieldset class="<?php echo $this->class; ?>" <?php echo ! empty( $this->style ) ? 'style="' . $this->style . '"' : ''; ?>>
|
||||
<?php
|
||||
|
||||
if ( ! empty( $this->title ) ) {
|
||||
echo '<legend class="screen-reader-text"><span>' . $this->title . '</span></legend>';
|
||||
}
|
||||
|
||||
?>
|
||||
<ul>
|
||||
<?php foreach ( $this->options as $option => $name ) : ?>
|
||||
<li>
|
||||
<label for="<?php echo $this->id . '-' . trim( strval( $option ) ); ?>">
|
||||
<input name="<?php echo $this->name; ?>"
|
||||
id="<?php echo $this->id . '-' . trim( strval( $option ) ); ?>"
|
||||
class="simcal-field simcal-field-checkbox"
|
||||
type="checkbox"
|
||||
value="<?php echo trim( strval( $option ) ); ?>"
|
||||
<?php checked( $this->value, 'yes', true ); ?>
|
||||
<?php echo $this->attributes; ?>
|
||||
/><?php echo esc_attr( $name ); ?>
|
||||
</label>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</fieldset>
|
||||
<?php
|
||||
|
||||
} else {
|
||||
|
||||
?>
|
||||
<span class="simcal-field-bool" <?php echo $this->style ? 'style="' . $this->style . '"' : ''; ?>>
|
||||
<?php if ( ! empty( $this->title ) ) : ?>
|
||||
<span class="screen-reader-text"><?php echo $this->title; ?></span>
|
||||
<?php endif; ?>
|
||||
<input name="<?php echo $this->name; ?>"
|
||||
type="checkbox"
|
||||
id="<?php echo $this->id; ?>"
|
||||
class="simcal-field simcal-field-checkbox <?php echo $this->class; ?>"
|
||||
value="yes"
|
||||
<?php checked( $this->value, 'yes', true ); ?>
|
||||
<?php echo $this->attributes; ?>/><?php echo ( ! empty( $this->text ) ? $this->text : __( 'Yes', 'google-calendar-events' ) ); ?>
|
||||
</span>
|
||||
<?php
|
||||
|
||||
echo $this->tooltip;
|
||||
|
||||
if ( ! empty( $this->description ) ) {
|
||||
echo '<p class="description">' . wp_kses_post( $this->description ) . '</p>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Date Picker Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Date Picker input field.
|
||||
*
|
||||
* A special field to choose dates or date ranges.
|
||||
* Holds a date value in 'yy-mm-dd' format.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Date_Picker extends Field {
|
||||
|
||||
/**
|
||||
* Select a date range.
|
||||
*
|
||||
* @access public
|
||||
* @var bool
|
||||
*/
|
||||
public $range = false;
|
||||
|
||||
/**
|
||||
* Use an inline picker.
|
||||
*
|
||||
* @access public
|
||||
* @var bool
|
||||
*/
|
||||
public $inline = true;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
|
||||
$this->range = isset( $field['range'] ) ? ( $field['range'] === true ? true : false ) : false;
|
||||
$this->inline = isset( $field['inline'] ) ? ( $field['inline'] === true ? true : false ) : true;
|
||||
|
||||
$subtype = $this->range === true ? 'simcal-field-date-picker-range ' : '';
|
||||
$this->type_class = 'simcal-field-date-picker ' . $subtype;
|
||||
|
||||
$data = array(
|
||||
'data-inline' => $this->inline === true ? 'true' : 'false',
|
||||
);
|
||||
$field['attributes'] = isset( $field['attributes'] ) ? array_merge( $field['attributes'], $data ) : $data;
|
||||
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the field markup
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
if ( ! empty( $this->description ) ) {
|
||||
echo '<p class="description">' . wp_kses_post( $this->description ) . '</p>';
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="<?php echo $this->id; ?>"
|
||||
class="<?php echo $this->class; ?>"
|
||||
<?php echo $this->style ? 'style="' . $this->style . '"' : ''; ?>
|
||||
<?php echo $this->attributes ?>>
|
||||
<?php
|
||||
|
||||
if ( false === $this->range ) {
|
||||
|
||||
?>
|
||||
<i class="simcal-icon-calendar"></i>
|
||||
<input type="<?php echo $this->inline === true ? 'text' : 'hidden'; ?>"
|
||||
name="<?php echo $this->name; ?>"
|
||||
value="<?php echo $this->value; ?>"
|
||||
placeholder="..."
|
||||
readonly="readonly" />
|
||||
<?php
|
||||
|
||||
if ( true === $this->inline ) {
|
||||
echo $this->tooltip;
|
||||
}
|
||||
|
||||
} else {
|
||||
// @todo eventually if a date range picker is needed, this can be extended
|
||||
}
|
||||
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Datetime Formatter Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Datetime formatter field.
|
||||
*
|
||||
* A special field to choose a format for date and time.
|
||||
*/
|
||||
class Datetime_Format extends Field {
|
||||
|
||||
/**
|
||||
* Datetime controls.
|
||||
*
|
||||
* @access public
|
||||
* @var string 'date' or 'time'
|
||||
*/
|
||||
public $subtype = '';
|
||||
|
||||
/**
|
||||
* Timestamp.
|
||||
*
|
||||
* @access private
|
||||
* @var int
|
||||
*/
|
||||
private $timestamp = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
|
||||
$this->subtype = isset( $field['subtype'] ) ? $field['subtype'] : '';
|
||||
$this->type_class = 'simcal-field-datetime-format simcal-field-' . $this->subtype . '-format-field';
|
||||
$this->timestamp = mktime( 13, 10, 00, 1, 1, intval( date( 'Y', time() ) ) + 1 );
|
||||
|
||||
parent::__construct( $field );
|
||||
|
||||
if ( empty( $this->value ) ) {
|
||||
if ( 'date' == $this->subtype ) {
|
||||
$this->value = 'l, d F Y';
|
||||
}
|
||||
if ( 'time' == $this->subtype ) {
|
||||
$this->value = 'G:i a';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
$id = $this->id ? ' id="' . $this->id . '" ' : '';
|
||||
$class = $this->class ? ' class="' . $this->class . '" ' : '';
|
||||
$style = $this->style ? ' style="' . $this->style . '" ' : '';
|
||||
$attr = $this->attributes;
|
||||
|
||||
?>
|
||||
<div <?php echo $id . $class . $style . $attr; ?>>
|
||||
<?php
|
||||
|
||||
if ( ! empty( $this->description ) ) {
|
||||
echo '<p class="description">' . $this->description . '</p>';
|
||||
}
|
||||
|
||||
$matches = array_unique( str_split( $this->value ) );
|
||||
|
||||
if ( 'date' == $this->subtype ) {
|
||||
$this->print_date( $matches );
|
||||
}
|
||||
|
||||
if ( 'time' == $this->subtype ) {
|
||||
$this->print_time( $matches );
|
||||
}
|
||||
|
||||
?>
|
||||
<input type="hidden"
|
||||
name="<?php echo $this->name; ?>"
|
||||
value="<?php echo trim( $this->value ); ?>" />
|
||||
<span>
|
||||
<em><?php _e( 'Preview', 'google-calendar-events' ); ?>:</em>
|
||||
<code><?php echo date_i18n( $this->value, $this->timestamp ); ?></code>
|
||||
</span>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print date input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*
|
||||
* @param array $matches
|
||||
*/
|
||||
private function print_date( $matches ) {
|
||||
|
||||
$date = array( 'weekday' => '', 'divider' => '', 'day' => '', 'month' => '', 'year' => '' );
|
||||
|
||||
foreach ( $matches as $match ) {
|
||||
if ( in_array( $match, array( 'D', 'l' ) ) ) {
|
||||
$this->weekday();
|
||||
unset( $date['weekday'] );
|
||||
} elseif ( in_array( $match, array( 'd', 'j' ) ) ) {
|
||||
$this->day();
|
||||
unset( $date['day'] );
|
||||
} elseif ( in_array( $match, array( 'F', 'M', 'm', 'n' ) ) ) {
|
||||
$this->month();
|
||||
unset( $date['month'] );
|
||||
} elseif ( in_array( $match, array( 'y', 'Y' ) ) ) {
|
||||
$this->year();
|
||||
unset( $date['year'] );
|
||||
} elseif ( in_array( $match, array( '.', ',', ':', '/', '-' ) ) ) {
|
||||
$this->divider();
|
||||
unset( $date['divider'] );
|
||||
}
|
||||
}
|
||||
|
||||
$this->print_fields( $date );
|
||||
}
|
||||
|
||||
/**
|
||||
* Print time input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*
|
||||
* @param array $matches
|
||||
*/
|
||||
private function print_time( $matches ) {
|
||||
|
||||
$time = array( 'hours' => '', 'divider' => '', 'minutes' => '', 'meridiem' => '' );
|
||||
|
||||
foreach ( $matches as $match ) {
|
||||
if ( in_array( $match, array( 'h', 'H', 'g', 'G' ) ) ) {
|
||||
$this->hours();
|
||||
unset( $time['hours'] );
|
||||
} elseif ( in_array( $match, array( 'i' ) ) ) {
|
||||
$this->minutes();
|
||||
unset( $time['minutes'] );
|
||||
} elseif ( in_array( $match, array( 'A', 'a' ) ) ) {
|
||||
$this->meridiem();
|
||||
unset( $time['meridiem'] );
|
||||
} elseif ( in_array( $match, array( '.', ',', ':', '/', '-' ) ) ) {
|
||||
$this->divider();
|
||||
unset( $time['divider'] );
|
||||
}
|
||||
}
|
||||
|
||||
$this->print_fields( $time );
|
||||
}
|
||||
|
||||
/**
|
||||
* Print input fields.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*
|
||||
* @param $fields
|
||||
*/
|
||||
private function print_fields( $fields ) {
|
||||
if ( ! empty( $fields ) && is_array( $fields ) ) {
|
||||
foreach ( $fields as $func => $v ) {
|
||||
if ( method_exists( $this, $func ) ) {
|
||||
$this->$func();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print weekday input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function weekday() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-weekday">
|
||||
<?php _e( 'Weekday', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-weekday">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="D" <?php selected( 'D', strpbrk( 'D', $this->value ) ) ?> data-preview="<?php echo date_i18n( 'D', $this->timestamp ); ?>"><?php echo date_i18n( 'D', $this->timestamp ); ?></option>
|
||||
<option value="l" <?php selected( 'l', strpbrk( 'l', $this->value ) ) ?> data-preview="<?php echo date_i18n( 'l', $this->timestamp ); ?>"><?php echo date_i18n( 'l', $this->timestamp ); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print day input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function day() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-day">
|
||||
<?php _e( 'Day', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-day">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="j" <?php selected( 'j', strpbrk( 'j', $this->value ) ) ?> data-preview="<?php echo date( 'j', $this->timestamp ); ?>"><?php echo date( 'j', $this->timestamp ); ?></option>
|
||||
<option value="d" <?php selected( 'd', strpbrk( 'd', $this->value ) ) ?> data-preview="<?php echo date( 'd', $this->timestamp ); ?>"><?php echo date( 'd', $this->timestamp ); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print month input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function month() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-month">
|
||||
<?php _e( 'Month', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-month">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="F" <?php selected( 'F', strpbrk( 'F', $this->value ) ) ?> data-preview="<?php echo date_i18n( 'F', $this->timestamp ); ?>"><?php echo date_i18n( 'F', $this->timestamp ); ?></option>
|
||||
<option value="M" <?php selected( 'M', strpbrk( 'M', $this->value ) ) ?> data-preview="<?php echo date_i18n( 'M', $this->timestamp ); ?>"><?php echo date_i18n( 'M', $this->timestamp ); ?></option>
|
||||
<option value="m" <?php selected( 'm', strpbrk( 'm', $this->value ) ) ?> data-preview="<?php echo date( 'm', $this->timestamp ); ?>"><?php echo date( 'm', $this->timestamp ); ?></option>
|
||||
<option value="n" <?php selected( 'n', strpbrk( 'n', $this->value ) ) ?> data-preview="<?php echo date( 'n', $this->timestamp ); ?>"><?php echo date( 'n', $this->timestamp ); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print year input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function year() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-year">
|
||||
<?php _e( 'Year', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-year">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="Y" <?php selected( 'Y', strpbrk( 'Y', $this->value ) ) ?> data-preview="<?php echo date( 'Y', $this->timestamp ); ?>"><?php echo date( 'Y', $this->timestamp ); ?></option>
|
||||
<option value="y" <?php selected( 'y', strpbrk( 'y', $this->value ) ) ?> data-preview="<?php echo date( 'y', $this->timestamp ); ?>"><?php echo date( 'y', $this->timestamp ); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print hours input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function hours() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-hours">
|
||||
<?php _e( 'Hours', 'google-calendar-events' ) ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-hours">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="g" <?php selected( 'g', strpbrk( 'g', $this->value ) ); ?> data-preview="<?php echo date( 'g', $this->timestamp ); ?>"><?php echo date( 'g', $this->timestamp ) . ' (12h)'; ?></option>
|
||||
<option value="G" <?php selected( 'G', strpbrk( 'G', $this->value ) ); ?> data-preview="<?php echo date( 'G', $this->timestamp - 43200 ); ?>"><?php echo date( 'G', $this->timestamp - 43200 ) . ' (24h)'; ?></option>
|
||||
<option value="h" <?php selected( 'h', strpbrk( 'h', $this->value ) ); ?> data-preview="<?php echo date( 'h', $this->timestamp ); ?>"><?php echo date( 'h', $this->timestamp ) . ' (12h)'; ?></option>
|
||||
<option value="H" <?php selected( 'H', strpbrk( 'H', $this->value ) ); ?> data-preview="<?php echo date( 'H', $this->timestamp - 43200 ); ?>"><?php echo date( 'H', $this->timestamp - 43200 ) . ' (24h)'; ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print minutes input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function minutes() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-minutes">
|
||||
<?php _e( 'Minutes', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-minutes">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="i" <?php selected( 'i', strpbrk( 'i', $this->value ) ); ?> data-preview="<?php echo date( 'i', $this->timestamp ); ?>"><?php echo date( 'i', $this->timestamp ); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print meridiem input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function meridiem() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-meridiem">
|
||||
<?php _e( 'Meridiem', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-meridiem">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="a" <?php selected( 'a', strpbrk( 'a', $this->value ) ); ?> data-preview="<?php echo date( 'a', $this->timestamp ); ?>"><?php echo date( 'a', $this->timestamp ); ?></option>
|
||||
<option value="A" <?php selected( 'A', strpbrk( 'A', $this->value ) ); ?> data-preview="<?php echo date( 'A', $this->timestamp ); ?>"><?php echo date( 'A', $this->timestamp ); ?></option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Print divider input.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @access private
|
||||
*/
|
||||
private function divider() {
|
||||
|
||||
?>
|
||||
<div>
|
||||
<label for="<?php echo $this->id; ?>-divider">
|
||||
<?php _ex( 'Divider', 'A character to separate two elements', 'google-calendar-events' ); ?>
|
||||
<select name="" id="<?php echo $this->id; ?>-divider">
|
||||
<option value="" data-preview=""></option>
|
||||
<option value="." <?php selected( '.', strpbrk( '.', $this->value ) ); ?> data-preview="." data-trim="true">.</option>
|
||||
<option value=", " <?php selected( ',', strpbrk( ',', $this->value ) ); ?> data-preview=", " data-trim="true">,</option>
|
||||
<option value=":" <?php selected( ':', strpbrk( ':', $this->value ) ); ?> data-preview=":" data-trim="true">:</option>
|
||||
<option value="-" <?php selected( '-', strpbrk( '-', $this->value ) ); ?> data-preview="-" data-trim="true">-</option>
|
||||
<option value="/" <?php selected( '/', strpbrk( '/', $this->value ) ); ?> data-preview="/" data-trim="true">/</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* License Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* License input field.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class License extends Field {
|
||||
|
||||
/**
|
||||
* Add-on.
|
||||
*
|
||||
* @access private
|
||||
* @var string
|
||||
*/
|
||||
private $addon = '';
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
$this->addon = isset( $field['addon'] ) ? esc_attr( $field['addon'] ) : '';
|
||||
$this->type_class = 'simcal-field-license';
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
if ( ! empty( $this->addon ) ) {
|
||||
|
||||
$status = apply_filters( 'simcal_addon_status_' . $this->addon, simcal_get_license_status( $this->addon ) );
|
||||
|
||||
if ( $status !== 'valid' ) {
|
||||
$display_activate = 'display: inline-block';
|
||||
$display_deactivate = 'display: none';
|
||||
$active = 'valid' == $status ? 'display: block' : 'display: none';
|
||||
$disabled = '';
|
||||
} else {
|
||||
$display_activate = $active = 'display: none';
|
||||
$display_deactivate = 'display: inline-block';
|
||||
$disabled = empty( $this->value ) ? '' : 'disabled="disabled"';
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="simcal-addon-manage-license-field" data-addon="<?php echo $this->addon; ?>">
|
||||
|
||||
<input type="text" <?php echo $disabled; ?>
|
||||
name="<?php echo $this->name; ?>"
|
||||
id="<?php echo $this->id; ?>"
|
||||
value="<?php echo $this->value; ?>"
|
||||
class="<?php echo $this->class; ?>" />
|
||||
|
||||
<span class="simcal-addon-manage-license-buttons">
|
||||
|
||||
<button class="button-secondary simcal-addon-manage-license deactivate" data-add-on="<?php echo $this->addon; ?>" style="<?php echo $display_deactivate; ?>">
|
||||
<i class="simcal-icon-spinner simcal-icon-spin" style="display: none;"></i><?php _e( 'Deactivate', 'google-calendar-events' ); ?>
|
||||
</button>
|
||||
|
||||
<button class="button-secondary simcal-addon-manage-license activate" data-add-on="<?php echo $this->addon; ?>" style="<?php echo $display_activate; ?>">
|
||||
<i class="simcal-icon-spinner simcal-icon-spin" style="display: none;"></i><?php _e( 'Activate', 'google-calendar-events' ); ?>
|
||||
</button>
|
||||
|
||||
<span class="error" style="color: red; display: none"> </span>
|
||||
|
||||
<strong class="label" style="color:green; <?php echo $active; ?>"> <?php _e( '(active)', 'google-calendar-events' ); ?></strong>
|
||||
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nonce Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nonce field.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Nonce extends Field {
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
wp_nonce_field( $this->name, $this->value );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Radio Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Radio input field.
|
||||
*
|
||||
* Outputs a fieldset of radio inputs for multiple choices.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Radio extends Field {
|
||||
|
||||
/**
|
||||
* Inline radios.
|
||||
*
|
||||
* @access private
|
||||
* @var bool
|
||||
*/
|
||||
private $inline = false;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
|
||||
$this->type_class = 'simcal-field-radios';
|
||||
$this->inline = isset( $field['inline'] ) ? ( 'inline' == $field['inline'] ? true : false ) : false;
|
||||
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
?>
|
||||
<fieldset id="<?php echo $this->id; ?>"
|
||||
class="<?php echo $this->class; ?>"
|
||||
<?php echo $this->style ? 'style="' . $this->style .'"' : ''; ?>>
|
||||
<?php
|
||||
|
||||
echo $this->description ? '<p class="description">' . wp_kses_post( $this->description ) . '</p>' : '';
|
||||
|
||||
if ( ! empty( $this->title ) ) :
|
||||
|
||||
?>
|
||||
<legend class="screen-reader-text">
|
||||
<span><?php echo $this->title; ?></span>
|
||||
</legend>
|
||||
<?php
|
||||
|
||||
endif;
|
||||
|
||||
?>
|
||||
<ul <?php echo $this->inline === true ? 'class="simcal-field-radios-inline"' : ''; ?>>
|
||||
<?php foreach ( $this->options as $option => $name ) : ?>
|
||||
<li>
|
||||
<label for="<?php echo $this->id . '-' . trim( strval( $option ) ); ?>">
|
||||
<input name="<?php echo $this->name; ?>"
|
||||
id="<?php echo $this->id . '-' . trim( strval( $option ) ); ?>"
|
||||
class="simcal-field simcal-field-radio"
|
||||
type="radio"
|
||||
value="<?php echo trim( strval( $option ) ); ?>"
|
||||
<?php echo $this->attributes; ?>
|
||||
<?php checked( $option, $this->value, true ); ?>
|
||||
/>
|
||||
<?php echo esc_attr( $name ); ?>
|
||||
</label>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
|
||||
<?php echo $this->tooltip; ?>
|
||||
|
||||
</fieldset>
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Select Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select input field.
|
||||
*
|
||||
* A standard dropdown or a multiselect field.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Select extends Field {
|
||||
|
||||
/**
|
||||
* Enhanced select.
|
||||
*
|
||||
* @access public
|
||||
* @var bool
|
||||
*/
|
||||
public $enhanced = false;
|
||||
|
||||
/**
|
||||
* Multiselect.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $multiselect = false;
|
||||
|
||||
/**
|
||||
* Allow void option.
|
||||
*
|
||||
* @access private
|
||||
* @var bool
|
||||
*/
|
||||
private $allow_void = false;
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
|
||||
$class = 'simcal-field-select';
|
||||
|
||||
$enhanced = isset( $field['enhanced'] ) ? $field['enhanced'] : '';
|
||||
if ( 'enhanced' == $enhanced ) {
|
||||
$this->enhanced = true;
|
||||
$class .= ' simcal-field-select-enhanced';
|
||||
}
|
||||
|
||||
$multiselect = isset( $field['multiselect'] ) ? $field['multiselect'] : '';
|
||||
if ( 'multiselect' == $multiselect ) {
|
||||
$this->multiselect = true;
|
||||
$class .= ' simcal-field-multiselect';
|
||||
}
|
||||
|
||||
if ( isset( $field['default'] ) ) {
|
||||
$this->default = $field['default'];
|
||||
}
|
||||
|
||||
$this->type_class = $class;
|
||||
|
||||
$allow_void = isset( $field['allow_void'] ) ? $field['allow_void'] : '';
|
||||
$this->allow_void = 'allow_void' == $allow_void ? true : false;
|
||||
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
if ( $this->multiselect === true && ! is_array( $this->value ) ) {
|
||||
$this->value = explode( ',', $this->value );
|
||||
}
|
||||
|
||||
if ( $this->default ) {
|
||||
if ( empty( $this->value ) || $this->value == '' ) {
|
||||
$this->value = $this->default;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<select name="<?php echo $this->name; ?><?php if ( $this->multiselect === true ) { echo '[]'; } ?>"
|
||||
id="<?php echo $this->id; ?>"
|
||||
style="<?php echo $this->style; ?>"
|
||||
class="<?php echo $this->class; ?>"
|
||||
<?php echo $this->attributes; ?>
|
||||
<?php echo ( $this->multiselect === true ) ? ' multiple="multiple"' : ''; ?>>
|
||||
<?php
|
||||
|
||||
if ( $this->allow_void === true ) {
|
||||
echo '<option value=""' . selected( '', $this->value, false ) . '></option>';
|
||||
}
|
||||
|
||||
foreach ( $this->options as $option => $name ) {
|
||||
if ( is_array( $this->value ) ) {
|
||||
$selected = selected( in_array( $option, $this->value ), true, false );
|
||||
} else {
|
||||
$selected = selected( $this->value, trim( strval( $option ) ), false );
|
||||
}
|
||||
echo '<option value="' . $option . '" ' . $selected . '>' . esc_attr( $name ) . '</option>';
|
||||
}
|
||||
|
||||
?>
|
||||
</select>
|
||||
<?php
|
||||
|
||||
echo $this->tooltip;
|
||||
|
||||
if ( ! empty( $this->description ) ) {
|
||||
echo '<p class="description">' . wp_kses_post( $this->description ) . '</p>';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Standard Field
|
||||
*
|
||||
* @package SimpleCalendar/Admin
|
||||
*/
|
||||
namespace SimpleCalendar\Admin\Fields;
|
||||
|
||||
use SimpleCalendar\Abstracts\Field;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard input field.
|
||||
*
|
||||
* For standard text inputs and subtypes (e.g. number, password, email...).
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Standard extends Field {
|
||||
|
||||
/**
|
||||
* Field subtype.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $subtype = '';
|
||||
|
||||
/**
|
||||
* Construct.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*
|
||||
* @param array $field
|
||||
*/
|
||||
public function __construct( $field ) {
|
||||
|
||||
$this->subtype = isset( $field['subtype'] ) ? esc_attr( $field['subtype'] ) : 'text';
|
||||
$this->type_class = 'simcal-field-' . $this->subtype;
|
||||
|
||||
parent::__construct( $field );
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the field markup.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
public function html() {
|
||||
|
||||
?>
|
||||
<input type="<?php echo $this->subtype; ?>"
|
||||
name="<?php echo $this->name; ?>"
|
||||
id="<?php echo $this->id; ?>"
|
||||
value="<?php echo $this->value; ?>"
|
||||
class="<?php echo $this->class; ?>"<?php
|
||||
echo $this->style ? 'style="' . $this->style . '" ' : ' ';
|
||||
echo $this->placeholder ? 'placeholder="' . $this->placeholder . '"' : ' ';
|
||||
echo $this->attributes; ?>/>
|
||||
<?php
|
||||
|
||||
echo $this->tooltip;
|
||||
|
||||
if ( ! empty( $this->description ) ) {
|
||||
echo '<p class="description">' . wp_kses_post( $this->description ) . '</p>';
|
||||
}
|
||||
|
||||
if ( is_string( $this->validation ) && ! empty ( $this->validation ) ) {
|
||||
echo $this->validation;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||