diff --git a/Zotlabs/Lib/Apps.php b/Zotlabs/Lib/Apps.php
index ed06943a1..20556212a 100644
--- a/Zotlabs/Lib/Apps.php
+++ b/Zotlabs/Lib/Apps.php
@@ -264,6 +264,8 @@ class Apps {
if(! $papp['photo'])
$papp['photo'] = z_root() . '/' . get_default_profile_photo(80);
+ self::translate_system_apps($papp);
+
$papp['papp'] = self::papp_encode($papp);
if(! strstr($papp['url'],'://'))
diff --git a/Zotlabs/Module/Wiki.php b/Zotlabs/Module/Wiki.php
index f1f7b87b2..9e7d151b5 100644
--- a/Zotlabs/Module/Wiki.php
+++ b/Zotlabs/Module/Wiki.php
@@ -72,7 +72,8 @@ class Wiki extends \Zotlabs\Web\Controller {
switch (argc()) {
case 2:
// Configure page template
- $wikiheader = t('Wiki Sandbox');
+ $wikiheaderName = t('Wiki');
+ $wikiheaderPage = t('Sandbox');
$content = '"# Wiki Sandbox\n\nContent you **edit** and **preview** here *will not be saved*."';
$hide_editor = false;
$showPageControls = false;
@@ -113,7 +114,8 @@ class Wiki extends \Zotlabs\Web\Controller {
} else {
$wiki_editor = true;
}
- $wikiheader = urldecode($wikiUrlName) . ': ' . urldecode($pageUrlName); // show wiki name and page
+ $wikiheaderName = urldecode($wikiUrlName);
+ $wikiheaderPage = urldecode($pageUrlName);
$p = wiki_get_page_content(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName));
if(!$p['success']) {
notice('Error retrieving page content' . EOL);
@@ -135,7 +137,8 @@ class Wiki extends \Zotlabs\Web\Controller {
require_once('library/markdown.php');
$o .= replace_macros(get_markup_template('wiki.tpl'),array(
- '$wikiheader' => $wikiheader,
+ '$wikiheaderName' => $wikiheaderName,
+ '$wikiheaderPage' => $wikiheaderPage,
'$hideEditor' => $hide_editor,
'$showPageControls' => $showPageControls,
'$showNewWikiButton'=> $showNewWikiButton,
@@ -152,6 +155,7 @@ class Wiki extends \Zotlabs\Web\Controller {
'$renderedContent' => Markdown(json_decode($content)),
'$wikiName' => array('wikiName', t('Enter the name of your new wiki:'), '', ''),
'$pageName' => array('pageName', t('Enter the name of the new page:'), '', ''),
+ '$pageRename' => array('pageRename', t('Enter the new name:'), '', ''),
'$commitMsg' => array('commitMsg', '', '', '', '', 'placeholder="(optional) Enter a custom message when saving the page..."'),
'$pageHistory' => $pageHistory['history']
));
@@ -377,7 +381,7 @@ class Wiki extends \Zotlabs\Web\Controller {
if($deleted['success']) {
$ob = \App::get_observer();
$commit = wiki_git_commit(array(
- 'commit_msg' => 'Deleted ' . $pageHtmlName,
+ 'commit_msg' => 'Deleted ' . $pageUrlName,
'resource_id' => $resource_id,
'observer' => $ob,
'files' => null
@@ -416,6 +420,48 @@ class Wiki extends \Zotlabs\Web\Controller {
}
}
+ // Rename a page
+ if ((argc() === 4) && (argv(2) === 'rename') && (argv(3) === 'page')) {
+ $resource_id = $_POST['resource_id'];
+ $pageUrlName = $_POST['oldName'];
+ $pageNewName = $_POST['newName'];
+ if ($pageUrlName === 'Home') {
+ json_return_and_die(array('message' => 'Cannot rename Home','success' => false));
+ }
+ if(urlencode(escape_tags($pageNewName)) === '') {
+ json_return_and_die(array('message' => 'Error renaming page. Invalid name.', 'success' => false));
+ }
+ // Determine if observer has permission to rename pages
+ $nick = argv(1);
+ $channel = get_channel_by_nick($nick);
+ if (local_channel() !== intval($channel['channel_id'])) {
+ $observer_hash = get_observer_hash();
+ $perms = wiki_get_permissions($resource_id, intval($channel['channel_id']), $observer_hash);
+ if(!$perms['write']) {
+ logger('Wiki write permission denied. ' . EOL);
+ json_return_and_die(array('success' => false));
+ }
+ }
+ $renamed = wiki_rename_page(array('resource_id' => $resource_id, 'pageUrlName' => $pageUrlName, 'pageNewName' => $pageNewName));
+ logger('$renamed: ' . json_encode($renamed));
+ if($renamed['success']) {
+ $ob = \App::get_observer();
+ $commit = wiki_git_commit(array(
+ 'commit_msg' => 'Renamed ' . urldecode($pageUrlName) . ' to ' . $renamed['page']['htmlName'],
+ 'resource_id' => $resource_id,
+ 'observer' => $ob,
+ 'files' => array($pageUrlName . '.md', $renamed['page']['fileName']),
+ 'all' => true
+ ));
+ if($commit['success']) {
+ json_return_and_die(array('name' => $renamed['page'], 'message' => 'Wiki git repo commit made', 'success' => true));
+ } else {
+ json_return_and_die(array('message' => 'Error making git commit','success' => false));
+ }
+ } else {
+ json_return_and_die(array('message' => 'Error renaming page', 'success' => false));
+ }
+ }
//notice('You must be authenticated.');
json_return_and_die(array('message' => 'You must be authenticated.', 'success' => false));
diff --git a/include/bbcode.php b/include/bbcode.php
index 63a475779..b720355af 100644
--- a/include/bbcode.php
+++ b/include/bbcode.php
@@ -491,6 +491,12 @@ function bb_code($match) {
return '' . trim($match[1]) . '
';
}
+function bb_highlight($match) {
+ if(in_array(strtolower($match[1]),['php','css','mysql','sql','abap','diff','html','perl','ruby',
+ 'vbscript','avrc','dtd','java','xml','cpp','python','javascript','js','sh']))
+ return text_highlight($match[2],strtolower($match[1]));
+ return $match[0];
+}
// BBcode 2 HTML was written by WAY2WEB.net
@@ -566,6 +572,15 @@ function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false)
$Text = str_replace(">", ">", $Text);
+ // Check for [code] text here, before the linefeeds are messed with.
+ // The highlighter will unescape and re-escape the content.
+
+ if (strpos($Text,'[code=') !== false) {
+ $Text = preg_replace_callback("/\[code=(.*?)\](.*?)\[\/code\]/ism", 'bb_highlight', $Text);
+ }
+
+
+
// Convert new line chars to html
tags
// nlbr seems to be hopelessly messed up
diff --git a/include/network.php b/include/network.php
index 0dd10e29b..a595a03d1 100644
--- a/include/network.php
+++ b/include/network.php
@@ -21,15 +21,16 @@ function get_capath() {
* TRUE if asked to return binary results (file download)
* @param int $redirects default 0
* internal use, recursion counter
- * @param array $opts (optional parameters) assoziative array with:
+ * @param array $opts (optional parameters) associative array with:
* * \b accept_content => supply Accept: header with 'accept_content' as the value
* * \b timeout => int seconds, default system config value or 60 seconds
* * \b http_auth => username:password
* * \b novalidate => do not validate SSL certs, default is to validate using our CA list
* * \b nobody => only return the header
* * \b filep => stream resource to write body to. header and body are not returned when using this option.
+ * * \b custom => custom request method: e.g. 'PUT', 'DELETE'
*
- * @return array an assoziative array with:
+ * @return array an associative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
@@ -65,6 +66,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
+ if(x($opts,'custom'))
+ @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
+
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
@@ -165,7 +169,9 @@ function z_fetch_url($url, $binary = false, $redirects = 0, $opts = array()) {
* 'http_auth' => username:password
* 'novalidate' => do not validate SSL certs, default is to validate using our CA list
* 'filep' => stream resource to write body to. header and body are not returned when using this option.
- * @return array an assoziative array with:
+ * 'custom' => custom request method: e.g. 'PUT', 'DELETE'
+ *
+ * @return array an associative array with:
* * \e int \b return_code => HTTP return code or 0 if timeout or failure
* * \e boolean \b success => boolean true (if HTTP 2xx result) or false
* * \e string \b header => HTTP headers
@@ -205,6 +211,10 @@ logger('headers: ' . print_r($opts['headers'],true) . 'redir: ' . $redirects);
if(x($opts,'nobody'))
@curl_setopt($ch, CURLOPT_NOBODY, $opts['nobody']);
+ if(x($opts,'custom'))
+ @curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $opts['custom']);
+
+
if(x($opts,'timeout') && intval($opts['timeout'])) {
@curl_setopt($ch, CURLOPT_TIMEOUT, $opts['timeout']);
}
diff --git a/include/text.php b/include/text.php
index bd59aa732..50a3d8892 100644
--- a/include/text.php
+++ b/include/text.php
@@ -2881,3 +2881,48 @@ function flatten_array_recursive($arr) {
}
return($ret);
}
+
+function text_highlight($s,$lang) {
+
+ if($lang === 'js')
+ $lang = 'javascript';
+
+ if(! strpos('Text_Highlighter',get_include_path())) {
+ set_include_path(get_include_path() . PATH_SEPARATOR . 'library/Text_Highlighter');
+ }
+ require_once('library/Text_Highlighter/Text/Highlighter.php');
+ require_once('library/Text_Highlighter/Text/Highlighter/Renderer/Html.php');
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 4,
+ );
+ $tag_added = false;
+ $s = trim(html_entity_decode($s,ENT_COMPAT));
+ $s = str_replace(" ","\t",$s);
+
+ // The highlighter library insists on an opening php tag for php code blocks. If
+ // it isn't present, nothing is highlighted. So we're going to see if it's present.
+ // If not, we'll add it, and then quietly remove it after we get the processed output back.
+
+ if($lang === 'php') {
+ if(strpos('setRenderer($renderer);
+ $o = $hl->highlight($s);
+ $o = str_replace([" ","\n"],[" ",''],$o);
+
+ if($tag_added) {
+ $b = substr($o,0,strpos($o,'
'));
+ $e = substr($o,strpos($o,''));
+ $o = $b . $e;
+ }
+
+ return('' . $o . '
');
+}
+
diff --git a/include/wiki.php b/include/wiki.php
index 4aa3fc1b4..d60f4a3a7 100644
--- a/include/wiki.php
+++ b/include/wiki.php
@@ -231,6 +231,34 @@ function wiki_create_page($name, $resource_id) {
}
+function wiki_rename_page($arr) {
+ $pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
+ $pageNewName = ((array_key_exists('pageNewName',$arr)) ? $arr['pageNewName'] : '');
+ $resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
+ $w = wiki_get_wiki($resource_id);
+ if (!$w['path']) {
+ return array('message' => 'Wiki not found.', 'success' => false);
+ }
+ $page_path_old = $w['path'].'/'.$pageUrlName.'.md';
+ logger('$page_path_old: ' . $page_path_old);
+ if (!is_readable($page_path_old) === true) {
+ return array('message' => 'Cannot read wiki page: ' . $page_path_old, 'success' => false);
+ }
+ $page = array('rawName' => $pageNewName, 'htmlName' => escape_tags($pageNewName), 'urlName' => urlencode(escape_tags($pageNewName)), 'fileName' => urlencode(escape_tags($pageNewName)).'.md');
+ $page_path_new = $w['path'] . '/' . $page['fileName'] ;
+ logger('$page_path_new: ' . $page_path_new);
+ if (is_file($page_path_new)) {
+ return array('message' => 'Page already exists.', 'success' => false);
+ }
+ // Rename the page file in the wiki repo
+ if(!rename($page_path_old, $page_path_new)) {
+ return array('message' => 'Error renaming page file.', 'success' => false);
+ } else {
+ return array('page' => $page, 'message' => '', 'success' => true);
+ }
+
+}
+
function wiki_get_page_content($arr) {
$pageUrlName = ((array_key_exists('pageUrlName',$arr)) ? $arr['pageUrlName'] : '');
$resource_id = ((array_key_exists('resource_id',$arr)) ? $arr['resource_id'] : '');
@@ -342,7 +370,7 @@ function wiki_revert_page($arr) {
}
}
} catch (\PHPGit\Exception\GitException $e) {
- json_return_and_die(array('content' => $content, 'message' => 'GitRepo error thrown', 'success' => false));
+ return array('content' => $content, 'message' => 'GitRepo error thrown', 'success' => false);
}
return array('content' => $content, 'message' => '', 'success' => true);
} else {
@@ -352,9 +380,18 @@ function wiki_revert_page($arr) {
function wiki_git_commit($arr) {
$files = ((array_key_exists('files', $arr)) ? $arr['files'] : null);
+ $all = ((array_key_exists('all', $arr)) ? $arr['all'] : false);
$commit_msg = ((array_key_exists('commit_msg', $arr)) ? $arr['commit_msg'] : 'Repo updated');
- $resource_id = ((array_key_exists('resource_id', $arr)) ? $arr['resource_id'] : json_return_and_die(array('message' => 'Wiki resource_id required for git commit', 'success' => false)));
- $observer = ((array_key_exists('observer', $arr)) ? $arr['observer'] : json_return_and_die(array('message' => 'Observer required for git commit', 'success' => false)));
+ if(array_key_exists('resource_id', $arr)) {
+ $resource_id = $arr['resource_id'];
+ } else {
+ return array('message' => 'Wiki resource_id required for git commit', 'success' => false);
+ }
+ if(array_key_exists('observer', $arr)) {
+ $observer = $arr['observer'];
+ } else {
+ return array('message' => 'Observer required for git commit', 'success' => false);
+ }
$w = wiki_get_wiki($resource_id);
if (!$w['path']) {
return array('message' => 'Error reading wiki', 'success' => false);
@@ -369,23 +406,23 @@ function wiki_git_commit($arr) {
if ($files === null) {
$options = array('all' => true); // git commit option to include all changes
} else {
- $options = array(); // git commit options
+ $options = array('all' => $all); // git commit options\
foreach ($files as $file) {
if (!$git->git->add($file)) { // add specified files to the git repo stage
if (!$git->git->reset->hard()) {
- json_return_and_die(array('message' => 'Error adding file to git stage: ' . $file . '. Error resetting git repo.', 'success' => false));
+ return array('message' => 'Error adding file to git stage: ' . $file . '. Error resetting git repo.', 'success' => false);
}
- json_return_and_die(array('message' => 'Error adding file to git stage: ' . $file, 'success' => false));
+ return array('message' => 'Error adding file to git stage: ' . $file, 'success' => false);
}
}
}
if ($git->commit($commit_msg, $options)) {
- json_return_and_die(array('message' => 'Wiki repo commit succeeded', 'success' => true));
+ return array('message' => 'Wiki repo commit succeeded', 'success' => true);
} else {
- json_return_and_die(array('message' => 'Wiki repo commit failed', 'success' => false));
+ return array('message' => 'Wiki repo commit failed', 'success' => false);
}
} catch (\PHPGit\Exception\GitException $e) {
- json_return_and_die(array('message' => 'GitRepo error thrown', 'success' => false));
+ return array('message' => 'GitRepo error thrown', 'success' => false);
}
}
diff --git a/library/Text_Highlighter/README b/library/Text_Highlighter/README
new file mode 100644
index 000000000..88f71aed2
--- /dev/null
+++ b/library/Text_Highlighter/README
@@ -0,0 +1,455 @@
+# $Id$
+
+Introduction
+============
+
+Text_Highlighter is a class for syntax highlighting. The main idea is to
+simplify creation of subclasses implementing syntax highlighting for
+particular language. Subclasses do not implement any new functioanality, they
+just provide syntax highlighting rules. The rules sources are in XML format.
+To create a highlighter for a language, there is no need to code a new class
+manually. Simply describe the rules in XML file and use Text_Highlighter_Generator
+to create a new class.
+
+
+This document does not contain a formal description of API - it is very
+simple, and I believe providing some examples of code is sufficient.
+
+
+Highlighter XML source
+======================
+
+Basics
+------
+
+Creating a new syntax highlighter begins with describing the highlighting
+rules. There are two basic elements: block and region. A block is just a
+portion of text matching a regular expression and highlighted with a single
+color. Keyword is an example of a block. A region is defined by two regular
+expressions: one for start of region, and another for the end. The main
+difference from a block is that a region can contain blocks and regions
+(including same-named regions). An example of a region is a group of
+statements enclosed in curly brackets (this is used in many languages, for
+example PHP and C). Also, characters matching start and end of a region may be
+highlighted with their own color, and region contents with another.
+
+Blocks and regions may be declared as contained. Contained blocks and regions
+can only appear inside regions. If a region or a block is not declared as
+contained, it can appear both on top level and inside regions. Block or region
+declared as not-contained can only appear on top level.
+
+For any region, a list of blocks and regions that can appear inside this
+region can be specified.
+
+In this document, the term "color group" is used. Chunks of text assigned to
+same color group will be highlighted with same color. Note that in versions
+prior 0.5.0 color goups were refered as CSS classes, but since 0.5.0 not only
+HTML output is supported, so "color group" is more appropriate term.
+
+Elements
+--------
+
+The toplevel element is . Attribute lang is required and denotes
+the name of the language. Its value is used as a part of generated class name,
+and must only contain letters, digits and underscores. Optional attribute
+case, when given value yes, makes the language case sensitive (default is case
+insensitive). Allowed subelements are:
+
+ * : Information about the authors of the file.
+ : Information about a single author of the file. (May be used
+ multiple times, one per author.)
+ - name="...": Author's name. Required.
+ - email="...": Author's email address. Optional.
+
+ * : Default color group.
+ - innerGroup="...": color group name. Required.
+
+ * : Region definition
+ - name="...": Region name. Required.
+ - innerGroup="...": Default color group of region contents. Required.
+ - delimGroup="...": color group of start and end of region. Optional,
+ defaults to value of innerGroup attribute.
+ - start="...", end="...": Regular expression matching start and end
+ of region. Required. Regular expression delimiters are optional, but
+ if you need to specify delimiter, use /. The only case when the
+ delimiters are needed, is specifying regular expression modifiers,
+ such as m or U. Examples: \/\* or /$/m.
+ - contained="yes": Marks region as contained.
+ - never-contained="yes": Marks region as not-contained.
+ - : Elements allowed inside this region.
+ - all="yes" Region can contain any other region or block
+ (except not-contained). May be used multiple times.
+ - Do not allow certain regions or blocks.
+ - region="..." Name of region not allowed within
+ current region.
+ - block="..." Name of block not allowed within
+ current region.
+ - region="..." Name of region allowed within current region.
+ - block="..." Name of block allowed within current region.
+ - Only allow this region within certain regions. May be
+ used multiple times.
+ - block="..." Name of parent region
+
+ * : Block definition
+ - name="...": Block name. Required.
+ - innerGroup="...": color group of block contents. Optional. If not
+ specified, color group of parent region or default color group will be
+ used. One would only want to omit this attribute if there are
+ keyword groups (see below) inherited from this block, and no special
+ highlighting should apply when the block does not match the keyword.
+ - match="..." Regular expression matching the block. Required.
+ Regular expression delimiters are optional, but if you need to
+ specify delimiter, use /. The only case when the delimiters are
+ needed, is specifying regular expression modifiers, such as m or U.
+ Examples: #|\/\/ or /$/m.
+ - contained="yes": Marks block as contained.
+ - never-contained="yes": Marks block as not-contained.
+ - Only allow this block within certain regions. May be used
+ multiple times.
+ - block="..." Name of parent region
+ - multiline="yes": Marks block as multi-line. By default, whole
+ blocks are assumed to reside in a single line. This make the things
+ faster. If you need to declare a multi-line block, use this
+ attribute.
+ - : Assigns another color group to a part of the block that
+ matched a subpattern.
+ - index="n": Subpattern index. Required.
+ - innerGroup="...": color group name. Required.
+
+ This is an example from CSS highlighter: the measure is matched as
+ a whole, but the measurement units are highlighted with different
+ color.
+
+
+
+
+
+
+ * : Keyword group definition. Keyword groups are useful when you
+ want to highlight some words that match a condition for a block with a
+ different color. Keywords are defined with literal match, not regular
+ expressions. For example, you have a block named identifier matching a
+ general identifier, and want to highlight reserved words (which match
+ this block as well) with different color. You inherit a keyword group
+ "reserved" from "identifier" block.
+ - name="...": Keyword group. Required.
+ - ifdef="...", ifndef="..." : Conditional declaration. See
+ "Conditions" below.
+ - inherits="...": Inherited block name. Required.
+ - innerGroup="...": color group of keyword group. Required.
+ - case="yes|no": Overrides case-sensitivity of the language.
+ Optional, defaults to global value.
+ - : Single keyword definition.
+ - match="..." The keyword. Note: this is not a regular
+ expression, but literal match (possibly case insensitive).
+
+Note that for BC reasons element partClass is alias for partGroup, and
+attributes innerClass and delimClass are aliases of innerGroup and
+delimGroup, respectively.
+
+
+Conditions
+----------
+
+Conditional declarations allow enabling or disabling certain highlighting
+rules at runtime. For example, Java highlighter has a very big list of
+keywords matching Java standard classes. Finding a match in this list can take
+much time. For that reason, corresponding keyword group is declared with
+"ifdef" attribute :
+
+
+
+
+
+ ...
+ ...
+
+
+
+
+
+This keyword group will be only enabled when "java.builtins" is passed as an
+element of "defines" option:
+
+ $options = array(
+ 'defines' => array(
+ 'java.builtins',
+ ),
+ 'numbers' => HL_NUMBERS_TABLE,
+ );
+ $highlighter = Text_Highlighter::factory('java', $options);
+
+"ifndef" attribute has reverse meaning.
+
+Currently, "ifdef" and "ifndef" attributes are only supported for
+tag.
+
+
+
+Class generation
+================
+
+Creating XML description of highlighting rules is the most complicated part of
+the process. To generate the class, you need just few lines of code:
+
+ generate();
+ $generator->saveCode('PHP.php');
+ ?>
+
+
+
+Command-line class generation tool
+==================================
+
+Example from previous section looks pretty simple, but it does not handle any
+errors which may occur during parsing of XML source. The package provides a
+command-line script to make generation of classes even more simple, and takes
+care of possible errors. It is called generate (on Unix/Linux) or generate.bat
+(on Windows). This script is able to process multiple files in one run, and
+also to process XML from standard input and write generated code to standard
+output.
+
+ Usage:
+ generate options
+
+ Options:
+ -x filename, --xml=filename
+ source XML file. Multiple input files can be specified, in which
+ case each -x option must be followed by -p unless -d is specified
+ Defaults to stdin
+ -p filename, --php=filename
+ destination PHP file. Defaults to stdout. If specied multiple times,
+ each -p must follow -x
+ -d dirname, --dir=dirname
+ Default destination directory. File names will be taken from XML input
+ ("lang" attribute of tag)
+ -h, --help
+ This help
+
+Examples
+
+ Read from php.xml, write to PHP.php
+
+ generate -x php.xml -p PHP.php
+
+ Read from php.xml, write to standard output
+
+ generate -x php.xml
+
+ Read from php.xml, write to PHP.php, read from xml.xml, write to XML.php
+
+ generate -x php.xml -p PHP.php -x xml.xml -p XML.php
+
+ Read from php.xml, write to /some/dir/PHP.php, read from xml.xml, write to
+ /some/dir/XML.php (assuming that xml.xml contains , and
+ php.xml contains )
+
+ generate -x php.xml -x xml.xml -d /some/dir/
+
+
+
+Renderers
+=========
+
+Introduction
+------------
+
+Text_Highlighter supports renderes. Using renderers, you can get output in
+different formats. Two renderers are included in the package:
+
+ - HTML renderer. Generates HTML output. A style sheet should be linked to
+ the document to display colored text
+
+ - Console renderer. Can be used to output highlighted text to
+ color-capable terminals, either directly or trough less -r
+
+
+Renderers API
+-------------
+
+Renderers are subclasses of Text_Highlighter_Renderer. Renderer should
+override at least two methods - acceptToken and getOutput. Overriding other
+methods is optional, depending on the nature of renderer's output and details
+of implementation.
+
+ string reset()
+ resets renderer state. This method is called every time before a new
+ source file is highlighted.
+
+ string preprocess(string $code)
+ preprocesses code. Can be used, for example, to normalize whitespace
+ before highlighting. Returns preprocessed string.
+
+ void acceptToken(string $group, string $content)
+ the core method of the renderer. Highlighter passes chunks of text to
+ this method in $content, and color group in $group
+
+ void finalize()
+ signals the renderer that no more tokens are available.
+
+ mixed getOutput()
+ returns generated output.
+
+
+Setting renderer options
+--------------------------------
+
+Renderers accept an optional argument to their constructor - options array.
+Elements of this array are renderer-specific.
+
+HTML renderer
+-------------
+
+HTML renderer produces HTML output with optional line numbering. The renderer
+itself does not provide information about actual colors of highlighted text.
+Instead, is used, where XXX is replaced with color group
+name (hl-var, hl-string, etc.). It is up to you to create a CSS stylesheet.
+If 'use_language' option with value evaluating to true was passed, class names
+will be formatted as "LANG-hl-XXX", where LANG is language name as defined in
+highlighter XML source ("lang" attribute of tag) in lower case.
+
+There are 3 special CSS classes:
+
+ hl-main - this class applies to whole output or right table column,
+ depending on 'numbers' option
+ hl-gutter - applies to left column in table
+ hl-table - applies to whole table
+
+HTML renderer accepts following options (each being optional):
+
+ * numbers - line numbering style.
+ 0 - no numbering (default)
+ HL_NUMBERS_LI - use
for line numbering
+ HL_NUMBERS_TABLE - create a 2-column table, with line numbers in left
+ column and highlighted text in right column
+
+ * tabsize - tabulation size. Defaults to 4
+
+ Example:
+
+ require_once 'Text/Highlighter/Renderer/Html.php';
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 8,
+ );
+ $renderer = new Text_Highlighter_Renderer_HTML($options);
+
+Console renderer
+----------------
+
+Console renderer produces output for displaying on a color-capable terminal,
+either directly or through less -r, using ANSI escape sequences. By default,
+this renderer only highlights most common color groups. Additional colors
+can be specified using 'colors' option. This renderer also accepts 'numbers'
+option - a boolean value, and 'tabsize' option.
+
+ Example :
+
+ require_once 'Text/Highlighter/Renderer/Console.php';
+ $colors = array(
+ 'prepro' => "\033[35m",
+ 'types' => "\033[32m",
+ );
+ $options = array(
+ 'numbers' => true,
+ 'tabsize' => 8,
+ 'colors' => $colors,
+ );
+ $renderer = new Text_Highlighter_Renderer_Console($options);
+
+
+ANSI color escape sequences have the following format:
+
+ ESC[#;#;....;#m
+
+where ESC is character with ASCII code 27 (033 octal, 0x1B hexadecimal). # is
+one of the following:
+
+ 0 for normal display
+ 1 for bold on
+ 4 underline (mono only)
+ 5 blink on
+ 7 reverse video on
+ 8 nondisplayed (invisible)
+ 30 black foreground
+ 31 red foreground
+ 32 green foreground
+ 33 yellow foreground
+ 34 blue foreground
+ 35 magenta foreground
+ 36 cyan foreground
+ 37 white foreground
+ 40 black background
+ 41 red background
+ 42 green background
+ 43 yellow background
+ 44 blue background
+ 45 magenta background
+ 46 cyan background
+ 47 white background
+
+
+How to use Text_Highlighter class
+=================================
+
+Creating a highlighter object
+-----------------------------
+
+To create a highlighter for a certain language, use Text_Highlighter::factory()
+static method:
+
+ require_once 'Text/Highlighter.php';
+ $hl = Text_Highlighter::factory('php');
+
+
+Setting a renderer
+------------------
+
+Actual output is produced by a renderer.
+
+ require_once 'Text/Highlighter.php';
+ require_once 'Text/Highlighter/Renderer/Html.php';
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 8,
+ );
+ $renderer = new Text_Highlighter_Renderer_HTML($options);
+ $hl = Text_Highlighter::factory('php');
+ $hl->setRenderer($renderer);
+
+Note that for BC reasons, it is possible to use highlighter without setting a
+renderer. If no renderer is set, HTML renderer will be used by default. In
+this case, you should pass options as second parameter to factory method. The
+following example works exactly as previous one:
+
+ require_once 'Text/Highlighter.php';
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 8,
+ );
+ $hl = Text_Highlighter::factory('php', $options);
+
+
+Getting output
+--------------
+
+And finally, do the highlighting and get the output:
+
+ require_once 'Text/Highlighter.php';
+ require_once 'Text/Highlighter/Renderer/Html.php';
+ $options = array(
+ 'numbers' => HL_NUMBERS_LI,
+ 'tabsize' => 8,
+ );
+ $renderer = new Text_Highlighter_Renderer_HTML($options);
+ $hl = Text_Highlighter::factory('php');
+ $hl->setRenderer($renderer);
+ $html = $hl->highlight(file_get_contents('example.php'));
+
+# vim: set autoindent tabstop=4 shiftwidth=4 softtabstop=4 tw=78: */
+
diff --git a/library/Text_Highlighter/TODO b/library/Text_Highlighter/TODO
new file mode 100644
index 000000000..77a148b8a
--- /dev/null
+++ b/library/Text_Highlighter/TODO
@@ -0,0 +1,12 @@
+# $Id$
+
+Major issues to solve (but I currently have no idea how) :
+
+- speedup highlighting process
+
+- switching between highlighters depending on context, for example :
+ PHP code -> HTML -> (JavaScript|CSS)
+
+
+# vim: set autoindent tabstop=4 shiftwidth=4 softtabstop=4 tw=78: */
+
diff --git a/library/Text_Highlighter/Text/Highlighter.php b/library/Text_Highlighter/Text/Highlighter.php
new file mode 100644
index 000000000..480113c16
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter.php
@@ -0,0 +1,398 @@
+
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+
+// require_once 'PEAR.php';
+
+// {{{ BC constants
+
+// BC trick : define constants related to default
+// renderer if needed
+if (!defined('HL_NUMBERS_LI')) {
+ /**#@+
+ * Constant for use with $options['numbers']
+ * @see Text_Highlighter_Renderer_Html::_init()
+ */
+ /**
+ * use numbered list
+ */
+ define ('HL_NUMBERS_LI' , 1);
+ /**
+ * Use 2-column table with line numbers in left column and code in right column.
+ * Forces $options['tag'] = HL_TAG_PRE
+ */
+ define ('HL_NUMBERS_TABLE' , 2);
+ /**#@-*/
+}
+
+// }}}
+// {{{ constants
+/**
+ * for our purpose, it is infinity
+ */
+define ('HL_INFINITY', 1000000000);
+
+// }}}
+
+/**
+ * Text highlighter base class
+ *
+ * @author Andrey Demenev
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+
+// {{{ Text_Highlighter
+
+/**
+ * Text highlighter base class
+ *
+ * This class implements all functions necessary for highlighting,
+ * but it does not contain highlighting rules. Actual highlighting is
+ * done using a descendent of this class.
+ *
+ * One is not supposed to manually create descendent classes.
+ * Instead, describe highlighting rules in XML format and
+ * use {@link Text_Highlighter_Generator} to create descendent class.
+ * Alternatively, an instance of a descendent class can be created
+ * directly.
+ *
+ * Use {@link Text_Highlighter::factory()} to create an
+ * object for particular language highlighter
+ *
+ * Usage example
+ *
+ *require_once 'Text/Highlighter.php';
+ *$hlSQL = Text_Highlighter::factory('SQL',array('numbers'=>true));
+ *echo $hlSQL->highlight('SELECT * FROM table a WHERE id = 12');
+ *
+ *
+ * @author Andrey Demenev
+ * @package Text_Highlighter
+ * @access public
+ */
+
+class Text_Highlighter
+{
+ // {{{ members
+
+ /**
+ * Syntax highlighting rules.
+ * Auto-generated classes set this var
+ *
+ * @access protected
+ * @see _init
+ * @var array
+ */
+ var $_syntax;
+
+ /**
+ * Renderer object.
+ *
+ * @access private
+ * @var array
+ */
+ var $_renderer;
+
+ /**
+ * Options. Keeped for BC
+ *
+ * @access protected
+ * @var array
+ */
+ var $_options = array();
+
+ /**
+ * Conditionds
+ *
+ * @access protected
+ * @var array
+ */
+ var $_conditions = array();
+
+ /**
+ * Disabled keywords
+ *
+ * @access protected
+ * @var array
+ */
+ var $_disabled = array();
+
+ /**
+ * Language
+ *
+ * @access protected
+ * @var string
+ */
+ var $_language = '';
+
+ // }}}
+ // {{{ _checkDefines
+
+ /**
+ * Called by subclssses' constructors to enable/disable
+ * optional highlighter rules
+ *
+ * @param array $defines Conditional defines
+ *
+ * @access protected
+ */
+ function _checkDefines()
+ {
+ if (isset($this->_options['defines'])) {
+ $defines = $this->_options['defines'];
+ } else {
+ $defines = array();
+ }
+ foreach ($this->_conditions as $name => $actions) {
+ foreach($actions as $action) {
+ $present = in_array($name, $defines);
+ if (!$action[1]) {
+ $present = !$present;
+ }
+ if ($present) {
+ unset($this->_disabled[$action[0]]);
+ } else {
+ $this->_disabled[$action[0]] = true;
+ }
+ }
+ }
+ }
+
+ // }}}
+ // {{{ factory
+
+ /**
+ * Create a new Highlighter object for specified language
+ *
+ * @param string $lang language, for example "SQL"
+ * @param array $options Rendering options. This
+ * parameter is only keeped for BC reasons, use
+ * {@link Text_Highlighter::setRenderer()} instead
+ *
+ * @return mixed a newly created Highlighter object, or
+ * a PEAR error object on error
+ *
+ * @static
+ * @access public
+ */
+ function &factory($lang, $options = array())
+ {
+ $lang = strtoupper($lang);
+ @include_once 'Text/Highlighter/' . $lang . '.php';
+
+ $classname = 'Text_Highlighter_' . $lang;
+
+ if (!class_exists($classname)) {
+ return PEAR::raiseError('Highlighter for ' . $lang . ' not found');
+ }
+
+ $obj = new $classname($options);
+
+ return $obj;
+ }
+
+ // }}}
+ // {{{ setRenderer
+
+ /**
+ * Set renderer object
+ *
+ * @param object $renderer Text_Highlighter_Renderer
+ *
+ * @access public
+ */
+ function setRenderer(&$renderer)
+ {
+ $this->_renderer = $renderer;
+ }
+
+ // }}}
+
+ /**
+ * Helper function to find matching brackets
+ *
+ * @access private
+ */
+ function _matchingBrackets($str)
+ {
+ return strtr($str, '()<>[]{}', ')(><][}{');
+ }
+
+
+
+
+ function _getToken()
+ {
+ if (!empty($this->_tokenStack)) {
+ return array_pop($this->_tokenStack);
+ }
+ if ($this->_pos >= $this->_len) {
+ return NULL;
+ }
+
+ if ($this->_state != -1 && preg_match($this->_endpattern, $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos)) {
+ $endpos = $m[0][1];
+ $endmatch = $m[0][0];
+ } else {
+ $endpos = -1;
+ }
+ preg_match ($this->_regs[$this->_state], $this->_str, $m, PREG_OFFSET_CAPTURE, $this->_pos);
+ $n = 1;
+
+
+ foreach ($this->_counts[$this->_state] as $i=>$count) {
+ if (!isset($m[$n])) {
+ break;
+ }
+ if ($m[$n][1]>-1 && ($endpos == -1 || $m[$n][1] < $endpos)) {
+ if ($this->_states[$this->_state][$i] != -1) {
+ $this->_tokenStack[] = array($this->_delim[$this->_state][$i], $m[$n][0]);
+ } else {
+ $inner = $this->_inner[$this->_state][$i];
+ if (isset($this->_parts[$this->_state][$i])) {
+ $parts = array();
+ $partpos = $m[$n][1];
+ for ($j=1; $j<=$count; $j++) {
+ if ($m[$j+$n][1] < 0) {
+ continue;
+ }
+ if (isset($this->_parts[$this->_state][$i][$j])) {
+ if ($m[$j+$n][1] > $partpos) {
+ array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$j+$n][1]-$partpos)));
+ }
+ array_unshift($parts, array($this->_parts[$this->_state][$i][$j], $m[$j+$n][0]));
+ }
+ $partpos = $m[$j+$n][1] + strlen($m[$j+$n][0]);
+ }
+ if ($partpos < $m[$n][1] + strlen($m[$n][0])) {
+ array_unshift($parts, array($inner, substr($this->_str, $partpos, $m[$n][1] - $partpos + strlen($m[$n][0]))));
+ }
+ $this->_tokenStack = array_merge($this->_tokenStack, $parts);
+ } else {
+ foreach ($this->_keywords[$this->_state][$i] as $g => $re) {
+ if (isset($this->_disabled[$g])) {
+ continue;
+ }
+ if (preg_match($re, $m[$n][0])) {
+ $inner = $this->_kwmap[$g];
+ break;
+ }
+ }
+ $this->_tokenStack[] = array($inner, $m[$n][0]);
+ }
+ }
+ if ($m[$n][1] > $this->_pos) {
+ $this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $m[$n][1]-$this->_pos));
+ }
+ $this->_pos = $m[$n][1] + strlen($m[$n][0]);
+ if ($this->_states[$this->_state][$i] != -1) {
+ $this->_stack[] = array($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern);
+ $this->_lastinner = $this->_inner[$this->_state][$i];
+ $this->_lastdelim = $this->_delim[$this->_state][$i];
+ $l = $this->_state;
+ $this->_state = $this->_states[$this->_state][$i];
+ $this->_endpattern = $this->_end[$this->_state];
+ if ($this->_subst[$l][$i]) {
+ for ($k=0; $k<=$this->_counts[$l][$i]; $k++) {
+ if (!isset($m[$i+$k])) {
+ break;
+ }
+ $quoted = preg_quote($m[$n+$k][0], '/');
+ $this->_endpattern = str_replace('%'.$k.'%', $quoted, $this->_endpattern);
+ $this->_endpattern = str_replace('%b'.$k.'%', $this->_matchingBrackets($quoted), $this->_endpattern);
+ }
+ }
+ }
+ return array_pop($this->_tokenStack);
+ }
+ $n += $count + 1;
+ }
+
+ if ($endpos > -1) {
+ $this->_tokenStack[] = array($this->_lastdelim, $endmatch);
+ if ($endpos > $this->_pos) {
+ $this->_tokenStack[] = array($this->_lastinner, substr($this->_str, $this->_pos, $endpos-$this->_pos));
+ }
+ list($this->_state, $this->_lastdelim, $this->_lastinner, $this->_endpattern) = array_pop($this->_stack);
+ $this->_pos = $endpos + strlen($endmatch);
+ return array_pop($this->_tokenStack);
+ }
+ $p = $this->_pos;
+ $this->_pos = HL_INFINITY;
+ return array($this->_lastinner, substr($this->_str, $p));
+ }
+
+
+
+
+ // {{{ highlight
+
+ /**
+ * Highlights code
+ *
+ * @param string $str Code to highlight
+ * @access public
+ * @return string Highlighted text
+ *
+ */
+
+ function highlight($str)
+ {
+ if (!($this->_renderer)) {
+ include_once('Text/Highlighter/Renderer/Html.php');
+ $this->_renderer = new Text_Highlighter_Renderer_Html($this->_options);
+ }
+ $this->_state = -1;
+ $this->_pos = 0;
+ $this->_stack = array();
+ $this->_tokenStack = array();
+ $this->_lastinner = $this->_defClass;
+ $this->_lastdelim = $this->_defClass;
+ $this->_endpattern = '';
+ $this->_renderer->reset();
+ $this->_renderer->setCurrentLanguage($this->_language);
+ $this->_str = $this->_renderer->preprocess($str);
+ $this->_len = strlen($this->_str);
+ while ($token = $this->_getToken()) {
+ $this->_renderer->acceptToken($token[0], $token[1]);
+ }
+ $this->_renderer->finalize();
+ return $this->_renderer->getOutput();
+ }
+
+ // }}}
+
+}
+
+// }}}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * c-hanging-comment-ender-p: nil
+ * End:
+ */
+
+?>
diff --git a/library/Text_Highlighter/Text/Highlighter/ABAP.php b/library/Text_Highlighter/Text/Highlighter/ABAP.php
new file mode 100644
index 000000000..b2f7bda94
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter/ABAP.php
@@ -0,0 +1,519 @@
+
+ *
+ */
+
+/**
+ * @ignore
+ */
+
+require_once 'Text/Highlighter.php';
+
+/**
+ * Auto-generated class. ABAP syntax highlighting
+ *
+ * @author Stoyan Stefanov
+ * @category Text
+ * @package Text_Highlighter
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+class Text_Highlighter_ABAP extends Text_Highlighter
+{
+ var $_language = 'abap';
+
+ /**
+ * PHP4 Compatible Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function Text_Highlighter_ABAP($options=array())
+ {
+ $this->__construct($options);
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function __construct($options=array())
+ {
+
+ $this->_options = $options;
+ $this->_regs = array (
+ -1 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)[a-z_\\-]\\w*)/',
+ 0 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)0[xX][\\da-f]+)|((?i)\\d\\d*|\\b0\\b)|((?i)0[0-7]+)|((?i)(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)[a-z_\\-]\\w*)/',
+ 1 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)0[xX][\\da-f]+)|((?i)\\d\\d*|\\b0\\b)|((?i)0[0-7]+)|((?i)(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)[a-z_\\-]\\w*)/',
+ 2 => '/((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)^\\*|")|((?i)\')|((?i)0[xX][\\da-f]+)|((?i)\\d\\d*|\\b0\\b)|((?i)0[0-7]+)|((?i)(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)[a-z_\\-]\\w*)/',
+ 3 => '//',
+ 4 => '//',
+ );
+ $this->_counts = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ ),
+ 0 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ ),
+ 1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_delim = array (
+ -1 =>
+ array (
+ 0 => 'brackets',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'comment',
+ 4 => 'quotes',
+ 5 => '',
+ ),
+ 0 =>
+ array (
+ 0 => 'brackets',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'comment',
+ 4 => 'quotes',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => '',
+ ),
+ 1 =>
+ array (
+ 0 => 'brackets',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'comment',
+ 4 => 'quotes',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => '',
+ ),
+ 2 =>
+ array (
+ 0 => 'brackets',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'comment',
+ 4 => 'quotes',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => '',
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_inner = array (
+ -1 =>
+ array (
+ 0 => 'code',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'comment',
+ 4 => 'string',
+ 5 => 'identifier',
+ ),
+ 0 =>
+ array (
+ 0 => 'code',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'comment',
+ 4 => 'string',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'identifier',
+ ),
+ 1 =>
+ array (
+ 0 => 'code',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'comment',
+ 4 => 'string',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'identifier',
+ ),
+ 2 =>
+ array (
+ 0 => 'code',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'comment',
+ 4 => 'string',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'identifier',
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_end = array (
+ 0 => '/(?i)\\}/',
+ 1 => '/(?i)\\)/',
+ 2 => '/(?i)\\]/',
+ 3 => '/(?mi)$/',
+ 4 => '/(?i)\'/',
+ );
+ $this->_states = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => -1,
+ ),
+ 0 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => -1,
+ ),
+ 1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => -1,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => 4,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => -1,
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_keywords = array (
+ -1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 => -1,
+ 5 =>
+ array (
+ 'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
+ 'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
+ 'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
+ ),
+ ),
+ 0 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 => -1,
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 =>
+ array (
+ 'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
+ 'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
+ 'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
+ ),
+ ),
+ 1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 => -1,
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 =>
+ array (
+ 'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
+ 'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
+ 'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
+ ),
+ ),
+ 2 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 => -1,
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 =>
+ array (
+ 'sy' => '/^((?i)screen-name|screen-group1|screen-group2|screen-group3|screen-group4|screen-required|screen-input|screen-output|screen-intensified|screen-invisible|screen-length|screen-active|sy-index|sy-pagno|sy-tabix|sy-tfill|sy-tlopc|sy-tmaxl|sy-toccu|sy-ttabc|sy-tstis|sy-ttabi|sy-dbcnt|sy-fdpos|sy-colno|sy-linct|sy-linno|sy-linsz|sy-pagct|sy-macol|sy-marow|sy-tleng|sy-sfoff|sy-willi|sy-lilli|sy-subrc|sy-fleng|sy-cucol|sy-curow|sy-lsind|sy-listi|sy-stepl|sy-tpagi|sy-winx1|sy-winy1|sy-winx2|sy-winy2|sy-winco|sy-winro|sy-windi|sy-srows|sy-scols|sy-loopc|sy-folen|sy-fodec|sy-tzone|sy-dayst|sy-ftype|sy-appli|sy-fdayw|sy-ccurs|sy-ccurt|sy-debug|sy-ctype|sy-input|sy-langu|sy-modno|sy-batch|sy-binpt|sy-calld|sy-dynnr|sy-dyngr|sy-newpa|sy-pri40|sy-rstrt|sy-wtitl|sy-cpage|sy-dbnam|sy-mandt|sy-prefx|sy-fmkey|sy-pexpi|sy-prini|sy-primm|sy-prrel|sy-playo|sy-prbig|sy-playp|sy-prnew|sy-prlog|sy-pdest|sy-plist|sy-pauth|sy-prdsn|sy-pnwpa|sy-callr|sy-repi2|sy-rtitl|sy-prrec|sy-prtxt|sy-prabt|sy-lpass|sy-nrpag|sy-paart|sy-prcop|sy-batzs|sy-bspld|sy-brep4|sy-batzo|sy-batzd|sy-batzw|sy-batzm|sy-ctabl|sy-dbsys|sy-dcsys|sy-macdb|sy-sysid|sy-opsys|sy-pfkey|sy-saprl|sy-tcode|sy-ucomm|sy-cfwae|sy-chwae|sy-spono|sy-sponr|sy-waers|sy-cdate|sy-datum|sy-slset|sy-subty|sy-subcs|sy-group|sy-ffile|sy-uzeit|sy-dsnam|sy-repid|sy-tabid|sy-tfdsn|sy-uname|sy-lstat|sy-abcde|sy-marky|sy-sfnam|sy-tname|sy-msgli|sy-title|sy-entry|sy-lisel|sy-uline|sy-xcode|sy-cprog|sy-xprog|sy-xform|sy-ldbpg|sy-tvar0|sy-tvar1|sy-tvar2|sy-tvar3|sy-tvar4|sy-tvar5|sy-tvar6|sy-tvar7|sy-tvar8|sy-tvar9|sy-msgid|sy-msgty|sy-msgno|sy-msgv1|sy-msgv2|sy-msgv3|sy-msgv4|sy-oncom|sy-vline|sy-winsl|sy-staco|sy-staro|sy-datar|sy-host|sy-locdb|sy-locop|sy-datlo|sy-timlo|sy-zonlo|syst-index|syst-pagno|syst-tabix|syst-tfill|syst-tlopc|syst-tmaxl|syst-toccu|syst-ttabc|syst-tstis|syst-ttabi|syst-dbcnt|syst-fdpos|syst-colno|syst-linct|syst-linno|syst-linsz|syst-pagct|syst-macol|syst-marow|syst-tleng|syst-sfoff|syst-willi|syst-lilli|syst-subrc|syst-fleng|syst-cucol|syst-curow|syst-lsind|syst-listi|syst-stepl|syst-tpagi|syst-winx1|syst-winy1|syst-winx2|syst-winy2|syst-winco|syst-winro|syst-windi|syst-srows|syst-scols|syst-loopc|syst-folen|syst-fodec|syst-tzone|syst-dayst|syst-ftype|syst-appli|syst-fdayw|syst-ccurs|syst-ccurt|syst-debug|syst-ctype|syst-input|syst-langu|syst-modno|syst-batch|syst-binpt|syst-calld|syst-dynnr|syst-dyngr|syst-newpa|syst-pri40|syst-rstrt|syst-wtitl|syst-cpage|syst-dbnam|syst-mandt|syst-prefx|syst-fmkey|syst-pexpi|syst-prini|syst-primm|syst-prrel|syst-playo|syst-prbig|syst-playp|syst-prnew|syst-prlog|syst-pdest|syst-plist|syst-pauth|syst-prdsn|syst-pnwpa|syst-callr|syst-repi2|syst-rtitl|syst-prrec|syst-prtxt|syst-prabt|syst-lpass|syst-nrpag|syst-paart|syst-prcop|syst-batzs|syst-bspld|syst-brep4|syst-batzo|syst-batzd|syst-batzw|syst-batzm|syst-ctabl|syst-dbsys|syst-dcsys|syst-macdb|syst-sysid|syst-opsys|syst-pfkey|syst-saprl|syst-tcode|syst-ucomm|syst-cfwae|syst-chwae|syst-spono|syst-sponr|syst-waers|syst-cdate|syst-datum|syst-slset|syst-subty|syst-subcs|syst-group|syst-ffile|syst-uzeit|syst-dsnam|syst-repid|syst-tabid|syst-tfdsn|syst-uname|syst-lstat|syst-abcde|syst-marky|syst-sfnam|syst-tname|syst-msgli|syst-title|syst-entry|syst-lisel|syst-uline|syst-xcode|syst-cprog|syst-xprog|syst-xform|syst-ldbpg|syst-tvar0|syst-tvar1|syst-tvar2|syst-tvar3|syst-tvar4|syst-tvar5|syst-tvar6|syst-tvar7|syst-tvar8|syst-tvar9|syst-msgid|syst-msgty|syst-msgno|syst-msgv1|syst-msgv2|syst-msgv3|syst-msgv4|syst-oncom|syst-vline|syst-winsl|syst-staco|syst-staro|syst-datar|syst-host|syst-locdb|syst-locop|syst-datlo|syst-timlo|syst-zonlo)$/',
+ 'reserved' => '/^((?i)abs|acos|add|add-corresponding|adjacent|after|aliases|all|analyzer|and|any|append|as|ascending|asin|assign|assigned|assigning|at|atan|authority-check|avg|back|before|begin|binary|bit|bit-and|bit-not|bit-or|bit-xor|blank|block|break-point|buffer|by|c|call|case|catch|ceil|centered|chain|change|changing|check|checkbox|class|class-data|class-events|class-methods|class-pool|clear|client|close|cnt|code|collect|color|comment|commit|communication|compute|concatenate|condense|constants|context|contexts|continue|control|controls|convert|copy|corresponding|cos|cosh|count|country|create|currency|cursor|customer-function|data|database|dataset|delete|decimals|default|define|demand|descending|describe|dialog|distinct|div|divide|divide-corresponding|do|duplicates|dynpro|edit|editor-call|else|elseif|end|end-of-definition|end-of-page|end-of-selection|endat|endcase|endcatch|endchain|endclass|enddo|endexec|endform|endfunction|endif|endinterface|endloop|endmethod|endmodule|endon|endprovide|endselect|endwhile|entries|events|exec|exit|exit-command|exp|exponent|export|exporting|exceptions|extended|extract|fetch|field|field-groups|field-symbols|fields|floor|for|form|format|frac|frame|free|from|function|function-pool|generate|get|group|hashed|header|help-id|help-request|hide|hotspot|icon|id|if|import|importing|include|index|infotypes|initialization|inner|input|insert|intensified|interface|interface-pool|interfaces|into|inverse|join|key|language|last|leave|left|left-justified|like|line|line-count|line-selection|line-size|lines|list-processing|load|load-of-program|local|locale|log|log10|loop|m|margin|mask|matchcode|max|memory|message|message-id|messages|method|methods|min|mod|mode|modif|modify|module|move|move-corresponding|multiply|multiply-corresponding|new|new-line|new-page|next|no|no-gap|no-gaps|no-heading|no-scrolling|no-sign|no-title|no-zero|nodes|non-unique|o|object|obligatory|occurs|of|off|on|open|or|order|others|outer|output|overlay|pack|page|parameter|parameters|perform|pf-status|position|print|print-control|private|process|program|property|protected|provide|public|put|radiobutton|raise|raising|range|ranges|read|receive|refresh|reject|replace|report|requested|reserve|reset|right-justified|rollback|round|rows|rtti|run|scan|screen|search|separated|scroll|scroll-boundary|select|select-options|selection-screen|selection-table|set|shared|shift|sign|sin|single|sinh|size|skip|sort|sorted|split|sql|sqrt|stamp|standard|start-of-selection|statics|stop|string|strlen|structure|submit|subtract|subtract-corresponding|sum|supply|suppress|symbol|syntax-check|syntax-trace|system-call|system-exceptions|table|table_line|tables|tan|tanh|text|textpool|time|times|title|titlebar|to|top-of-page|transaction|transfer|translate|transporting|trunc|type|type-pool|type-pools|types|uline|under|unique|unit|unpack|up|update|user-command|using|value|value-request|values|vary|when|where|while|window|with|with-title|work|write|x|xstring|z|zone)$/',
+ 'constants' => '/^((?i)initial|null|space|col_background|col_heading|col_normal|col_total|col_key|col_positive|col_negative|col_group)$/',
+ ),
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_parts = array (
+ 0 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ ),
+ 1 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ ),
+ 2 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_subst = array (
+ -1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ ),
+ 0 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ ),
+ 1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ ),
+ 2 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_conditions = array (
+ );
+ $this->_kwmap = array (
+ 'sy' => 'reserved',
+ 'reserved' => 'reserved',
+ 'constants' => 'reserved',
+ );
+ $this->_defClass = 'code';
+ $this->_checkDefines();
+ }
+
+}
\ No newline at end of file
diff --git a/library/Text_Highlighter/Text/Highlighter/AVRC.php b/library/Text_Highlighter/Text/Highlighter/AVRC.php
new file mode 100644
index 000000000..de4b82ccd
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter/AVRC.php
@@ -0,0 +1,894 @@
+
+
+ *
+ */
+
+/**
+ * @ignore
+ */
+
+require_once 'Text/Highlighter.php';
+
+/**
+ * Auto-generated class. AVRC syntax highlighting
+ *
+ * @author Andrey Demenev
+ * @category Text
+ * @package Text_Highlighter
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: 0.7.0
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+class Text_Highlighter_AVRC extends Text_Highlighter
+{
+ var $_language = 'avrc';
+
+ /**
+ * PHP4 Compatible Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function Text_Highlighter_AVRC($options=array())
+ {
+ $this->__construct($options);
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function __construct($options=array())
+ {
+
+ $this->_options = $options;
+ $this->_regs = array (
+ -1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 0 => '/((?i)\\\\)/',
+ 1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 2 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 3 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 4 => '//',
+ 5 => '/((?i)")|((?i)<)/',
+ 6 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 7 => '/((?i)\\$\\w+\\s*:.+\\$)/',
+ 8 => '/((?i)\\$\\w+\\s*:.+\\$)/',
+ );
+ $this->_counts = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 0 =>
+ array (
+ 0 => 0,
+ ),
+ 1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 3 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ ),
+ 6 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 2,
+ 8 => 0,
+ 9 => 0,
+ ),
+ 7 =>
+ array (
+ 0 => 0,
+ ),
+ 8 =>
+ array (
+ 0 => 0,
+ ),
+ );
+ $this->_delim = array (
+ -1 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 0 =>
+ array (
+ 0 => '',
+ ),
+ 1 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 2 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 3 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'quotes',
+ ),
+ 6 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => 'mlcomment',
+ 9 => 'comment',
+ ),
+ 7 =>
+ array (
+ 0 => '',
+ ),
+ 8 =>
+ array (
+ 0 => '',
+ ),
+ );
+ $this->_inner = array (
+ -1 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 0 =>
+ array (
+ 0 => 'special',
+ ),
+ 1 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 2 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 3 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 'string',
+ 1 => 'string',
+ ),
+ 6 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'identifier',
+ 4 => 'number',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'mlcomment',
+ 9 => 'comment',
+ ),
+ 7 =>
+ array (
+ 0 => 'inlinedoc',
+ ),
+ 8 =>
+ array (
+ 0 => 'inlinedoc',
+ ),
+ );
+ $this->_end = array (
+ 0 => '/(?i)"/',
+ 1 => '/(?i)\\}/',
+ 2 => '/(?i)\\)/',
+ 3 => '/(?i)\\]/',
+ 4 => '/(?i)>/',
+ 5 => '/(?mi)(? '/(?mi)(? '/(?i)\\*\\//',
+ 8 => '/(?mi)$/',
+ );
+ $this->_states = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 0 =>
+ array (
+ 0 => -1,
+ ),
+ 1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 3 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 0,
+ 1 => 4,
+ ),
+ 6 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => -1,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => 7,
+ 9 => 8,
+ ),
+ 7 =>
+ array (
+ 0 => -1,
+ ),
+ 8 =>
+ array (
+ 0 => -1,
+ ),
+ );
+ $this->_keywords = array (
+ -1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 0 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ 1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 2 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 3 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ ),
+ 6 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'registers' => '/^(ACSR|ADCH|ADCL|ADCSRA|ADMUX|ASSR|DDRA|DDRB|DDRC|DDRD|DDRE|DDRF|DDRG|EEARH|EEARL|EECR|EEDR|EICRA|EICRB|EIFR|EIMSK|ETIFR|ETIMSK|GICR|GIFR|ICR1H|ICR1L|ICR3H|ICR3L|MCUCR|MCUCSR|OCDR|OCR0|OCR1AH|OCR1AL|OCR1BH|OCR1BL|OCR1CH|OCR1CL|OCR2|OCR3AH|OCR3AL|OCR3BH|OCR3BL|OCR3CH|OCR3CL|OSCCAL|PINA|PINB|PINC|PIND|PINE|PINF|PING|PORTA|PORTB|PORTC|PORTD|PORTE|PORTF|PORTG|RAMPZ|SFIOR|SPCR|SPDR|SPH|SPL|SPMCR|SPMCSR|SPSR|SREG|TCCR0|TCCR1A|TCCR1B|TCCR1C|TCCR2|TCCR3A|TCCR3B|TCCR3C|TCNT0|TCNT1H|TCNT1L|TCNT2|TCNT3H|TCNT3L|TIFR|TIMSK|TWAR|TWBR|TWCR|TWDR|TWSR|UBRR0H|UBRR0L|UBRR1H|UBRR1L|UBRRH|UBRRL|UCSR0A|UCSR0B|UCSR0C|UCSR1A|UCSR1B|UCSR1C|UCSRA|UCSRB|UCSRC|UDR|UDR0|UDR1|WDTCR|XDIV|XMCRA|XMCRB)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 => -1,
+ 9 => -1,
+ ),
+ 7 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ 8 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ );
+ $this->_parts = array (
+ 0 =>
+ array (
+ 0 => NULL,
+ ),
+ 1 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ 10 => NULL,
+ 11 => NULL,
+ 12 => NULL,
+ 13 => NULL,
+ ),
+ 2 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ 10 => NULL,
+ 11 => NULL,
+ 12 => NULL,
+ 13 => NULL,
+ ),
+ 3 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ 10 => NULL,
+ 11 => NULL,
+ 12 => NULL,
+ 13 => NULL,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ ),
+ 6 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ ),
+ 7 =>
+ array (
+ 0 => NULL,
+ ),
+ 8 =>
+ array (
+ 0 => NULL,
+ ),
+ );
+ $this->_subst = array (
+ -1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 0 =>
+ array (
+ 0 => false,
+ ),
+ 1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 2 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 3 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => false,
+ 1 => false,
+ ),
+ 6 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ ),
+ 7 =>
+ array (
+ 0 => false,
+ ),
+ 8 =>
+ array (
+ 0 => false,
+ ),
+ );
+ $this->_conditions = array (
+ );
+ $this->_kwmap = array (
+ 'reserved' => 'reserved',
+ 'registers' => 'reserved',
+ 'types' => 'types',
+ 'Common Macros' => 'prepro',
+ );
+ $this->_defClass = 'code';
+ $this->_checkDefines();
+ }
+
+}
\ No newline at end of file
diff --git a/library/Text_Highlighter/Text/Highlighter/CPP.php b/library/Text_Highlighter/Text/Highlighter/CPP.php
new file mode 100644
index 000000000..eaa47c575
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter/CPP.php
@@ -0,0 +1,891 @@
+
+
+ *
+ */
+
+/**
+ * @ignore
+ */
+
+require_once 'Text/Highlighter.php';
+
+/**
+ * Auto-generated class. CPP syntax highlighting
+ *
+ * @author Aaron Kalin
+ * @author Andrey Demenev
+ * @category Text
+ * @package Text_Highlighter
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: 0.7.0
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+class Text_Highlighter_CPP extends Text_Highlighter
+{
+ var $_language = 'cpp';
+
+ /**
+ * PHP4 Compatible Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function Text_Highlighter_CPP($options=array())
+ {
+ $this->__construct($options);
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function __construct($options=array())
+ {
+
+ $this->_options = $options;
+ $this->_regs = array (
+ -1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 0 => '/((?i)\\\\)/',
+ 1 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 2 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 3 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)\\[)|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?mi)^[ \\t]*#include)|((?mii)^[ \\t]*#[ \\t]*[a-z]+)|((?i)\\d*\\.?\\d+)|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 4 => '//',
+ 5 => '/((?i)")|((?i)<)/',
+ 6 => '/((?i)")|((?i)\\{)|((?i)\\()|((?i)[a-z_]\\w*)|((?i)\\b0[xX][\\da-f]+)|((?i)\\b\\d\\d*|\\b0\\b)|((?i)\\b0[0-7]+)|((?i)\\b(\\d*\\.\\d+)|(\\d+\\.\\d*))|((?i)\\/\\*)|((?i)\\/\\/.+)/',
+ 7 => '/((?i)\\$\\w+\\s*:.+\\$)/',
+ 8 => '/((?i)\\$\\w+\\s*:.+\\$)/',
+ );
+ $this->_counts = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 0 =>
+ array (
+ 0 => 0,
+ ),
+ 1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 3 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 2,
+ 9 => 0,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ ),
+ 6 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 2,
+ 8 => 0,
+ 9 => 0,
+ ),
+ 7 =>
+ array (
+ 0 => 0,
+ ),
+ 8 =>
+ array (
+ 0 => 0,
+ ),
+ );
+ $this->_delim = array (
+ -1 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 0 =>
+ array (
+ 0 => '',
+ ),
+ 1 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 2 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 3 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => 'brackets',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => 'prepro',
+ 10 => 'prepro',
+ 11 => '',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'quotes',
+ ),
+ 6 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'brackets',
+ 2 => 'brackets',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => 'mlcomment',
+ 9 => 'comment',
+ ),
+ 7 =>
+ array (
+ 0 => '',
+ ),
+ 8 =>
+ array (
+ 0 => '',
+ ),
+ );
+ $this->_inner = array (
+ -1 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 0 =>
+ array (
+ 0 => 'special',
+ ),
+ 1 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 2 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 3 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'code',
+ 4 => 'identifier',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'number',
+ 9 => 'prepro',
+ 10 => 'code',
+ 11 => 'number',
+ 12 => 'mlcomment',
+ 13 => 'comment',
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 'string',
+ 1 => 'string',
+ ),
+ 6 =>
+ array (
+ 0 => 'string',
+ 1 => 'code',
+ 2 => 'code',
+ 3 => 'identifier',
+ 4 => 'number',
+ 5 => 'number',
+ 6 => 'number',
+ 7 => 'number',
+ 8 => 'mlcomment',
+ 9 => 'comment',
+ ),
+ 7 =>
+ array (
+ 0 => 'inlinedoc',
+ ),
+ 8 =>
+ array (
+ 0 => 'inlinedoc',
+ ),
+ );
+ $this->_end = array (
+ 0 => '/(?i)"/',
+ 1 => '/(?i)\\}/',
+ 2 => '/(?i)\\)/',
+ 3 => '/(?i)\\]/',
+ 4 => '/(?i)>/',
+ 5 => '/(?mi)(? '/(?mi)(? '/(?i)\\*\\//',
+ 8 => '/(?mi)$/',
+ );
+ $this->_states = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 0 =>
+ array (
+ 0 => -1,
+ ),
+ 1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 3 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => 3,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => 5,
+ 10 => 6,
+ 11 => -1,
+ 12 => 7,
+ 13 => 8,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => 0,
+ 1 => 4,
+ ),
+ 6 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 2,
+ 3 => -1,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => 7,
+ 9 => 8,
+ ),
+ 7 =>
+ array (
+ 0 => -1,
+ ),
+ 8 =>
+ array (
+ 0 => -1,
+ ),
+ );
+ $this->_keywords = array (
+ -1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 0 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ 1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 2 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 3 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 => -1,
+ 10 => -1,
+ 11 =>
+ array (
+ ),
+ 12 => -1,
+ 13 => -1,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ ),
+ 6 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 =>
+ array (
+ 'reserved' => '/^(and|and_eq|asm|bitand|bitor|break|case|catch|compl|const_cast|continue|default|delete|do|dynamic_cast|else|for|fortran|friend|goto|if|new|not|not_eq|operator|or|or_eq|private|protected|public|reinterpret_cast|return|sizeof|static_cast|switch|this|throw|try|typeid|using|while|xor|xor_eq|false|true)$/',
+ 'types' => '/^(auto|bool|char|class|const|double|enum|explicit|export|extern|float|inline|int|long|mutable|namespace|register|short|signed|static|struct|template|typedef|typename|union|unsigned|virtual|void|volatile|wchar_t)$/',
+ 'Common Macros' => '/^(NULL|TRUE|FALSE|MAX|MIN|__LINE__|__DATA__|__FILE__|__TIME__|__STDC__)$/',
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 => -1,
+ 9 => -1,
+ ),
+ 7 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ 8 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ );
+ $this->_parts = array (
+ 0 =>
+ array (
+ 0 => NULL,
+ ),
+ 1 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ 10 => NULL,
+ 11 => NULL,
+ 12 => NULL,
+ 13 => NULL,
+ ),
+ 2 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ 10 => NULL,
+ 11 => NULL,
+ 12 => NULL,
+ 13 => NULL,
+ ),
+ 3 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ 10 => NULL,
+ 11 => NULL,
+ 12 => NULL,
+ 13 => NULL,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ ),
+ 6 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ 4 => NULL,
+ 5 => NULL,
+ 6 => NULL,
+ 7 => NULL,
+ 8 => NULL,
+ 9 => NULL,
+ ),
+ 7 =>
+ array (
+ 0 => NULL,
+ ),
+ 8 =>
+ array (
+ 0 => NULL,
+ ),
+ );
+ $this->_subst = array (
+ -1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 0 =>
+ array (
+ 0 => false,
+ ),
+ 1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 2 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 3 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ 0 => false,
+ 1 => false,
+ ),
+ 6 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ ),
+ 7 =>
+ array (
+ 0 => false,
+ ),
+ 8 =>
+ array (
+ 0 => false,
+ ),
+ );
+ $this->_conditions = array (
+ );
+ $this->_kwmap = array (
+ 'reserved' => 'reserved',
+ 'types' => 'types',
+ 'Common Macros' => 'prepro',
+ );
+ $this->_defClass = 'code';
+ $this->_checkDefines();
+ }
+
+}
\ No newline at end of file
diff --git a/library/Text_Highlighter/Text/Highlighter/CSS.php b/library/Text_Highlighter/Text/Highlighter/CSS.php
new file mode 100644
index 000000000..51757c88e
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter/CSS.php
@@ -0,0 +1,437 @@
+
+ *
+ */
+
+/**
+ * @ignore
+ */
+
+require_once 'Text/Highlighter.php';
+
+/**
+ * Auto-generated class. CSS syntax highlighting
+ *
+ * @author Andrey Demenev
+ * @category Text
+ * @package Text_Highlighter
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: 0.7.0
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+class Text_Highlighter_CSS extends Text_Highlighter
+{
+ var $_language = 'css';
+
+ /**
+ * PHP4 Compatible Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function Text_Highlighter_CSS($options=array())
+ {
+ $this->__construct($options);
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function __construct($options=array())
+ {
+
+ $this->_options = $options;
+ $this->_regs = array (
+ -1 => '/((?i)\\/\\*)|((?i)(@[a-z\\d]+))|((?i)(((\\.|#)?[a-z]+[a-z\\d\\-]*(?![a-z\\d\\-]))|(\\*))(?!\\s*:\\s*[\\s\\{]))|((?i):[a-z][a-z\\d\\-]*)|((?i)\\[)|((?i)\\{)/',
+ 0 => '//',
+ 1 => '/((?i)\\d*\\.?\\d+(\\%|em|ex|pc|pt|px|in|mm|cm))|((?i)\\d*\\.?\\d+)|((?i)[a-z][a-z\\d\\-]*)|((?i)#([\\da-f]{6}|[\\da-f]{3})\\b)/',
+ 2 => '/((?i)\')|((?i)")|((?i)[\\w\\-\\:]+)/',
+ 3 => '/((?i)\\/\\*)|((?i)[a-z][a-z\\d\\-]*\\s*:)|((?i)(((\\.|#)?[a-z]+[a-z\\d\\-]*(?![a-z\\d\\-]))|(\\*))(?!\\s*:\\s*[\\s\\{]))|((?i)\\{)/',
+ 4 => '/((?i)\\\\[\\\\(\\\\)\\\\])/',
+ 5 => '/((?i)\\\\\\\\|\\\\"|\\\\\'|\\\\`)/',
+ 6 => '/((?i)\\\\\\\\|\\\\"|\\\\\'|\\\\`|\\\\t|\\\\n|\\\\r)/',
+ );
+ $this->_counts = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => 4,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 => 1,
+ 1 => 0,
+ 2 => 0,
+ 3 => 1,
+ ),
+ 2 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 0,
+ ),
+ 3 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 4,
+ 3 => 0,
+ ),
+ 4 =>
+ array (
+ 0 => 0,
+ ),
+ 5 =>
+ array (
+ 0 => 0,
+ ),
+ 6 =>
+ array (
+ 0 => 0,
+ ),
+ );
+ $this->_delim = array (
+ -1 =>
+ array (
+ 0 => 'comment',
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => 'brackets',
+ 5 => 'brackets',
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 => '',
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ ),
+ 2 =>
+ array (
+ 0 => 'quotes',
+ 1 => 'quotes',
+ 2 => '',
+ ),
+ 3 =>
+ array (
+ 0 => 'comment',
+ 1 => 'reserved',
+ 2 => '',
+ 3 => 'brackets',
+ ),
+ 4 =>
+ array (
+ 0 => '',
+ ),
+ 5 =>
+ array (
+ 0 => '',
+ ),
+ 6 =>
+ array (
+ 0 => '',
+ ),
+ );
+ $this->_inner = array (
+ -1 =>
+ array (
+ 0 => 'comment',
+ 1 => 'var',
+ 2 => 'identifier',
+ 3 => 'special',
+ 4 => 'code',
+ 5 => 'code',
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 => 'number',
+ 1 => 'number',
+ 2 => 'code',
+ 3 => 'var',
+ ),
+ 2 =>
+ array (
+ 0 => 'string',
+ 1 => 'string',
+ 2 => 'var',
+ ),
+ 3 =>
+ array (
+ 0 => 'comment',
+ 1 => 'code',
+ 2 => 'identifier',
+ 3 => 'code',
+ ),
+ 4 =>
+ array (
+ 0 => 'string',
+ ),
+ 5 =>
+ array (
+ 0 => 'special',
+ ),
+ 6 =>
+ array (
+ 0 => 'special',
+ ),
+ );
+ $this->_end = array (
+ 0 => '/(?i)\\*\\//',
+ 1 => '/(?i)(?=;|\\})/',
+ 2 => '/(?i)\\]/',
+ 3 => '/(?i)\\}/',
+ 4 => '/(?i)\\)/',
+ 5 => '/(?i)\'/',
+ 6 => '/(?i)"/',
+ );
+ $this->_states = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 => 2,
+ 5 => 3,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ ),
+ 2 =>
+ array (
+ 0 => 5,
+ 1 => 6,
+ 2 => -1,
+ ),
+ 3 =>
+ array (
+ 0 => 0,
+ 1 => 1,
+ 2 => -1,
+ 3 => 3,
+ ),
+ 4 =>
+ array (
+ 0 => -1,
+ ),
+ 5 =>
+ array (
+ 0 => -1,
+ ),
+ 6 =>
+ array (
+ 0 => -1,
+ ),
+ );
+ $this->_keywords = array (
+ -1 =>
+ array (
+ 0 => -1,
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 => -1,
+ 5 => -1,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ 'propertyValue' => '/^((?i)far-left|left|center-left|center-right|center|far-right|right-side|right|behind|leftwards|rightwards|inherit|scroll|fixed|transparent|none|repeat-x|repeat-y|repeat|no-repeat|collapse|separate|auto|top|bottom|both|open-quote|close-quote|no-open-quote|no-close-quote|crosshair|default|pointer|move|e-resize|ne-resize|nw-resize|n-resize|se-resize|sw-resize|s-resize|text|wait|help|ltr|rtl|inline|block|list-item|run-in|compact|marker|table|inline-table|table-row-group|table-header-group|table-footer-group|table-row|table-column-group|table-column|table-cell|table-caption|below|level|above|higher|lower|show|hide|caption|icon|menu|message-box|small-caption|status-bar|normal|wider|narrower|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded|italic|oblique|small-caps|bold|bolder|lighter|inside|outside|disc|circle|square|decimal|decimal-leading-zero|lower-roman|upper-roman|lower-greek|lower-alpha|lower-latin|upper-alpha|upper-latin|hebrew|armenian|georgian|cjk-ideographic|hiragana|katakana|hiragana-iroha|katakana-iroha|crop|cross|invert|visible|hidden|always|avoid|x-low|low|medium|high|x-high|mix?|repeat?|static|relative|absolute|portrait|landscape|spell-out|once|digits|continuous|code|x-slow|slow|fast|x-fast|faster|slower|justify|underline|overline|line-through|blink|capitalize|uppercase|lowercase|embed|bidi-override|baseline|sub|super|text-top|middle|text-bottom|silent|x-soft|soft|loud|x-loud|pre|nowrap|serif|sans-serif|cursive|fantasy|monospace|empty|string|strict|loose|char|true|false|dotted|dashed|solid|double|groove|ridge|inset|outset|larger|smaller|xx-small|x-small|small|large|x-large|xx-large|all|newspaper|distribute|distribute-all-lines|distribute-center-last|inter-word|inter-ideograph|inter-cluster|kashida|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|keep-all|break-all|break-word|lr-tb|tb-rl|thin|thick|inline-block|w-resize|hand|distribute-letter|distribute-space|whitespace|male|female|child)$/',
+ 'namedcolor' => '/^((?i)aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|purple|red|silver|teal|white|yellow|activeborder|activecaption|appworkspace|background|buttonface|buttonhighlight|buttonshadow|buttontext|captiontext|graytext|highlight|highlighttext|inactiveborder|inactivecaption|inactivecaptiontext|infobackground|infotext|menu|menutext|scrollbar|threeddarkshadow|threedface|threedhighlight|threedlightshadow|threedshadow|window|windowframe|windowtext)$/',
+ ),
+ 3 =>
+ array (
+ ),
+ ),
+ 2 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 =>
+ array (
+ ),
+ ),
+ 3 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 =>
+ array (
+ ),
+ 3 => -1,
+ ),
+ 4 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ 5 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ 6 =>
+ array (
+ 0 =>
+ array (
+ ),
+ ),
+ );
+ $this->_parts = array (
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 =>
+ array (
+ 1 => 'string',
+ ),
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ ),
+ 2 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ ),
+ 3 =>
+ array (
+ 0 => NULL,
+ 1 => NULL,
+ 2 => NULL,
+ 3 => NULL,
+ ),
+ 4 =>
+ array (
+ 0 => NULL,
+ ),
+ 5 =>
+ array (
+ 0 => NULL,
+ ),
+ 6 =>
+ array (
+ 0 => NULL,
+ ),
+ );
+ $this->_subst = array (
+ -1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ ),
+ 2 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ ),
+ 3 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ ),
+ 4 =>
+ array (
+ 0 => false,
+ ),
+ 5 =>
+ array (
+ 0 => false,
+ ),
+ 6 =>
+ array (
+ 0 => false,
+ ),
+ );
+ $this->_conditions = array (
+ );
+ $this->_kwmap = array (
+ 'propertyValue' => 'string',
+ 'namedcolor' => 'var',
+ );
+ $this->_defClass = 'code';
+ $this->_checkDefines();
+ }
+
+}
diff --git a/library/Text_Highlighter/Text/Highlighter/DIFF.php b/library/Text_Highlighter/Text/Highlighter/DIFF.php
new file mode 100644
index 000000000..2bb25a453
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter/DIFF.php
@@ -0,0 +1,384 @@
+
+ *
+ */
+
+/**
+ * @ignore
+ */
+
+require_once 'Text/Highlighter.php';
+
+/**
+ * Auto-generated class. DIFF syntax highlighting
+ *
+ * @author Andrey Demenev
+ * @category Text
+ * @package Text_Highlighter
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+class Text_Highlighter_DIFF extends Text_Highlighter
+{
+ var $_language = 'diff';
+
+ /**
+ * PHP4 Compatible Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function Text_Highlighter_DIFF($options=array())
+ {
+ $this->__construct($options);
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function __construct($options=array())
+ {
+
+ $this->_options = $options;
+ $this->_regs = array (
+ -1 => '/((?m)^\\\\\\sNo\\snewline.+$)|((?m)^\\-\\-\\-$)|((?m)^(diff\\s+\\-|Only\\s+|Index).*$)|((?m)^(\\-\\-\\-|\\+\\+\\+)\\s.+$)|((?m)^\\*.*$)|((?m)^\\+.*$)|((?m)^!.*$)|((?m)^\\<\\s.*$)|((?m)^\\>\\s.*$)|((?m)^\\d+(\\,\\d+)?[acd]\\d+(,\\d+)?$)|((?m)^\\-.*$)|((?m)^\\+.*$)|((?m)^@@.+@@$)|((?m)^d\\d+\\s\\d+$)|((?m)^a\\d+\\s\\d+$)|((?m)^(\\d+)(,\\d+)?(a)$)|((?m)^(\\d+)(,\\d+)?(c)$)|((?m)^(\\d+)(,\\d+)?(d)$)|((?m)^a(\\d+)(\\s\\d+)?$)|((?m)^c(\\d+)(\\s\\d+)?$)|((?m)^d(\\d+)(\\s\\d+)?$)/',
+ 0 => '//',
+ 1 => '//',
+ 2 => '//',
+ 3 => '//',
+ 4 => '//',
+ );
+ $this->_counts = array (
+ -1 =>
+ array (
+ 0 => 0,
+ 1 => 0,
+ 2 => 1,
+ 3 => 1,
+ 4 => 0,
+ 5 => 0,
+ 6 => 0,
+ 7 => 0,
+ 8 => 0,
+ 9 => 2,
+ 10 => 0,
+ 11 => 0,
+ 12 => 0,
+ 13 => 0,
+ 14 => 0,
+ 15 => 3,
+ 16 => 3,
+ 17 => 3,
+ 18 => 2,
+ 19 => 2,
+ 20 => 2,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_delim = array (
+ -1 =>
+ array (
+ 0 => '',
+ 1 => '',
+ 2 => '',
+ 3 => '',
+ 4 => '',
+ 5 => '',
+ 6 => '',
+ 7 => '',
+ 8 => '',
+ 9 => '',
+ 10 => '',
+ 11 => '',
+ 12 => '',
+ 13 => '',
+ 14 => 'code',
+ 15 => 'code',
+ 16 => 'code',
+ 17 => '',
+ 18 => 'code',
+ 19 => 'code',
+ 20 => '',
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_inner = array (
+ -1 =>
+ array (
+ 0 => 'special',
+ 1 => 'code',
+ 2 => 'var',
+ 3 => 'reserved',
+ 4 => 'quotes',
+ 5 => 'string',
+ 6 => 'inlinedoc',
+ 7 => 'quotes',
+ 8 => 'string',
+ 9 => 'code',
+ 10 => 'quotes',
+ 11 => 'string',
+ 12 => 'code',
+ 13 => 'code',
+ 14 => 'var',
+ 15 => 'string',
+ 16 => 'inlinedoc',
+ 17 => 'code',
+ 18 => 'string',
+ 19 => 'inlinedoc',
+ 20 => 'code',
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_end = array (
+ 0 => '/(?m)(?=^[ad]\\d+\\s\\d+)/',
+ 1 => '/(?m)^(\\.)$/',
+ 2 => '/(?m)^(\\.)$/',
+ 3 => '/(?m)^(\\.)$/',
+ 4 => '/(?m)^(\\.)$/',
+ );
+ $this->_states = array (
+ -1 =>
+ array (
+ 0 => -1,
+ 1 => -1,
+ 2 => -1,
+ 3 => -1,
+ 4 => -1,
+ 5 => -1,
+ 6 => -1,
+ 7 => -1,
+ 8 => -1,
+ 9 => -1,
+ 10 => -1,
+ 11 => -1,
+ 12 => -1,
+ 13 => -1,
+ 14 => 0,
+ 15 => 1,
+ 16 => 2,
+ 17 => -1,
+ 18 => 3,
+ 19 => 4,
+ 20 => -1,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_keywords = array (
+ -1 =>
+ array (
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ 5 =>
+ array (
+ ),
+ 6 =>
+ array (
+ ),
+ 7 =>
+ array (
+ ),
+ 8 =>
+ array (
+ ),
+ 9 =>
+ array (
+ ),
+ 10 =>
+ array (
+ ),
+ 11 =>
+ array (
+ ),
+ 12 =>
+ array (
+ ),
+ 13 =>
+ array (
+ ),
+ 14 => -1,
+ 15 => -1,
+ 16 => -1,
+ 17 =>
+ array (
+ ),
+ 18 => -1,
+ 19 => -1,
+ 20 =>
+ array (
+ ),
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_parts = array (
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_subst = array (
+ -1 =>
+ array (
+ 0 => false,
+ 1 => false,
+ 2 => false,
+ 3 => false,
+ 4 => false,
+ 5 => false,
+ 6 => false,
+ 7 => false,
+ 8 => false,
+ 9 => false,
+ 10 => false,
+ 11 => false,
+ 12 => false,
+ 13 => false,
+ 14 => false,
+ 15 => false,
+ 16 => false,
+ 17 => false,
+ 18 => false,
+ 19 => false,
+ 20 => false,
+ ),
+ 0 =>
+ array (
+ ),
+ 1 =>
+ array (
+ ),
+ 2 =>
+ array (
+ ),
+ 3 =>
+ array (
+ ),
+ 4 =>
+ array (
+ ),
+ );
+ $this->_conditions = array (
+ );
+ $this->_kwmap = array (
+ );
+ $this->_defClass = 'default';
+ $this->_checkDefines();
+ }
+
+}
\ No newline at end of file
diff --git a/library/Text_Highlighter/Text/Highlighter/DTD.php b/library/Text_Highlighter/Text/Highlighter/DTD.php
new file mode 100644
index 000000000..41b0faa78
--- /dev/null
+++ b/library/Text_Highlighter/Text/Highlighter/DTD.php
@@ -0,0 +1,426 @@
+
+ *
+ */
+
+/**
+ * @ignore
+ */
+
+require_once 'Text/Highlighter.php';
+
+/**
+ * Auto-generated class. DTD syntax highlighting
+ *
+ * @author Andrey Demenev
+ * @category Text
+ * @package Text_Highlighter
+ * @copyright 2004-2006 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version Release: @package_version@
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+class Text_Highlighter_DTD extends Text_Highlighter
+{
+ var $_language = 'dtd';
+
+ /**
+ * PHP4 Compatible Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function Text_Highlighter_DTD($options=array())
+ {
+ $this->__construct($options);
+ }
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options
+ * @access public
+ */
+ function __construct($options=array())
+ {
+
+ $this->_options = $options;
+ $this->_regs = array (
+ -1 => '/(\\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/avrc.xml b/library/Text_Highlighter/avrc.xml
new file mode 100644
index 000000000..dec571e13
--- /dev/null
+++ b/library/Text_Highlighter/avrc.xml
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+
+ C/C++ highlighter specific to Atmel AVR microcontrollers
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/cpp.xml b/library/Text_Highlighter/cpp.xml
new file mode 100644
index 000000000..2cbaa930f
--- /dev/null
+++ b/library/Text_Highlighter/cpp.xml
@@ -0,0 +1,201 @@
+
+
+
+
+
+
+
+
+
+
+
+Thanks to Aaron Kalin for initial
+implementation of this highlighter
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/css.xml b/library/Text_Highlighter/css.xml
new file mode 100644
index 000000000..2473bcfb7
--- /dev/null
+++ b/library/Text_Highlighter/css.xml
@@ -0,0 +1,368 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/diff.xml b/library/Text_Highlighter/diff.xml
new file mode 100644
index 000000000..d088f9257
--- /dev/null
+++ b/library/Text_Highlighter/diff.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/dtd.xml b/library/Text_Highlighter/dtd.xml
new file mode 100644
index 000000000..18fa07db7
--- /dev/null
+++ b/library/Text_Highlighter/dtd.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/generate b/library/Text_Highlighter/generate
new file mode 100644
index 000000000..4e22e82fd
--- /dev/null
+++ b/library/Text_Highlighter/generate
@@ -0,0 +1,171 @@
+#!@php_bin@
+
+ * @copyright 2004 Andrey Demenev
+ * @license http://www.php.net/license/3_0.txt PHP License
+ * @version CVS: $Id$
+ * @link http://pear.php.net/package/Text_Highlighter
+ */
+
+require_once 'Text/Highlighter/Generator.php';
+require_once 'Console/Getopt.php';
+
+$options = Console_Getopt::getopt($argv, 'x:p:d:h', array('xml=', 'php=','dir=', 'help'));
+
+if (PEAR::isError($options)) {
+ $message = str_replace('Console_Getopt: ','',$options->message);
+ usage($message);
+}
+
+$source = array();
+$dest = array();
+$dir = '';
+
+$expectp = false;
+$expectx = false;
+$unexpectedx = false;
+$unexpectedp = false;
+$si = $di = 0;
+
+foreach ($options[0] as $option) {
+ switch ($option[0]) {
+ case 'x':
+ case '--xml':
+ $source[$si] = $option[1];
+ if ($si) {
+ $di++;
+ }
+ $si++;
+ if ($expectp) {
+ $unexpectedx = true;
+ }
+ $expectp = true;
+ $expectx = false;
+ break;
+
+ case 'p':
+ case '--php':
+ if ($expectx) {
+ $unexpectedp = true;
+ }
+ $dest[$di] = $option[1];
+ $expectp = false;
+ $expectx = true;
+ break;
+
+ case 'd':
+ case '--dir':
+ $dir = $option[1];
+ break;
+
+ case 'h':
+ case '--help':
+ usage();
+ break;
+ }
+}
+
+
+if ($unexpectedx && !$dir) {
+ usage('Unexpected -x or --xml', STDERR);
+}
+
+if ($unexpectedp) {
+ usage('Unexpected -p or --php', STDERR);
+}
+
+$nsource = count($source);
+$ndest = count($dest);
+
+if (!$nsource && !$ndest) {
+ $source[]='php://stdin';
+ if (!$dir) {
+ $dest[]='php://stdout';
+ } else {
+ $dest[] = null;
+ }
+} elseif ($expectp && !$dir && $nsource > 1) {
+ usage('-x or --xml without following -p or --php', STDERR);
+} elseif ($nsource == 1 && !$ndest && !$dir) {
+ $dest[]='php://stdout';
+}
+
+if ($dir && substr($dir,-1)!='/' && substr($dir,-1)!=='\\' ) {
+ $dir .= DIRECTORY_SEPARATOR;
+}
+
+
+foreach ($source as $i => $xmlfile)
+{
+ $gen = new Text_Highlighter_Generator;
+ $gen->setInputFile($xmlfile);
+ if ($gen->hasErrors()) {
+ break;
+ }
+ $gen->generate();
+ if ($gen->hasErrors()) {
+ break;
+ }
+ if (isset($dest[$i])) {
+ $phpfile = $dest[$i];
+ } else {
+ $phpfile = $dir . $gen->language . '.php';
+ }
+ $gen->saveCode($phpfile);
+ if ($gen->hasErrors()) {
+ break;
+ }
+}
+if ($gen->hasErrors()) {
+ $errors = $gen->getErrors();
+ foreach ($errors as $error) {
+ fwrite (STDERR, $error . "\n");
+ }
+ exit(1);
+}
+
+function usage($message='', $file=STDOUT)
+{
+ $code = 0;
+ if ($message) {
+ $message .= "\n\n";
+ $code = 1;
+ }
+ $message .= << tag)
+ -h, --help
+ This help
+MSG;
+ fwrite ($file, $message);
+ exit($code);
+}
+?>
+
diff --git a/library/Text_Highlighter/generate.bat b/library/Text_Highlighter/generate.bat
new file mode 100644
index 000000000..3960486c1
--- /dev/null
+++ b/library/Text_Highlighter/generate.bat
@@ -0,0 +1,188 @@
+@echo off
+rem vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4:
+
+rem Console highlighter class generator
+
+rem PHP versions 4 and 5
+
+rem LICENSE: This source file is subject to version 3.0 of the PHP license
+rem that is available through the world-wide-web at the following URI:
+rem http://www.php.net/license/3_0.txt. If you did not receive a copy of
+rem the PHP License and are unable to obtain it through the web, please
+rem send a note to license@php.net so we can mail you a copy immediately.
+
+rem @category Text
+rem @package Text_Highlighter
+rem @author Andrey Demenev
+rem @copyright 2004 Andrey Demenev
+rem @license http://www.php.net/license/3_0.txt PHP License
+rem @version CVS: $Id: generate.bat,v 1.1 2007-06-03 02:35:28 ssttoo Exp $
+rem @link http://pear.php.net/package/Text_Highlighter
+
+set "MHL_PARAMS="
+:doshift
+set "MHL_PARAMS=%MHL_PARAMS% %1"
+shift
+if -%1- == -- GOTO noshift
+GOTO doshift
+:noshift
+@php_bin@ -q -d output_buffering=1 -d include_path="@php_dir@" @bin_dir@/Text/Highlighter/generate.bat %MHL_PARAMS%
+
+GOTO finish
+message);
+ usage($message);
+}
+
+$source = array();
+$dest = array();
+$dir = '';
+
+$expectp = false;
+$expectx = false;
+$unexpectedx = false;
+$unexpectedp = false;
+$si = $di = 0;
+
+foreach ($options[0] as $option) {
+ switch ($option[0]) {
+ case 'x':
+ case '--xml':
+ $source[$si] = $option[1];
+ if ($si) {
+ $di++;
+ }
+ $si++;
+ if ($expectp) {
+ $unexpectedx = true;
+ }
+ $expectp = true;
+ $expectx = false;
+ break;
+
+ case 'p':
+ case '--php':
+ if ($expectx) {
+ $unexpectedp = true;
+ }
+ $dest[$di] = $option[1];
+ $expectp = false;
+ $expectx = true;
+ break;
+
+ case 'd':
+ case '--dir':
+ $dir = $option[1];
+ break;
+
+ case 'h':
+ case '--help':
+ usage();
+ break;
+ }
+}
+
+
+if ($unexpectedx && !$dir) {
+ usage('Unexpected -x or --xml', STDERR);
+}
+
+if ($unexpectedp) {
+ usage('Unexpected -p or --php', STDERR);
+}
+
+$nsource = count($source);
+$ndest = count($dest);
+
+if (!$nsource && !$ndest) {
+ $source[]='php://stdin';
+ if (!$dir) {
+ $dest[]='php://stdout';
+ } else {
+ $dest[] = null;
+ }
+} elseif ($expectp && !$dir && $nsource > 1) {
+ usage('-x or --xml without following -p or --php', STDERR);
+} elseif ($nsource == 1 && !$ndest && !$dir) {
+ $dest[]='php://stdout';
+}
+
+if ($dir && substr($dir,-1)!='/' && substr($dir,-1)!=='\\' ) {
+ $dir .= DIRECTORY_SEPARATOR;
+}
+
+
+foreach ($source as $i => $xmlfile)
+{
+ $gen = new Text_Highlighter_Generator;
+ $gen->setInputFile($xmlfile);
+ if ($gen->hasErrors()) {
+ break;
+ }
+ $gen->generate();
+ if ($gen->hasErrors()) {
+ break;
+ }
+ if (isset($dest[$i])) {
+ $phpfile = $dest[$i];
+ } else {
+ $phpfile = $dir . $gen->language . '.php';
+ }
+ $gen->saveCode($phpfile);
+ if ($gen->hasErrors()) {
+ break;
+ }
+}
+if ($gen->hasErrors()) {
+ $errors = $gen->getErrors();
+ foreach ($errors as $error) {
+ fwrite (STDERR, $error . "\n");
+ }
+ exit(1);
+}
+
+exit(0);
+
+function usage($message='', $file=STDOUT)
+{
+ $code = 0;
+ if ($message) {
+ $message .= "\n\n";
+ $code = 1;
+ }
+ $message .= << tag)
+ -h, --help
+ This help
+MSG;
+ fwrite ($file, $message);
+ exit($code);
+}
+?>
+:finish
diff --git a/library/Text_Highlighter/html.xml b/library/Text_Highlighter/html.xml
new file mode 100644
index 000000000..58d51fc5b
--- /dev/null
+++ b/library/Text_Highlighter/html.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/java.xml b/library/Text_Highlighter/java.xml
new file mode 100644
index 000000000..12052b5db
--- /dev/null
+++ b/library/Text_Highlighter/java.xml
@@ -0,0 +1,2824 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/javascript.xml b/library/Text_Highlighter/javascript.xml
new file mode 100644
index 000000000..e478515a7
--- /dev/null
+++ b/library/Text_Highlighter/javascript.xml
@@ -0,0 +1,174 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/mysql.xml b/library/Text_Highlighter/mysql.xml
new file mode 100644
index 000000000..082b62795
--- /dev/null
+++ b/library/Text_Highlighter/mysql.xml
@@ -0,0 +1,424 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/perl.xml b/library/Text_Highlighter/perl.xml
new file mode 100644
index 000000000..54f8835ea
--- /dev/null
+++ b/library/Text_Highlighter/perl.xml
@@ -0,0 +1,439 @@
+
+
+
+
+
+
+
+
+
+
+ This highlighter is EXPERIMENTAL, so that it may work incorrectly.
+Most rules were created by Mariusz Jakubowski, and extended by me.
+My knowledge of Perl is poor, and Perl syntax seems too
+complicated to me.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/php.xml b/library/Text_Highlighter/php.xml
new file mode 100644
index 000000000..1b08ea203
--- /dev/null
+++ b/library/Text_Highlighter/php.xml
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/python.xml b/library/Text_Highlighter/python.xml
new file mode 100644
index 000000000..29e77203c
--- /dev/null
+++ b/library/Text_Highlighter/python.xml
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/release b/library/Text_Highlighter/release
new file mode 100644
index 000000000..66f1fa603
--- /dev/null
+++ b/library/Text_Highlighter/release
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+/usr/local/bin/php package.php make
+/usr/local/bin/pear package
diff --git a/library/Text_Highlighter/ruby.xml b/library/Text_Highlighter/ruby.xml
new file mode 100644
index 000000000..599f5af17
--- /dev/null
+++ b/library/Text_Highlighter/ruby.xml
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+FIXME: While this construction : s.split /z/i
+is valid, regular expression is not recognized as such
+(/ folowing an identifier or number is not recognized as
+start of RE), making highlighting improper
+
+%q(a (nested) string) does not get highlighted correctly
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/sample.css b/library/Text_Highlighter/sample.css
new file mode 100644
index 000000000..b4b38c5fc
--- /dev/null
+++ b/library/Text_Highlighter/sample.css
@@ -0,0 +1,62 @@
+.hl-main ol {
+ line-height: 1.0;
+}
+.hl-default {
+ color: Black;
+}
+.hl-code {
+ color: Black;
+}
+.hl-brackets {
+ color: Olive;
+}
+.hl-comment {
+ color: Purple;
+}
+.hl-quotes {
+ color: Darkred;
+}
+.hl-string {
+ color: Red;
+}
+.hl-identifier {
+ color: Blue;
+}
+.hl-builtin {
+ color: Teal;
+}
+.hl-reserved {
+ color: Green;
+}
+.hl-inlinedoc {
+ color: Blue;
+}
+.hl-var {
+ color: Darkblue;
+}
+.hl-url {
+ color: Blue;
+}
+.hl-special {
+ color: Navy;
+}
+.hl-number {
+ color: Maroon;
+}
+.hl-inlinetags {
+ color: Blue;
+}
+.hl-main {
+ background: #ccc none repeat scroll 0 0;
+ color: #000;
+/* background-color: White; */
+}
+.hl-gutter {
+ background-color: #999999;
+ color: White
+}
+.hl-table {
+ font-family: courier;
+ font-size: 12px;
+ border: solid 1px Lightgrey;
+}
diff --git a/library/Text_Highlighter/sh.xml b/library/Text_Highlighter/sh.xml
new file mode 100644
index 000000000..1250de3bc
--- /dev/null
+++ b/library/Text_Highlighter/sh.xml
@@ -0,0 +1,242 @@
+
+
+
+
+
+
+
+
+
+ This highlighter is EXPERIMENTAL. It may work incorrectly.
+ It is a crude hack of the perl syntax, which itself wasn't so good.
+ But this seems to work OK.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/sql.xml b/library/Text_Highlighter/sql.xml
new file mode 100644
index 000000000..19cae49a0
--- /dev/null
+++ b/library/Text_Highlighter/sql.xml
@@ -0,0 +1,496 @@
+
+
+
+
+
+
+
+
+
+
+ Based on SQL-99
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/vbscript.xml b/library/Text_Highlighter/vbscript.xml
new file mode 100644
index 000000000..09c37ffde
--- /dev/null
+++ b/library/Text_Highlighter/vbscript.xml
@@ -0,0 +1,305 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/Text_Highlighter/xml.xml b/library/Text_Highlighter/xml.xml
new file mode 100644
index 000000000..2271ff3ae
--- /dev/null
+++ b/library/Text_Highlighter/xml.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/fullcalendar/CHANGELOG.txt b/library/fullcalendar/CHANGELOG.txt
index d753163e3..32559a8ad 100644
--- a/library/fullcalendar/CHANGELOG.txt
+++ b/library/fullcalendar/CHANGELOG.txt
@@ -1,8 +1,51 @@
+v2.7.3 (2016-06-02)
+-------------------
+
+internal enhancements that plugins can benefit from:
+- EventEmitter not correctly working with stopListeningTo
+- normalizeEvent hook for manipulating event data
+
+
+v2.7.2 (2016-05-20)
+-------------------
+
+- fixed desktops/laptops with touch support not accepting mouse events for
+ dayClick/dragging/resizing (#3154, #3149)
+- fixed dayClick incorrectly triggered on touch scroll (#3152)
+- fixed touch event dragging wrongfully beginning upon scrolling document (#3160)
+- fixed minified JS still contained comments
+- UI change: mouse users must hover over an event to reveal its resizers
+
+
+v2.7.1 (2016-05-01)
+-------------------
+
+- dayClick not firing on touch devices (#3138)
+- icons for prev/next not working in MS Edge (#2852)
+- fix bad languages troubles with firewalls (#3133, #3132)
+- update all dev dependencies (#3145, #3010, #2901, #251)
+- git-ignore npm debug logs (#3011)
+- misc automated test updates (#3139, #3147)
+- Google Calendar htmlLink not always defined (#2844)
+
+
+v2.7.0 (2016-04-23)
+-------------------
+
+touch device support (#994):
+ - smoother scrolling
+ - interactions initiated via "long press":
+ - event drag-n-drop
+ - event resize
+ - time-range selecting
+ - `longPressDelay`
+
+
v2.6.1 (2016-02-17)
-------------------
-- make nowIndicator positioning refresh on window resize
+- make `nowIndicator` positioning refresh on window resize
v2.6.0 (2016-01-07)
diff --git a/library/fullcalendar/CONTRIBUTING.txt b/library/fullcalendar/CONTRIBUTING.txt
index 0204d12c7..5c6dce4ac 100644
--- a/library/fullcalendar/CONTRIBUTING.txt
+++ b/library/fullcalendar/CONTRIBUTING.txt
@@ -41,7 +41,7 @@ Also, you will need the [grunt-cli][grunt-cli] and [bower][bower] packages insta
Then, clone FullCalendar's git repo:
- git clone git://github.com/arshaw/fullcalendar.git
+ git clone git://github.com/fullcalendar/fullcalendar.git
Enter the directory and install FullCalendar's development dependencies:
diff --git a/library/fullcalendar/fullcalendar.css b/library/fullcalendar/fullcalendar.css
index b43d666ef..81e9c1ee2 100644
--- a/library/fullcalendar/fullcalendar.css
+++ b/library/fullcalendar/fullcalendar.css
@@ -1,7 +1,7 @@
/*!
- * FullCalendar v2.6.1 Stylesheet
+ * FullCalendar v2.7.3 Stylesheet
* Docs & License: http://fullcalendar.io/
- * (c) 2015 Adam Shaw
+ * (c) 2016 Adam Shaw
*/
@@ -28,6 +28,7 @@ body .fc { /* extra precedence to overcome jqui */
.fc-unthemed tbody,
.fc-unthemed .fc-divider,
.fc-unthemed .fc-row,
+.fc-unthemed .fc-content, /* for gutter border */
.fc-unthemed .fc-popover {
border-color: #ddd;
}
@@ -72,7 +73,6 @@ body .fc { /* extra precedence to overcome jqui */
.fc-icon {
display: inline-block;
- width: 1em;
height: 1em;
line-height: 1em;
font-size: 1em;
@@ -99,7 +99,6 @@ NOTE: use percentage font sizes or else old IE chokes
.fc-icon:after {
position: relative;
- margin: 0 -1em; /* ensures character will be centered, regardless of width */
}
.fc-icon-left-single-arrow:after {
@@ -107,7 +106,6 @@ NOTE: use percentage font sizes or else old IE chokes
font-weight: bold;
font-size: 200%;
top: -7%;
- left: 3%;
}
.fc-icon-right-single-arrow:after {
@@ -115,7 +113,6 @@ NOTE: use percentage font sizes or else old IE chokes
font-weight: bold;
font-size: 200%;
top: -7%;
- left: -3%;
}
.fc-icon-left-double-arrow:after {
@@ -134,14 +131,12 @@ NOTE: use percentage font sizes or else old IE chokes
content: "\25C4";
font-size: 125%;
top: 3%;
- left: -2%;
}
.fc-icon-right-triangle:after {
content: "\25BA";
font-size: 125%;
top: 3%;
- left: 2%;
}
.fc-icon-down-triangle:after {
@@ -491,15 +486,15 @@ temporary rendered events).
/* Scrolling Container
--------------------------------------------------------------------------------------------------*/
-.fc-scroller { /* this class goes on elements for guaranteed vertical scrollbars */
- overflow-y: scroll;
- overflow-x: hidden;
+.fc-scroller {
+ -webkit-overflow-scrolling: touch;
}
-.fc-scroller > * { /* we expect an immediate inner element */
+/* TODO: move to agenda/basic */
+.fc-scroller > .fc-day-grid,
+.fc-scroller > .fc-time-grid {
position: relative; /* re-scope all positions */
width: 100%; /* hack to force re-sizing this inner element when scrollbars appear/disappear */
- overflow: hidden; /* don't let negative margins or absolute positioning create further scroll */
}
@@ -547,15 +542,68 @@ temporary rendered events).
z-index: 2;
}
+/* resizer (cursor AND touch devices) */
+
.fc-event .fc-resizer {
position: absolute;
- z-index: 3;
+ z-index: 4;
+}
+
+/* resizer (touch devices) */
+
+.fc-event .fc-resizer {
+ display: none;
+}
+
+.fc-event.fc-allow-mouse-resize .fc-resizer,
+.fc-event.fc-selected .fc-resizer {
+ /* only show when hovering or selected (with touch) */
+ display: block;
+}
+
+/* hit area */
+
+.fc-event.fc-selected .fc-resizer:before {
+ /* 40x40 touch area */
+ content: "";
+ position: absolute;
+ z-index: 9999; /* user of this util can scope within a lower z-index */
+ top: 50%;
+ left: 50%;
+ width: 40px;
+ height: 40px;
+ margin-left: -20px;
+ margin-top: -20px;
+}
+
+
+/* Event Selection (only for touch devices)
+--------------------------------------------------------------------------------------------------*/
+
+.fc-event.fc-selected {
+ z-index: 9999 !important; /* overcomes inline z-index */
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
+}
+
+.fc-event.fc-selected.fc-dragging {
+ box-shadow: 0 2px 7px rgba(0, 0, 0, 0.3);
}
/* Horizontal Events
--------------------------------------------------------------------------------------------------*/
+/* bigger touch area when selected */
+.fc-h-event.fc-selected:before {
+ content: "";
+ position: absolute;
+ z-index: 3; /* below resizers */
+ top: -10px;
+ bottom: -10px;
+ left: 0;
+ right: 0;
+}
+
/* events that are continuing to/from another week. kill rounded corners and butt up against edge */
.fc-ltr .fc-h-event.fc-not-start,
@@ -576,36 +624,56 @@ temporary rendered events).
border-bottom-right-radius: 0;
}
-/* resizer */
-
-.fc-h-event .fc-resizer { /* positioned it to overcome the event's borders */
- top: -1px;
- bottom: -1px;
- left: -1px;
- right: -1px;
- width: 5px;
-}
+/* resizer (cursor AND touch devices) */
/* left resizer */
.fc-ltr .fc-h-event .fc-start-resizer,
-.fc-ltr .fc-h-event .fc-start-resizer:before,
-.fc-ltr .fc-h-event .fc-start-resizer:after,
-.fc-rtl .fc-h-event .fc-end-resizer,
-.fc-rtl .fc-h-event .fc-end-resizer:before,
-.fc-rtl .fc-h-event .fc-end-resizer:after {
- right: auto; /* ignore the right and only use the left */
+.fc-rtl .fc-h-event .fc-end-resizer {
cursor: w-resize;
+ left: -1px; /* overcome border */
}
/* right resizer */
.fc-ltr .fc-h-event .fc-end-resizer,
-.fc-ltr .fc-h-event .fc-end-resizer:before,
-.fc-ltr .fc-h-event .fc-end-resizer:after,
-.fc-rtl .fc-h-event .fc-start-resizer,
-.fc-rtl .fc-h-event .fc-start-resizer:before,
-.fc-rtl .fc-h-event .fc-start-resizer:after {
- left: auto; /* ignore the left and only use the right */
+.fc-rtl .fc-h-event .fc-start-resizer {
cursor: e-resize;
+ right: -1px; /* overcome border */
+}
+
+/* resizer (mouse devices) */
+
+.fc-h-event.fc-allow-mouse-resize .fc-resizer {
+ width: 7px;
+ top: -1px; /* overcome top border */
+ bottom: -1px; /* overcome bottom border */
+}
+
+/* resizer (touch devices) */
+
+.fc-h-event.fc-selected .fc-resizer {
+ /* 8x8 little dot */
+ border-radius: 4px;
+ border-width: 1px;
+ width: 6px;
+ height: 6px;
+ border-style: solid;
+ border-color: inherit;
+ background: #fff;
+ /* vertically center */
+ top: 50%;
+ margin-top: -4px;
+}
+
+/* left resizer */
+.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,
+.fc-rtl .fc-h-event.fc-selected .fc-end-resizer {
+ margin-left: -4px; /* centers the 8x8 dot on the left edge */
+}
+
+/* right resizer */
+.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,
+.fc-rtl .fc-h-event.fc-selected .fc-start-resizer {
+ margin-right: -4px; /* centers the 8x8 dot on the right edge */
}
@@ -620,6 +688,20 @@ be a descendant of the grid when it is being dragged.
padding: 0 1px;
}
+.fc-day-grid-event.fc-selected:after {
+ content: "";
+ position: absolute;
+ z-index: 1; /* same z-index as fc-bg, behind text */
+ /* overcome the borders */
+ top: -1px;
+ right: -1px;
+ bottom: -1px;
+ left: -1px;
+ /* darkening effect */
+ background: #000;
+ opacity: .25;
+ filter: alpha(opacity=25); /* for IE */
+}
.fc-day-grid-event .fc-content { /* force events to be one-line tall */
white-space: nowrap;
@@ -630,10 +712,18 @@ be a descendant of the grid when it is being dragged.
font-weight: bold;
}
-.fc-day-grid-event .fc-resizer { /* enlarge the default hit area */
- left: -3px;
- right: -3px;
- width: 7px;
+/* resizer (cursor devices) */
+
+/* left resizer */
+.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,
+.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer {
+ margin-left: -2px; /* to the day cell's edge */
+}
+
+/* right resizer */
+.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,
+.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer {
+ margin-right: -2px; /* to the day cell's edge */
}
@@ -681,6 +771,20 @@ a.fc-more:hover {
border: 0 solid red;
}
+
+/* Utilities
+--------------------------------------------------------------------------------------------------*/
+
+.fc-unselectable {
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-touch-callout: none;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
/* Toolbar
--------------------------------------------------------------------------------------------------*/
@@ -1031,6 +1135,20 @@ be a descendant of the grid when it is being dragged.
overflow: hidden; /* don't let the bg flow over rounded corners */
}
+.fc-time-grid-event.fc-selected {
+ /* need to allow touch resizers to extend outside event's bounding box */
+ /* common fc-selected styles hide the fc-bg, so don't need this anyway */
+ overflow: visible;
+}
+
+.fc-time-grid-event.fc-selected .fc-bg {
+ display: none; /* hide semi-white background, to appear darker */
+}
+
+.fc-time-grid-event .fc-content {
+ overflow: hidden; /* for when .fc-selected */
+}
+
.fc-time-grid-event .fc-time,
.fc-time-grid-event .fc-title {
padding: 0 1px;
@@ -1072,9 +1190,9 @@ be a descendant of the grid when it is being dragged.
padding: 0; /* undo padding from above */
}
-/* resizer */
+/* resizer (cursor device) */
-.fc-time-grid-event .fc-resizer {
+.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer {
left: 0;
right: 0;
bottom: 0;
@@ -1087,10 +1205,28 @@ be a descendant of the grid when it is being dragged.
cursor: s-resize;
}
-.fc-time-grid-event .fc-resizer:after {
+.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after {
content: "=";
}
+/* resizer (touch device) */
+
+.fc-time-grid-event.fc-selected .fc-resizer {
+ /* 10x10 dot */
+ border-radius: 5px;
+ border-width: 1px;
+ width: 8px;
+ height: 8px;
+ border-style: solid;
+ border-color: inherit;
+ background: #fff;
+ /* horizontally center */
+ left: 50%;
+ margin-left: -5px;
+ /* center on the bottom edge */
+ bottom: -5px;
+}
+
/* Now Indicator
--------------------------------------------------------------------------------------------------*/
diff --git a/library/fullcalendar/fullcalendar.js b/library/fullcalendar/fullcalendar.js
index d6042cc17..cbe67697d 100644
--- a/library/fullcalendar/fullcalendar.js
+++ b/library/fullcalendar/fullcalendar.js
@@ -1,7 +1,7 @@
/*!
- * FullCalendar v2.6.1
+ * FullCalendar v2.7.3
* Docs & License: http://fullcalendar.io/
- * (c) 2015 Adam Shaw
+ * (c) 2016 Adam Shaw
*/
(function(factory) {
@@ -19,8 +19,8 @@
;;
var FC = $.fullCalendar = {
- version: "2.6.1",
- internalApiVersion: 3
+ version: "2.7.3",
+ internalApiVersion: 4
};
var fcViews = FC.views = {};
@@ -262,29 +262,25 @@ function matchCellWidths(els) {
}
-// Turns a container element into a scroller if its contents is taller than the allotted height.
-// Returns true if the element is now a scroller, false otherwise.
-// NOTE: this method is best because it takes weird zooming dimensions into account
-function setPotentialScroller(containerEl, height) {
- containerEl.height(height).addClass('fc-scroller');
+// Given one element that resides inside another,
+// Subtracts the height of the inner element from the outer element.
+function subtractInnerElHeight(outerEl, innerEl) {
+ var both = outerEl.add(innerEl);
+ var diff;
- // are scrollbars needed?
- if (containerEl[0].scrollHeight - 1 > containerEl[0].clientHeight) { // !!! -1 because IE is often off-by-one :(
- return true;
- }
+ // effin' IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
+ both.css({
+ position: 'relative', // cause a reflow, which will force fresh dimension recalculation
+ left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
+ });
+ diff = outerEl.outerHeight() - innerEl.outerHeight(); // grab the dimensions
+ both.css({ position: '', left: '' }); // undo hack
- unsetScroller(containerEl); // undo
- return false;
+ return diff;
}
-// Takes an element that might have been a scroller, and turns it back into a normal element.
-function unsetScroller(containerEl) {
- containerEl.height('').removeClass('fc-scroller');
-}
-
-
-/* General DOM Utilities
+/* Element Geom Utilities
----------------------------------------------------------------------------------------------------------------------*/
FC.getOuterRect = getOuterRect;
@@ -309,26 +305,30 @@ function getScrollParent(el) {
// Queries the outer bounding area of a jQuery element.
// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
-function getOuterRect(el) {
+// Origin is optional.
+function getOuterRect(el, origin) {
var offset = el.offset();
+ var left = offset.left - (origin ? origin.left : 0);
+ var top = offset.top - (origin ? origin.top : 0);
return {
- left: offset.left,
- right: offset.left + el.outerWidth(),
- top: offset.top,
- bottom: offset.top + el.outerHeight()
+ left: left,
+ right: left + el.outerWidth(),
+ top: top,
+ bottom: top + el.outerHeight()
};
}
// Queries the area within the margin/border/scrollbars of a jQuery element. Does not go within the padding.
// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
+// Origin is optional.
// NOTE: should use clientLeft/clientTop, but very unreliable cross-browser.
-function getClientRect(el) {
+function getClientRect(el, origin) {
var offset = el.offset();
var scrollbarWidths = getScrollbarWidths(el);
- var left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left;
- var top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top;
+ var left = offset.left + getCssFloat(el, 'border-left-width') + scrollbarWidths.left - (origin ? origin.left : 0);
+ var top = offset.top + getCssFloat(el, 'border-top-width') + scrollbarWidths.top - (origin ? origin.top : 0);
return {
left: left,
@@ -341,10 +341,13 @@ function getClientRect(el) {
// Queries the area within the margin/border/padding of a jQuery element. Assumed not to have scrollbars.
// Returns a rectangle with absolute coordinates: left, right (exclusive), top, bottom (exclusive).
-function getContentRect(el) {
+// Origin is optional.
+function getContentRect(el, origin) {
var offset = el.offset(); // just outside of border, margin not included
- var left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left');
- var top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top');
+ var left = offset.left + getCssFloat(el, 'border-left-width') + getCssFloat(el, 'padding-left') -
+ (origin ? origin.left : 0);
+ var top = offset.top + getCssFloat(el, 'border-top-width') + getCssFloat(el, 'padding-top') -
+ (origin ? origin.top : 0);
return {
left: left,
@@ -414,13 +417,82 @@ function getCssFloat(el, prop) {
}
+/* Mouse / Touch Utilities
+----------------------------------------------------------------------------------------------------------------------*/
+
+FC.preventDefault = preventDefault;
+
+
// Returns a boolean whether this was a left mouse click and no ctrl key (which means right click on Mac)
function isPrimaryMouseButton(ev) {
return ev.which == 1 && !ev.ctrlKey;
}
-/* Geometry
+function getEvX(ev) {
+ if (ev.pageX !== undefined) {
+ return ev.pageX;
+ }
+ var touches = ev.originalEvent.touches;
+ if (touches) {
+ return touches[0].pageX;
+ }
+}
+
+
+function getEvY(ev) {
+ if (ev.pageY !== undefined) {
+ return ev.pageY;
+ }
+ var touches = ev.originalEvent.touches;
+ if (touches) {
+ return touches[0].pageY;
+ }
+}
+
+
+function getEvIsTouch(ev) {
+ return /^touch/.test(ev.type);
+}
+
+
+function preventSelection(el) {
+ el.addClass('fc-unselectable')
+ .on('selectstart', preventDefault);
+}
+
+
+// Stops a mouse/touch event from doing it's native browser action
+function preventDefault(ev) {
+ ev.preventDefault();
+}
+
+
+// attach a handler to get called when ANY scroll action happens on the page.
+// this was impossible to do with normal on/off because 'scroll' doesn't bubble.
+// http://stackoverflow.com/a/32954565/96342
+// returns `true` on success.
+function bindAnyScroll(handler) {
+ if (window.addEventListener) {
+ window.addEventListener('scroll', handler, true); // useCapture=true
+ return true;
+ }
+ return false;
+}
+
+
+// undoes bindAnyScroll. must pass in the original function.
+// returns `true` on success.
+function unbindAnyScroll(handler) {
+ if (window.removeEventListener) {
+ window.removeEventListener('scroll', handler, true); // useCapture=true
+ return true;
+ }
+ return false;
+}
+
+
+/* General Geometry Utils
----------------------------------------------------------------------------------------------------------------------*/
FC.intersectRects = intersectRects;
@@ -946,22 +1018,21 @@ function proxy(obj, methodName) {
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
-// N milliseconds.
+// N milliseconds. If `immediate` is passed, trigger the function on the
+// leading edge, instead of the trailing.
// https://github.com/jashkenas/underscore/blob/1.6.0/underscore.js#L714
-function debounce(func, wait) {
- var timeoutId;
- var args;
- var context;
- var timestamp; // of most recent call
+function debounce(func, wait, immediate) {
+ var timeout, args, context, timestamp, result;
+
var later = function() {
var last = +new Date() - timestamp;
- if (last < wait && last > 0) {
- timeoutId = setTimeout(later, wait - last);
+ if (last < wait) {
+ timeout = setTimeout(later, wait - last);
}
else {
- timeoutId = null;
- func.apply(context, args);
- if (!timeoutId) {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
context = args = null;
}
}
@@ -971,9 +1042,15 @@ function debounce(func, wait) {
context = this;
args = arguments;
timestamp = +new Date();
- if (!timeoutId) {
- timeoutId = setTimeout(later, wait);
+ var callNow = immediate && !timeout;
+ if (!timeout) {
+ timeout = setTimeout(later, wait);
}
+ if (callNow) {
+ result = func.apply(context, args);
+ context = args = null;
+ }
+ return result;
};
}
@@ -1777,61 +1854,162 @@ function extendClass(superClass, members) {
function mixIntoClass(theClass, members) {
- copyOwnProps(members.prototype || members, theClass.prototype); // TODO: copyNativeMethods?
+ copyOwnProps(members, theClass.prototype); // TODO: copyNativeMethods?
}
;;
-var Emitter = FC.Emitter = Class.extend({
+var EmitterMixin = FC.EmitterMixin = {
- callbackHash: null,
+ // jQuery-ification via $(this) allows a non-DOM object to have
+ // the same event handling capabilities (including namespaces).
- on: function(name, callback) {
- this.getCallbacks(name).add(callback);
- return this; // for chaining
- },
+ on: function(types, handler) {
+ // handlers are always called with an "event" object as their first param.
+ // sneak the `this` context and arguments into the extra parameter object
+ // and forward them on to the original handler.
+ var intercept = function(ev, extra) {
+ return handler.apply(
+ extra.context || this,
+ extra.args || []
+ );
+ };
- off: function(name, callback) {
- this.getCallbacks(name).remove(callback);
- return this; // for chaining
- },
-
-
- trigger: function(name) { // args...
- var args = Array.prototype.slice.call(arguments, 1);
-
- this.triggerWith(name, this, args);
-
- return this; // for chaining
- },
-
-
- triggerWith: function(name, context, args) {
- var callbacks = this.getCallbacks(name);
-
- callbacks.fireWith(context, args);
-
- return this; // for chaining
- },
-
-
- getCallbacks: function(name) {
- var callbacks;
-
- if (!this.callbackHash) {
- this.callbackHash = {};
+ // mimick jQuery's internal "proxy" system (risky, I know)
+ // causing all functions with the same .guid to appear to be the same.
+ // https://github.com/jquery/jquery/blob/2.2.4/src/core.js#L448
+ // this is needed for calling .off with the original non-intercept handler.
+ if (!handler.guid) {
+ handler.guid = $.guid++;
}
+ intercept.guid = handler.guid;
- callbacks = this.callbackHash[name];
- if (!callbacks) {
- callbacks = this.callbackHash[name] = $.Callbacks();
- }
+ $(this).on(types, intercept);
- return callbacks;
+ return this; // for chaining
+ },
+
+
+ off: function(types, handler) {
+ $(this).off(types, handler);
+
+ return this; // for chaining
+ },
+
+
+ trigger: function(types) {
+ var args = Array.prototype.slice.call(arguments, 1); // arguments after the first
+
+ // pass in "extra" info to the intercept
+ $(this).triggerHandler(types, { args: args });
+
+ return this; // for chaining
+ },
+
+
+ triggerWith: function(types, context, args) {
+
+ // `triggerHandler` is less reliant on the DOM compared to `trigger`.
+ // pass in "extra" info to the intercept.
+ $(this).triggerHandler(types, { context: context, args: args });
+
+ return this; // for chaining
}
-});
+};
+
+;;
+
+/*
+Utility methods for easily listening to events on another object,
+and more importantly, easily unlistening from them.
+*/
+var ListenerMixin = FC.ListenerMixin = (function() {
+ var guid = 0;
+ var ListenerMixin = {
+
+ listenerId: null,
+
+ /*
+ Given an `other` object that has on/off methods, bind the given `callback` to an event by the given name.
+ The `callback` will be called with the `this` context of the object that .listenTo is being called on.
+ Can be called:
+ .listenTo(other, eventName, callback)
+ OR
+ .listenTo(other, {
+ eventName1: callback1,
+ eventName2: callback2
+ })
+ */
+ listenTo: function(other, arg, callback) {
+ if (typeof arg === 'object') { // given dictionary of callbacks
+ for (var eventName in arg) {
+ if (arg.hasOwnProperty(eventName)) {
+ this.listenTo(other, eventName, arg[eventName]);
+ }
+ }
+ }
+ else if (typeof arg === 'string') {
+ other.on(
+ arg + '.' + this.getListenerNamespace(), // use event namespacing to identify this object
+ $.proxy(callback, this) // always use `this` context
+ // the usually-undesired jQuery guid behavior doesn't matter,
+ // because we always unbind via namespace
+ );
+ }
+ },
+
+ /*
+ Causes the current object to stop listening to events on the `other` object.
+ `eventName` is optional. If omitted, will stop listening to ALL events on `other`.
+ */
+ stopListeningTo: function(other, eventName) {
+ other.off((eventName || '') + '.' + this.getListenerNamespace());
+ },
+
+ /*
+ Returns a string, unique to this object, to be used for event namespacing
+ */
+ getListenerNamespace: function() {
+ if (this.listenerId == null) {
+ this.listenerId = guid++;
+ }
+ return '_listener' + this.listenerId;
+ }
+
+ };
+ return ListenerMixin;
+})();
+;;
+
+// simple class for toggle a `isIgnoringMouse` flag on delay
+// initMouseIgnoring must first be called, with a millisecond delay setting.
+var MouseIgnorerMixin = {
+
+ isIgnoringMouse: false, // bool
+ delayUnignoreMouse: null, // method
+
+
+ initMouseIgnoring: function(delay) {
+ this.delayUnignoreMouse = debounce(proxy(this, 'unignoreMouse'), delay || 1000);
+ },
+
+
+ // temporarily ignore mouse actions on segments
+ tempIgnoreMouse: function() {
+ this.isIgnoringMouse = true;
+ this.delayUnignoreMouse();
+ },
+
+
+ // delayUnignoreMouse eventually calls this
+ unignoreMouse: function() {
+ this.isIgnoringMouse = false;
+ }
+
+};
+
;;
/* A rectangular panel that is absolutely positioned over other content
@@ -1848,12 +2026,11 @@ Options:
- hide (callback)
*/
-var Popover = Class.extend({
+var Popover = Class.extend(ListenerMixin, {
isHidden: true,
options: null,
el: null, // the container element for the popover. generated by this object
- documentMousedownProxy: null, // document mousedown handler bound to `this`
margin: 10, // the space required between the popover and the edges of the scroll container
@@ -1907,7 +2084,7 @@ var Popover = Class.extend({
});
if (options.autoHide) {
- $(document).on('mousedown', this.documentMousedownProxy = proxy(this, 'documentMousedown'));
+ this.listenTo($(document), 'mousedown', this.documentMousedown);
}
},
@@ -1930,7 +2107,7 @@ var Popover = Class.extend({
this.el = null;
}
- $(document).off('mousedown', this.documentMousedownProxy);
+ this.stopListeningTo($(document), 'mousedown');
},
@@ -2243,148 +2420,325 @@ var CoordCache = FC.CoordCache = Class.extend({
----------------------------------------------------------------------------------------------------------------------*/
// TODO: use Emitter
-var DragListener = FC.DragListener = Class.extend({
+var DragListener = FC.DragListener = Class.extend(ListenerMixin, MouseIgnorerMixin, {
options: null,
- isListening: false,
- isDragging: false,
+ // for IE8 bug-fighting behavior
+ subjectEl: null,
+ subjectHref: null,
// coordinates of the initial mousedown
originX: null,
originY: null,
- // handler attached to the document, bound to the DragListener's `this`
- mousemoveProxy: null,
- mouseupProxy: null,
-
- // for IE8 bug-fighting behavior, for now
- subjectEl: null, // the element being draged. optional
- subjectHref: null,
-
+ // the wrapping element that scrolls, or MIGHT scroll if there's overflow.
+ // TODO: do this for wrappers that have overflow:hidden as well.
scrollEl: null,
- scrollBounds: null, // { top, bottom, left, right }
- scrollTopVel: null, // pixels per second
- scrollLeftVel: null, // pixels per second
- scrollIntervalId: null, // ID of setTimeout for scrolling animation loop
- scrollHandlerProxy: null, // this-scoped function for handling when scrollEl is scrolled
- scrollSensitivity: 30, // pixels from edge for scrolling to start
- scrollSpeed: 200, // pixels per second, at maximum speed
- scrollIntervalMs: 50, // millisecond wait between scroll increment
+ isInteracting: false,
+ isDistanceSurpassed: false,
+ isDelayEnded: false,
+ isDragging: false,
+ isTouch: false,
+
+ delay: null,
+ delayTimeoutId: null,
+ minDistance: null,
+
+ handleTouchScrollProxy: null, // calls handleTouchScroll, always bound to `this`
constructor: function(options) {
- options = options || {};
- this.options = options;
- this.subjectEl = options.subjectEl;
+ this.options = options || {};
+ this.handleTouchScrollProxy = proxy(this, 'handleTouchScroll');
+ this.initMouseIgnoring(500);
},
- // Call this when the user does a mousedown. Will probably lead to startListening
- mousedown: function(ev) {
- if (isPrimaryMouseButton(ev)) {
+ // Interaction (high-level)
+ // -----------------------------------------------------------------------------------------------------------------
- ev.preventDefault(); // prevents native selection in most browsers
- this.startListening(ev);
+ startInteraction: function(ev, extraOptions) {
+ var isTouch = getEvIsTouch(ev);
- // start the drag immediately if there is no minimum distance for a drag start
- if (!this.options.distance) {
- this.startDrag(ev);
+ if (ev.type === 'mousedown') {
+ if (this.isIgnoringMouse) {
+ return;
}
- }
- },
-
-
- // Call this to start tracking mouse movements
- startListening: function(ev) {
- var scrollParent;
-
- if (!this.isListening) {
-
- // grab scroll container and attach handler
- if (ev && this.options.scroll) {
- scrollParent = getScrollParent($(ev.target));
- if (!scrollParent.is(window) && !scrollParent.is(document)) {
- this.scrollEl = scrollParent;
-
- // scope to `this`, and use `debounce` to make sure rapid calls don't happen
- this.scrollHandlerProxy = debounce(proxy(this, 'scrollHandler'), 100);
- this.scrollEl.on('scroll', this.scrollHandlerProxy);
- }
- }
-
- $(document)
- .on('mousemove', this.mousemoveProxy = proxy(this, 'mousemove'))
- .on('mouseup', this.mouseupProxy = proxy(this, 'mouseup'))
- .on('selectstart', this.preventDefault); // prevents native selection in IE<=8
-
- if (ev) {
- this.originX = ev.pageX;
- this.originY = ev.pageY;
+ else if (!isPrimaryMouseButton(ev)) {
+ return;
}
else {
- // if no starting information was given, origin will be the topleft corner of the screen.
- // if so, dx/dy in the future will be the absolute coordinates.
- this.originX = 0;
- this.originY = 0;
+ ev.preventDefault(); // prevents native selection in most browsers
}
+ }
- this.isListening = true;
- this.listenStart(ev);
+ if (!this.isInteracting) {
+
+ // process options
+ extraOptions = extraOptions || {};
+ this.delay = firstDefined(extraOptions.delay, this.options.delay, 0);
+ this.minDistance = firstDefined(extraOptions.distance, this.options.distance, 0);
+ this.subjectEl = this.options.subjectEl;
+
+ this.isInteracting = true;
+ this.isTouch = isTouch;
+ this.isDelayEnded = false;
+ this.isDistanceSurpassed = false;
+
+ this.originX = getEvX(ev);
+ this.originY = getEvY(ev);
+ this.scrollEl = getScrollParent($(ev.target));
+
+ this.bindHandlers();
+ this.initAutoScroll();
+ this.handleInteractionStart(ev);
+ this.startDelay(ev);
+
+ if (!this.minDistance) {
+ this.handleDistanceSurpassed(ev);
+ }
}
},
- // Called when drag listening has started (but a real drag has not necessarily began)
- listenStart: function(ev) {
- this.trigger('listenStart', ev);
+ handleInteractionStart: function(ev) {
+ this.trigger('interactionStart', ev);
},
- // Called when the user moves the mouse
- mousemove: function(ev) {
- var dx = ev.pageX - this.originX;
- var dy = ev.pageY - this.originY;
- var minDistance;
+ endInteraction: function(ev, isCancelled) {
+ if (this.isInteracting) {
+ this.endDrag(ev);
+
+ if (this.delayTimeoutId) {
+ clearTimeout(this.delayTimeoutId);
+ this.delayTimeoutId = null;
+ }
+
+ this.destroyAutoScroll();
+ this.unbindHandlers();
+
+ this.isInteracting = false;
+ this.handleInteractionEnd(ev, isCancelled);
+
+ // a touchstart+touchend on the same element will result in the following addition simulated events:
+ // mouseover + mouseout + click
+ // let's ignore these bogus events
+ if (this.isTouch) {
+ this.tempIgnoreMouse();
+ }
+ }
+ },
+
+
+ handleInteractionEnd: function(ev, isCancelled) {
+ this.trigger('interactionEnd', ev, isCancelled || false);
+ },
+
+
+ // Binding To DOM
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ bindHandlers: function() {
+ var _this = this;
+ var touchStartIgnores = 1;
+
+ if (this.isTouch) {
+ this.listenTo($(document), {
+ touchmove: this.handleTouchMove,
+ touchend: this.endInteraction,
+ touchcancel: this.endInteraction,
+
+ // Sometimes touchend doesn't fire
+ // (can't figure out why. touchcancel doesn't fire either. has to do with scrolling?)
+ // If another touchstart happens, we know it's bogus, so cancel the drag.
+ // touchend will continue to be broken until user does a shorttap/scroll, but this is best we can do.
+ touchstart: function(ev) {
+ if (touchStartIgnores) { // bindHandlers is called from within a touchstart,
+ touchStartIgnores--; // and we don't want this to fire immediately, so ignore.
+ }
+ else {
+ _this.endInteraction(ev, true); // isCancelled=true
+ }
+ }
+ });
+
+ // listen to ALL scroll actions on the page
+ if (
+ !bindAnyScroll(this.handleTouchScrollProxy) && // hopefully this works and short-circuits the rest
+ this.scrollEl // otherwise, attach a single handler to this
+ ) {
+ this.listenTo(this.scrollEl, 'scroll', this.handleTouchScroll);
+ }
+ }
+ else {
+ this.listenTo($(document), {
+ mousemove: this.handleMouseMove,
+ mouseup: this.endInteraction
+ });
+ }
+
+ this.listenTo($(document), {
+ selectstart: preventDefault, // don't allow selection while dragging
+ contextmenu: preventDefault // long taps would open menu on Chrome dev tools
+ });
+ },
+
+
+ unbindHandlers: function() {
+ this.stopListeningTo($(document));
+
+ // unbind scroll listening
+ unbindAnyScroll(this.handleTouchScrollProxy);
+ if (this.scrollEl) {
+ this.stopListeningTo(this.scrollEl, 'scroll');
+ }
+ },
+
+
+ // Drag (high-level)
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ // extraOptions ignored if drag already started
+ startDrag: function(ev, extraOptions) {
+ this.startInteraction(ev, extraOptions); // ensure interaction began
+
+ if (!this.isDragging) {
+ this.isDragging = true;
+ this.handleDragStart(ev);
+ }
+ },
+
+
+ handleDragStart: function(ev) {
+ this.trigger('dragStart', ev);
+ this.initHrefHack();
+ },
+
+
+ handleMove: function(ev) {
+ var dx = getEvX(ev) - this.originX;
+ var dy = getEvY(ev) - this.originY;
+ var minDistance = this.minDistance;
var distanceSq; // current distance from the origin, squared
- if (!this.isDragging) { // if not already dragging...
- // then start the drag if the minimum distance criteria is met
- minDistance = this.options.distance || 1;
+ if (!this.isDistanceSurpassed) {
distanceSq = dx * dx + dy * dy;
if (distanceSq >= minDistance * minDistance) { // use pythagorean theorem
- this.startDrag(ev);
+ this.handleDistanceSurpassed(ev);
}
}
if (this.isDragging) {
- this.drag(dx, dy, ev); // report a drag, even if this mousemove initiated the drag
+ this.handleDrag(dx, dy, ev);
}
},
- // Call this to initiate a legitimate drag.
- // This function is called internally from this class, but can also be called explicitly from outside
- startDrag: function(ev) {
+ // Called while the mouse is being moved and when we know a legitimate drag is taking place
+ handleDrag: function(dx, dy, ev) {
+ this.trigger('drag', dx, dy, ev);
+ this.updateAutoScroll(ev); // will possibly cause scrolling
+ },
- if (!this.isListening) { // startDrag must have manually initiated
- this.startListening();
+
+ endDrag: function(ev) {
+ if (this.isDragging) {
+ this.isDragging = false;
+ this.handleDragEnd(ev);
+ }
+ },
+
+
+ handleDragEnd: function(ev) {
+ this.trigger('dragEnd', ev);
+ this.destroyHrefHack();
+ },
+
+
+ // Delay
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ startDelay: function(initialEv) {
+ var _this = this;
+
+ if (this.delay) {
+ this.delayTimeoutId = setTimeout(function() {
+ _this.handleDelayEnd(initialEv);
+ }, this.delay);
+ }
+ else {
+ this.handleDelayEnd(initialEv);
+ }
+ },
+
+
+ handleDelayEnd: function(initialEv) {
+ this.isDelayEnded = true;
+
+ if (this.isDistanceSurpassed) {
+ this.startDrag(initialEv);
+ }
+ },
+
+
+ // Distance
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ handleDistanceSurpassed: function(ev) {
+ this.isDistanceSurpassed = true;
+
+ if (this.isDelayEnded) {
+ this.startDrag(ev);
+ }
+ },
+
+
+ // Mouse / Touch
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ handleTouchMove: function(ev) {
+ // prevent inertia and touchmove-scrolling while dragging
+ if (this.isDragging) {
+ ev.preventDefault();
}
+ this.handleMove(ev);
+ },
+
+
+ handleMouseMove: function(ev) {
+ this.handleMove(ev);
+ },
+
+
+ // Scrolling (unrelated to auto-scroll)
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ handleTouchScroll: function(ev) {
+ // if the drag is being initiated by touch, but a scroll happens before
+ // the drag-initiating delay is over, cancel the drag
if (!this.isDragging) {
- this.isDragging = true;
- this.dragStart(ev);
+ this.endInteraction(ev, true); // isCancelled=true
}
},
- // Called when the actual drag has started (went beyond minDistance)
- dragStart: function(ev) {
- var subjectEl = this.subjectEl;
+ // HREF Hack
+ // -----------------------------------------------------------------------------------------------------------------
- this.trigger('dragStart', ev);
+
+ initHrefHack: function() {
+ var subjectEl = this.subjectEl;
// remove a mousedown'd 's href so it is not visited (IE8 bug)
if ((this.subjectHref = subjectEl ? subjectEl.attr('href') : null)) {
@@ -2393,75 +2747,21 @@ var DragListener = FC.DragListener = Class.extend({
},
- // Called while the mouse is being moved and when we know a legitimate drag is taking place
- drag: function(dx, dy, ev) {
- this.trigger('drag', dx, dy, ev);
- this.updateScroll(ev); // will possibly cause scrolling
- },
-
-
- // Called when the user does a mouseup
- mouseup: function(ev) {
- this.stopListening(ev);
- },
-
-
- // Called when the drag is over. Will not cause listening to stop however.
- // A concluding 'cellOut' event will NOT be triggered.
- stopDrag: function(ev) {
- if (this.isDragging) {
- this.stopScrolling();
- this.dragStop(ev);
- this.isDragging = false;
- }
- },
-
-
- // Called when dragging has been stopped
- dragStop: function(ev) {
- var _this = this;
-
- this.trigger('dragStop', ev);
+ destroyHrefHack: function() {
+ var subjectEl = this.subjectEl;
+ var subjectHref = this.subjectHref;
// restore a mousedown'd 's href (for IE8 bug)
setTimeout(function() { // must be outside of the click's execution
- if (_this.subjectHref) {
- _this.subjectEl.attr('href', _this.subjectHref);
+ if (subjectHref) {
+ subjectEl.attr('href', subjectHref);
}
}, 0);
},
- // Call this to stop listening to the user's mouse events
- stopListening: function(ev) {
- this.stopDrag(ev); // if there's a current drag, kill it
-
- if (this.isListening) {
-
- // remove the scroll handler if there is a scrollEl
- if (this.scrollEl) {
- this.scrollEl.off('scroll', this.scrollHandlerProxy);
- this.scrollHandlerProxy = null;
- }
-
- $(document)
- .off('mousemove', this.mousemoveProxy)
- .off('mouseup', this.mouseupProxy)
- .off('selectstart', this.preventDefault);
-
- this.mousemoveProxy = null;
- this.mouseupProxy = null;
-
- this.isListening = false;
- this.listenStop(ev);
- }
- },
-
-
- // Called when drag listening has stopped
- listenStop: function(ev) {
- this.trigger('listenStop', ev);
- },
+ // Utils
+ // -----------------------------------------------------------------------------------------------------------------
// Triggers a callback. Calls a function in the option hash of the same name.
@@ -2470,30 +2770,71 @@ var DragListener = FC.DragListener = Class.extend({
if (this.options[name]) {
this.options[name].apply(this, Array.prototype.slice.call(arguments, 1));
}
+ // makes _methods callable by event name. TODO: kill this
+ if (this['_' + name]) {
+ this['_' + name].apply(this, Array.prototype.slice.call(arguments, 1));
+ }
+ }
+
+
+});
+
+;;
+/*
+this.scrollEl is set in DragListener
+*/
+DragListener.mixin({
+
+ isAutoScroll: false,
+
+ scrollBounds: null, // { top, bottom, left, right }
+ scrollTopVel: null, // pixels per second
+ scrollLeftVel: null, // pixels per second
+ scrollIntervalId: null, // ID of setTimeout for scrolling animation loop
+
+ // defaults
+ scrollSensitivity: 30, // pixels from edge for scrolling to start
+ scrollSpeed: 200, // pixels per second, at maximum speed
+ scrollIntervalMs: 50, // millisecond wait between scroll increment
+
+
+ initAutoScroll: function() {
+ var scrollEl = this.scrollEl;
+
+ this.isAutoScroll =
+ this.options.scroll &&
+ scrollEl &&
+ !scrollEl.is(window) &&
+ !scrollEl.is(document);
+
+ if (this.isAutoScroll) {
+ // debounce makes sure rapid calls don't happen
+ this.listenTo(scrollEl, 'scroll', debounce(this.handleDebouncedScroll, 100));
+ }
},
- // Stops a given mouse event from doing it's native browser action. In our case, text selection.
- preventDefault: function(ev) {
- ev.preventDefault();
+ destroyAutoScroll: function() {
+ this.endAutoScroll(); // kill any animation loop
+
+ // remove the scroll handler if there is a scrollEl
+ if (this.isAutoScroll) {
+ this.stopListeningTo(this.scrollEl, 'scroll'); // will probably get removed by unbindHandlers too :(
+ }
},
- /* Scrolling
- ------------------------------------------------------------------------------------------------------------------*/
-
-
// Computes and stores the bounding rectangle of scrollEl
computeScrollBounds: function() {
- var el = this.scrollEl;
-
- this.scrollBounds = el ? getOuterRect(el) : null;
+ if (this.isAutoScroll) {
+ this.scrollBounds = getOuterRect(this.scrollEl);
// TODO: use getClientRect in future. but prevents auto scrolling when on top of scrollbars
+ }
},
// Called when the dragging is in progress and scrolling should be updated
- updateScroll: function(ev) {
+ updateAutoScroll: function(ev) {
var sensitivity = this.scrollSensitivity;
var bounds = this.scrollBounds;
var topCloseness, bottomCloseness;
@@ -2504,10 +2845,10 @@ var DragListener = FC.DragListener = Class.extend({
if (bounds) { // only scroll if scrollEl exists
// compute closeness to edges. valid range is from 0.0 - 1.0
- topCloseness = (sensitivity - (ev.pageY - bounds.top)) / sensitivity;
- bottomCloseness = (sensitivity - (bounds.bottom - ev.pageY)) / sensitivity;
- leftCloseness = (sensitivity - (ev.pageX - bounds.left)) / sensitivity;
- rightCloseness = (sensitivity - (bounds.right - ev.pageX)) / sensitivity;
+ topCloseness = (sensitivity - (getEvY(ev) - bounds.top)) / sensitivity;
+ bottomCloseness = (sensitivity - (bounds.bottom - getEvY(ev))) / sensitivity;
+ leftCloseness = (sensitivity - (getEvX(ev) - bounds.left)) / sensitivity;
+ rightCloseness = (sensitivity - (bounds.right - getEvX(ev))) / sensitivity;
// translate vertical closeness into velocity.
// mouse must be completely in bounds for velocity to happen.
@@ -2594,38 +2935,36 @@ var DragListener = FC.DragListener = Class.extend({
// if scrolled all the way, which causes the vels to be zero, stop the animation loop
if (!this.scrollTopVel && !this.scrollLeftVel) {
- this.stopScrolling();
+ this.endAutoScroll();
}
},
// Kills any existing scrolling animation loop
- stopScrolling: function() {
+ endAutoScroll: function() {
if (this.scrollIntervalId) {
clearInterval(this.scrollIntervalId);
this.scrollIntervalId = null;
- // when all done with scrolling, recompute positions since they probably changed
- this.scrollStop();
+ this.handleScrollEnd();
}
},
// Get called when the scrollEl is scrolled (NOTE: this is delayed via debounce)
- scrollHandler: function() {
+ handleDebouncedScroll: function() {
// recompute all coordinates, but *only* if this is *not* part of our scrolling animation
if (!this.scrollIntervalId) {
- this.scrollStop();
+ this.handleScrollEnd();
}
},
// Called when scrolling has stopped, whether through auto scroll, or the user scrolling
- scrollStop: function() {
+ handleScrollEnd: function() {
}
});
-
;;
/* Tracks mouse movements over a component and raises events about which hit the mouse is over.
@@ -2654,18 +2993,16 @@ var HitDragListener = DragListener.extend({
// Called when drag listening starts (but a real drag has not necessarily began).
// ev might be undefined if dragging was started manually.
- listenStart: function(ev) {
+ handleInteractionStart: function(ev) {
var subjectEl = this.subjectEl;
var subjectRect;
var origPoint;
var point;
- DragListener.prototype.listenStart.apply(this, arguments); // call the super-method
-
this.computeCoords();
if (ev) {
- origPoint = { left: ev.pageX, top: ev.pageY };
+ origPoint = { left: getEvX(ev), top: getEvY(ev) };
point = origPoint;
// constrain the point to bounds of the element being dragged
@@ -2695,61 +3032,64 @@ var HitDragListener = DragListener.extend({
this.origHit = null;
this.coordAdjust = null;
}
+
+ // call the super-method. do it after origHit has been computed
+ DragListener.prototype.handleInteractionStart.apply(this, arguments);
},
// Recomputes the drag-critical positions of elements
computeCoords: function() {
this.component.prepareHits();
- this.computeScrollBounds(); // why is this here???
+ this.computeScrollBounds(); // why is this here??????
},
// Called when the actual drag has started
- dragStart: function(ev) {
+ handleDragStart: function(ev) {
var hit;
- DragListener.prototype.dragStart.apply(this, arguments); // call the super-method
+ DragListener.prototype.handleDragStart.apply(this, arguments); // call the super-method
// might be different from this.origHit if the min-distance is large
- hit = this.queryHit(ev.pageX, ev.pageY);
+ hit = this.queryHit(getEvX(ev), getEvY(ev));
// report the initial hit the mouse is over
// especially important if no min-distance and drag starts immediately
if (hit) {
- this.hitOver(hit);
+ this.handleHitOver(hit);
}
},
// Called when the drag moves
- drag: function(dx, dy, ev) {
+ handleDrag: function(dx, dy, ev) {
var hit;
- DragListener.prototype.drag.apply(this, arguments); // call the super-method
+ DragListener.prototype.handleDrag.apply(this, arguments); // call the super-method
- hit = this.queryHit(ev.pageX, ev.pageY);
+ hit = this.queryHit(getEvX(ev), getEvY(ev));
if (!isHitsEqual(hit, this.hit)) { // a different hit than before?
if (this.hit) {
- this.hitOut();
+ this.handleHitOut();
}
if (hit) {
- this.hitOver(hit);
+ this.handleHitOver(hit);
}
}
},
// Called when dragging has been stopped
- dragStop: function() {
- this.hitDone();
- DragListener.prototype.dragStop.apply(this, arguments); // call the super-method
+ handleDragEnd: function() {
+ this.handleHitDone();
+ DragListener.prototype.handleDragEnd.apply(this, arguments); // call the super-method
},
// Called when a the mouse has just moved over a new hit
- hitOver: function(hit) {
+ handleHitOver: function(hit) {
var isOrig = isHitsEqual(hit, this.origHit);
this.hit = hit;
@@ -2759,26 +3099,26 @@ var HitDragListener = DragListener.extend({
// Called when the mouse has just moved out of a hit
- hitOut: function() {
+ handleHitOut: function() {
if (this.hit) {
this.trigger('hitOut', this.hit);
- this.hitDone();
+ this.handleHitDone();
this.hit = null;
}
},
// Called after a hitOut. Also called before a dragStop
- hitDone: function() {
+ handleHitDone: function() {
if (this.hit) {
this.trigger('hitDone', this.hit);
}
},
- // Called when drag listening has stopped
- listenStop: function() {
- DragListener.prototype.listenStop.apply(this, arguments); // call the super-method
+ // Called when the interaction ends, whether there was a real drag or not
+ handleInteractionEnd: function() {
+ DragListener.prototype.handleInteractionEnd.apply(this, arguments); // call the super-method
this.origHit = null;
this.hit = null;
@@ -2788,8 +3128,8 @@ var HitDragListener = DragListener.extend({
// Called when scrolling has stopped, whether through auto scroll, or the user scrolling
- scrollStop: function() {
- DragListener.prototype.scrollStop.apply(this, arguments); // call the super-method
+ handleScrollEnd: function() {
+ DragListener.prototype.handleScrollEnd.apply(this, arguments); // call the super-method
this.computeCoords(); // hits' absolute positions will be in new places. recompute
},
@@ -2844,7 +3184,7 @@ function isHitPropsWithin(subHit, superHit) {
/* Creates a clone of an element and lets it track the mouse as it moves
----------------------------------------------------------------------------------------------------------------------*/
-var MouseFollower = Class.extend({
+var MouseFollower = Class.extend(ListenerMixin, {
options: null,
@@ -2856,16 +3196,14 @@ var MouseFollower = Class.extend({
top0: null,
left0: null,
- // the initial position of the mouse
- mouseY0: null,
- mouseX0: null,
+ // the absolute coordinates of the initiating touch/mouse action
+ y0: null,
+ x0: null,
// the number of pixels the mouse has moved from its initial position
topDelta: null,
leftDelta: null,
- mousemoveProxy: null, // document mousemove handler, bound to the MouseFollower's `this`
-
isFollowing: false,
isHidden: false,
isAnimating: false, // doing the revert animation?
@@ -2882,8 +3220,8 @@ var MouseFollower = Class.extend({
if (!this.isFollowing) {
this.isFollowing = true;
- this.mouseY0 = ev.pageY;
- this.mouseX0 = ev.pageX;
+ this.y0 = getEvY(ev);
+ this.x0 = getEvX(ev);
this.topDelta = 0;
this.leftDelta = 0;
@@ -2891,7 +3229,12 @@ var MouseFollower = Class.extend({
this.updatePosition();
}
- $(document).on('mousemove', this.mousemoveProxy = proxy(this, 'mousemove'));
+ if (getEvIsTouch(ev)) {
+ this.listenTo($(document), 'touchmove', this.handleMove);
+ }
+ else {
+ this.listenTo($(document), 'mousemove', this.handleMove);
+ }
}
},
@@ -2916,7 +3259,7 @@ var MouseFollower = Class.extend({
if (this.isFollowing && !this.isAnimating) { // disallow more than one stop animation at a time
this.isFollowing = false;
- $(document).off('mousemove', this.mousemoveProxy);
+ this.stopListeningTo($(document));
if (shouldRevert && revertDuration && !this.isHidden) { // do a revert animation?
this.isAnimating = true;
@@ -2942,6 +3285,7 @@ var MouseFollower = Class.extend({
if (!el) {
this.sourceEl.width(); // hack to force IE8 to compute correct bounding box
el = this.el = this.sourceEl.clone()
+ .addClass(this.options.additionalClass || '')
.css({
position: 'absolute',
visibility: '', // in case original element was hidden (commonly through hideEvents())
@@ -2953,8 +3297,13 @@ var MouseFollower = Class.extend({
height: this.sourceEl.height(), // explicit width in case there was a 'bottom' value
opacity: this.options.opacity || '',
zIndex: this.options.zIndex
- })
- .appendTo(this.parentEl);
+ });
+
+ // we don't want long taps or any mouse interaction causing selection/menus.
+ // would use preventSelection(), but that prevents selectstart, causing problems.
+ el.addClass('fc-unselectable');
+
+ el.appendTo(this.parentEl);
}
return el;
@@ -2994,9 +3343,9 @@ var MouseFollower = Class.extend({
// Gets called when the user moves the mouse
- mousemove: function(ev) {
- this.topDelta = ev.pageY - this.mouseY0;
- this.leftDelta = ev.pageX - this.mouseX0;
+ handleMove: function(ev) {
+ this.topDelta = getEvY(ev) - this.y0;
+ this.leftDelta = getEvX(ev) - this.x0;
if (!this.isHidden) {
this.updatePosition();
@@ -3031,7 +3380,7 @@ var MouseFollower = Class.extend({
/* An abstract class comprised of a "grid" of areas that each represent a specific datetime
----------------------------------------------------------------------------------------------------------------------*/
-var Grid = FC.Grid = Class.extend({
+var Grid = FC.Grid = Class.extend(ListenerMixin, MouseIgnorerMixin, {
view: null, // a View object
isRTL: null, // shortcut to the view's isRTL option
@@ -3042,8 +3391,6 @@ var Grid = FC.Grid = Class.extend({
el: null, // the containing element
elsByFill: null, // a hash of jQuery element sets used for rendering each fill. Keyed by fill name.
- externalDragStartProxy: null, // binds the Grid's scope to externalDragStart (in DayGrid.events)
-
// derived from options
eventTimeFormat: null,
displayEventTime: null,
@@ -3056,13 +3403,19 @@ var Grid = FC.Grid = Class.extend({
// TODO: port isTimeScale into same system?
largeUnit: null,
+ dayDragListener: null,
+ segDragListener: null,
+ segResizeListener: null,
+ externalDragListener: null,
+
constructor: function(view) {
this.view = view;
this.isRTL = view.opt('isRTL');
-
this.elsByFill = {};
- this.externalDragStartProxy = proxy(this, 'externalDragStart');
+
+ this.dayDragListener = this.buildDayDragListener();
+ this.initMouseIgnoring();
},
@@ -3195,20 +3548,11 @@ var Grid = FC.Grid = Class.extend({
// Sets the container element that the grid should render inside of.
// Does other DOM-related initializations.
setElement: function(el) {
- var _this = this;
-
this.el = el;
+ preventSelection(el);
- // attach a handler to the grid's root element.
- // jQuery will take care of unregistering them when removeElement gets called.
- el.on('mousedown', function(ev) {
- if (
- !$(ev.target).is('.fc-event-container *, .fc-more') && // not an an event element, or "more.." link
- !$(ev.target).closest('.fc-popover').length // not on a popover (like the "more.." events one)
- ) {
- _this.dayMousedown(ev);
- }
- });
+ this.bindDayHandler('touchstart', this.dayTouchStart);
+ this.bindDayHandler('mousedown', this.dayMousedown);
// attach event-element-related handlers. in Grid.events
// same garbage collection note as above.
@@ -3218,10 +3562,27 @@ var Grid = FC.Grid = Class.extend({
},
+ bindDayHandler: function(name, handler) {
+ var _this = this;
+
+ // attach a handler to the grid's root element.
+ // jQuery will take care of unregistering them when removeElement gets called.
+ this.el.on(name, function(ev) {
+ if (
+ !$(ev.target).is('.fc-event-container *, .fc-more') && // not an an event element, or "more.." link
+ !$(ev.target).closest('.fc-popover').length // not on a popover (like the "more.." events one)
+ ) {
+ return handler.call(_this, ev);
+ }
+ });
+ },
+
+
// Removes the grid's container element from the DOM. Undoes any other DOM-related attachments.
// DOES NOT remove any content beforehand (doesn't clear events or call unrenderDates), unlike View
removeElement: function() {
this.unbindGlobalHandlers();
+ this.clearDragListeners();
this.el.remove();
@@ -3254,18 +3615,47 @@ var Grid = FC.Grid = Class.extend({
// Binds DOM handlers to elements that reside outside the grid, such as the document
bindGlobalHandlers: function() {
- $(document).on('dragstart sortstart', this.externalDragStartProxy); // jqui
+ this.listenTo($(document), {
+ dragstart: this.externalDragStart, // jqui
+ sortstart: this.externalDragStart // jqui
+ });
},
// Unbinds DOM handlers from elements that reside outside the grid
unbindGlobalHandlers: function() {
- $(document).off('dragstart sortstart', this.externalDragStartProxy); // jqui
+ this.stopListeningTo($(document));
},
// Process a mousedown on an element that represents a day. For day clicking and selecting.
dayMousedown: function(ev) {
+ if (!this.isIgnoringMouse) {
+ this.dayDragListener.startInteraction(ev, {
+ //distance: 5, // needs more work if we want dayClick to fire correctly
+ });
+ }
+ },
+
+
+ dayTouchStart: function(ev) {
+ var view = this.view;
+
+ // HACK to prevent a user's clickaway for unselecting a range or an event
+ // from causing a dayClick.
+ if (view.isSelected || view.selectedEvent) {
+ this.tempIgnoreMouse();
+ }
+
+ this.dayDragListener.startInteraction(ev, {
+ delay: this.view.opt('longPressDelay')
+ });
+ },
+
+
+ // Creates a listener that tracks the user's drag across day elements.
+ // For day clicking and selecting.
+ buildDayDragListener: function() {
var _this = this;
var view = this.view;
var isSelectable = view.opt('selectable');
@@ -3276,14 +3666,21 @@ var Grid = FC.Grid = Class.extend({
// if the drag ends on the same day, it is a 'dayClick'.
// if 'selectable' is enabled, this listener also detects selections.
var dragListener = new HitDragListener(this, {
- //distance: 5, // needs more work if we want dayClick to fire correctly
scroll: view.opt('dragScroll'),
+ interactionStart: function() {
+ dayClickHit = dragListener.origHit; // for dayClick, where no dragging happens
+ },
dragStart: function() {
view.unselect(); // since we could be rendering a new selection, we want to clear any old one
},
hitOver: function(hit, isOrig, origHit) {
if (origHit) { // click needs to have started on a hit
- dayClickHit = isOrig ? hit : null; // single-hit selection is a day click
+
+ // if user dragged to another cell at any point, it can no longer be a dayClick
+ if (!isOrig) {
+ dayClickHit = null;
+ }
+
if (isSelectable) {
selectionSpan = _this.computeSelection(
_this.getHitSpan(origHit),
@@ -3304,23 +3701,46 @@ var Grid = FC.Grid = Class.extend({
_this.unrenderSelection();
enableCursor();
},
- listenStop: function(ev) {
- if (dayClickHit) {
- view.triggerDayClick(
- _this.getHitSpan(dayClickHit),
- _this.getHitEl(dayClickHit),
- ev
- );
+ interactionEnd: function(ev, isCancelled) {
+ if (!isCancelled) {
+ if (
+ dayClickHit &&
+ !_this.isIgnoringMouse // see hack in dayTouchStart
+ ) {
+ view.triggerDayClick(
+ _this.getHitSpan(dayClickHit),
+ _this.getHitEl(dayClickHit),
+ ev
+ );
+ }
+ if (selectionSpan) {
+ // the selection will already have been rendered. just report it
+ view.reportSelection(selectionSpan, ev);
+ }
+ enableCursor();
}
- if (selectionSpan) {
- // the selection will already have been rendered. just report it
- view.reportSelection(selectionSpan, ev);
- }
- enableCursor();
}
});
- dragListener.mousedown(ev); // start listening, which will eventually initiate a dragStart
+ return dragListener;
+ },
+
+
+ // Kills all in-progress dragging.
+ // Useful for when public API methods that result in re-rendering are invoked during a drag.
+ // Also useful for when touch devices misbehave and don't fire their touchend.
+ clearDragListeners: function() {
+ this.dayDragListener.endInteraction();
+
+ if (this.segDragListener) {
+ this.segDragListener.endInteraction(); // will clear this.segDragListener
+ }
+ if (this.segResizeListener) {
+ this.segResizeListener.endInteraction(); // will clear this.segResizeListener
+ }
+ if (this.externalDragListener) {
+ this.externalDragListener.endInteraction(); // will clear this.externalDragListener
+ }
},
@@ -3330,10 +3750,11 @@ var Grid = FC.Grid = Class.extend({
// Renders a mock event at the given event location, which contains zoned start/end properties.
+ // Returns all mock event elements.
renderEventLocationHelper: function(eventLocation, sourceSeg) {
var fakeEvent = this.fabricateHelperEvent(eventLocation, sourceSeg);
- this.renderHelper(fakeEvent, sourceSeg); // do the actual rendering
+ return this.renderHelper(fakeEvent, sourceSeg); // do the actual rendering
},
@@ -3361,6 +3782,7 @@ var Grid = FC.Grid = Class.extend({
// Renders a mock event. Given zoned event date properties.
+ // Must return all mock event elements.
renderHelper: function(eventLocation, sourceSeg) {
// subclasses must implement
},
@@ -3640,7 +4062,8 @@ Grid.mixin({
// Unrenders all events currently rendered on the grid
unrenderEvents: function() {
- this.triggerSegMouseout(); // trigger an eventMouseout if user's mouse is over an event
+ this.handleSegMouseout(); // trigger an eventMouseout if user's mouse is over an event
+ this.clearDragListeners();
this.unrenderFgSegs();
this.unrenderBgSegs();
@@ -3768,48 +4191,44 @@ Grid.mixin({
// Attaches event-element-related handlers to the container element and leverage bubbling
bindSegHandlers: function() {
+ this.bindSegHandler('touchstart', this.handleSegTouchStart);
+ this.bindSegHandler('touchend', this.handleSegTouchEnd);
+ this.bindSegHandler('mouseenter', this.handleSegMouseover);
+ this.bindSegHandler('mouseleave', this.handleSegMouseout);
+ this.bindSegHandler('mousedown', this.handleSegMousedown);
+ this.bindSegHandler('click', this.handleSegClick);
+ },
+
+
+ // Executes a handler for any a user-interaction on a segment.
+ // Handler gets called with (seg, ev), and with the `this` context of the Grid
+ bindSegHandler: function(name, handler) {
var _this = this;
- var view = this.view;
- $.each(
- {
- mouseenter: function(seg, ev) {
- _this.triggerSegMouseover(seg, ev);
- },
- mouseleave: function(seg, ev) {
- _this.triggerSegMouseout(seg, ev);
- },
- click: function(seg, ev) {
- return view.trigger('eventClick', this, seg.event, ev); // can return `false` to cancel
- },
- mousedown: function(seg, ev) {
- if ($(ev.target).is('.fc-resizer') && view.isEventResizable(seg.event)) {
- _this.segResizeMousedown(seg, ev, $(ev.target).is('.fc-start-resizer'));
- }
- else if (view.isEventDraggable(seg.event)) {
- _this.segDragMousedown(seg, ev);
- }
- }
- },
- function(name, func) {
- // attach the handler to the container element and only listen for real event elements via bubbling
- _this.el.on(name, '.fc-event-container > *', function(ev) {
- var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents
+ this.el.on(name, '.fc-event-container > *', function(ev) {
+ var seg = $(this).data('fc-seg'); // grab segment data. put there by View::renderEvents
- // only call the handlers if there is not a drag/resize in progress
- if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {
- return func.call(this, seg, ev); // `this` will be the event element
- }
- });
+ // only call the handlers if there is not a drag/resize in progress
+ if (seg && !_this.isDraggingSeg && !_this.isResizingSeg) {
+ return handler.call(_this, seg, ev); // context will be the Grid
}
- );
+ });
+ },
+
+
+ handleSegClick: function(seg, ev) {
+ return this.view.trigger('eventClick', seg.el[0], seg.event, ev); // can return `false` to cancel
},
// Updates internal state and triggers handlers for when an event element is moused over
- triggerSegMouseover: function(seg, ev) {
- if (!this.mousedOverSeg) {
+ handleSegMouseover: function(seg, ev) {
+ if (
+ !this.isIgnoringMouse &&
+ !this.mousedOverSeg
+ ) {
this.mousedOverSeg = seg;
+ seg.el.addClass('fc-allow-mouse-resize');
this.view.trigger('eventMouseover', seg.el[0], seg.event, ev);
}
},
@@ -3817,56 +4236,132 @@ Grid.mixin({
// Updates internal state and triggers handlers for when an event element is moused out.
// Can be given no arguments, in which case it will mouseout the segment that was previously moused over.
- triggerSegMouseout: function(seg, ev) {
+ handleSegMouseout: function(seg, ev) {
ev = ev || {}; // if given no args, make a mock mouse event
if (this.mousedOverSeg) {
seg = seg || this.mousedOverSeg; // if given no args, use the currently moused-over segment
this.mousedOverSeg = null;
+ seg.el.removeClass('fc-allow-mouse-resize');
this.view.trigger('eventMouseout', seg.el[0], seg.event, ev);
}
},
+ handleSegMousedown: function(seg, ev) {
+ var isResizing = this.startSegResize(seg, ev, { distance: 5 });
+
+ if (!isResizing && this.view.isEventDraggable(seg.event)) {
+ this.buildSegDragListener(seg)
+ .startInteraction(ev, {
+ distance: 5
+ });
+ }
+ },
+
+
+ handleSegTouchStart: function(seg, ev) {
+ var view = this.view;
+ var event = seg.event;
+ var isSelected = view.isEventSelected(event);
+ var isDraggable = view.isEventDraggable(event);
+ var isResizable = view.isEventResizable(event);
+ var isResizing = false;
+ var dragListener;
+
+ if (isSelected && isResizable) {
+ // only allow resizing of the event is selected
+ isResizing = this.startSegResize(seg, ev);
+ }
+
+ if (!isResizing && (isDraggable || isResizable)) { // allowed to be selected?
+
+ dragListener = isDraggable ?
+ this.buildSegDragListener(seg) :
+ this.buildSegSelectListener(seg); // seg isn't draggable, but still needs to be selected
+
+ dragListener.startInteraction(ev, { // won't start if already started
+ delay: isSelected ? 0 : this.view.opt('longPressDelay') // do delay if not already selected
+ });
+ }
+
+ // a long tap simulates a mouseover. ignore this bogus mouseover.
+ this.tempIgnoreMouse();
+ },
+
+
+ handleSegTouchEnd: function(seg, ev) {
+ // touchstart+touchend = click, which simulates a mouseover.
+ // ignore this bogus mouseover.
+ this.tempIgnoreMouse();
+ },
+
+
+ // returns boolean whether resizing actually started or not.
+ // assumes the seg allows resizing.
+ // `dragOptions` are optional.
+ startSegResize: function(seg, ev, dragOptions) {
+ if ($(ev.target).is('.fc-resizer')) {
+ this.buildSegResizeListener(seg, $(ev.target).is('.fc-start-resizer'))
+ .startInteraction(ev, dragOptions);
+ return true;
+ }
+ return false;
+ },
+
+
+
/* Event Dragging
------------------------------------------------------------------------------------------------------------------*/
- // Called when the user does a mousedown on an event, which might lead to dragging.
+ // Builds a listener that will track user-dragging on an event segment.
// Generic enough to work with any type of Grid.
- segDragMousedown: function(seg, ev) {
+ // Has side effect of setting/unsetting `segDragListener`
+ buildSegDragListener: function(seg) {
var _this = this;
var view = this.view;
var calendar = view.calendar;
var el = seg.el;
var event = seg.event;
+ var isDragging;
+ var mouseFollower; // A clone of the original element that will move with the mouse
var dropLocation; // zoned event date properties
- // A clone of the original element that will move with the mouse
- var mouseFollower = new MouseFollower(seg.el, {
- parentEl: view.el,
- opacity: view.opt('dragOpacity'),
- revertDuration: view.opt('dragRevertDuration'),
- zIndex: 2 // one above the .fc-view
- });
+ if (this.segDragListener) {
+ return this.segDragListener;
+ }
// Tracks mouse movement over the *view's* coordinate map. Allows dragging and dropping between subcomponents
// of the view.
- var dragListener = new HitDragListener(view, {
- distance: 5,
+ var dragListener = this.segDragListener = new HitDragListener(view, {
scroll: view.opt('dragScroll'),
subjectEl: el,
subjectCenter: true,
- listenStart: function(ev) {
+ interactionStart: function(ev) {
+ isDragging = false;
+ mouseFollower = new MouseFollower(seg.el, {
+ additionalClass: 'fc-dragging',
+ parentEl: view.el,
+ opacity: dragListener.isTouch ? null : view.opt('dragOpacity'),
+ revertDuration: view.opt('dragRevertDuration'),
+ zIndex: 2 // one above the .fc-view
+ });
mouseFollower.hide(); // don't show until we know this is a real drag
mouseFollower.start(ev);
},
dragStart: function(ev) {
- _this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
+ if (dragListener.isTouch && !view.isEventSelected(event)) {
+ // if not previously selected, will fire after a delay. then, select the event
+ view.selectEvent(event);
+ }
+ isDragging = true;
+ _this.handleSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
_this.segDragStart(seg, ev);
view.hideEvent(event); // hide all event segments. our mouseFollower will take over
},
hitOver: function(hit, isOrig, origHit) {
+ var dragHelperEls;
// starting hit could be forced (DayGrid.limit)
if (seg.hit) {
@@ -3886,7 +4381,13 @@ Grid.mixin({
}
// if a valid drop location, have the subclass render a visual indication
- if (dropLocation && view.renderDrag(dropLocation, seg)) {
+ if (dropLocation && (dragHelperEls = view.renderDrag(dropLocation, seg))) {
+
+ dragHelperEls.addClass('fc-dragging');
+ if (!dragListener.isTouch) {
+ _this.applyDragOpacity(dragHelperEls);
+ }
+
mouseFollower.hide(); // if the subclass is already using a mock event "helper", hide our own
}
else {
@@ -3902,27 +4403,54 @@ Grid.mixin({
mouseFollower.show(); // show in case we are moving out of all hits
dropLocation = null;
},
- hitDone: function() { // Called after a hitOut OR before a dragStop
+ hitDone: function() { // Called after a hitOut OR before a dragEnd
enableCursor();
},
- dragStop: function(ev) {
+ interactionEnd: function(ev) {
// do revert animation if hasn't changed. calls a callback when finished (whether animation or not)
mouseFollower.stop(!dropLocation, function() {
- view.unrenderDrag();
- view.showEvent(event);
- _this.segDragStop(seg, ev);
-
+ if (isDragging) {
+ view.unrenderDrag();
+ view.showEvent(event);
+ _this.segDragStop(seg, ev);
+ }
if (dropLocation) {
view.reportEventDrop(event, dropLocation, this.largeUnit, el, ev);
}
});
- },
- listenStop: function() {
- mouseFollower.stop(); // put in listenStop in case there was a mousedown but the drag never started
+ _this.segDragListener = null;
}
});
- dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart
+ return dragListener;
+ },
+
+
+ // seg isn't draggable, but let's use a generic DragListener
+ // simply for the delay, so it can be selected.
+ // Has side effect of setting/unsetting `segDragListener`
+ buildSegSelectListener: function(seg) {
+ var _this = this;
+ var view = this.view;
+ var event = seg.event;
+
+ if (this.segDragListener) {
+ return this.segDragListener;
+ }
+
+ var dragListener = this.segDragListener = new DragListener({
+ dragStart: function(ev) {
+ if (dragListener.isTouch && !view.isEventSelected(event)) {
+ // if not previously selected, will fire after a delay. then, select the event
+ view.selectEvent(event);
+ }
+ },
+ interactionEnd: function(ev) {
+ _this.segDragListener = null;
+ }
+ });
+
+ return dragListener;
},
@@ -4038,8 +4566,8 @@ Grid.mixin({
var dropLocation; // a null value signals an unsuccessful drag
// listener that tracks mouse movement over date-associated pixel regions
- var dragListener = new HitDragListener(this, {
- listenStart: function() {
+ var dragListener = _this.externalDragListener = new HitDragListener(this, {
+ interactionStart: function() {
_this.isDraggingExternal = true;
},
hitOver: function(hit) {
@@ -4063,17 +4591,16 @@ Grid.mixin({
hitOut: function() {
dropLocation = null; // signal unsuccessful
},
- hitDone: function() { // Called after a hitOut OR before a dragStop
+ hitDone: function() { // Called after a hitOut OR before a dragEnd
enableCursor();
_this.unrenderDrag();
},
- dragStop: function() {
+ interactionEnd: function(ev) {
if (dropLocation) { // element was dropped on a valid hit
_this.view.reportExternalDrop(meta, dropLocation, el, ev, ui);
}
- },
- listenStop: function() {
_this.isDraggingExternal = false;
+ _this.externalDragListener = null;
}
});
@@ -4114,6 +4641,7 @@ Grid.mixin({
// `dropLocation` contains hypothetical start/end/allDay values the event would have if dropped. end can be null.
// `seg` is the internal segment object that is being dragged. If dragging an external element, `seg` is null.
// A truthy returned value indicates this method has rendered a helper element.
+ // Must return elements used for any mock events.
renderDrag: function(dropLocation, seg) {
// subclasses must implement
},
@@ -4129,24 +4657,28 @@ Grid.mixin({
------------------------------------------------------------------------------------------------------------------*/
- // Called when the user does a mousedown on an event's resizer, which might lead to resizing.
+ // Creates a listener that tracks the user as they resize an event segment.
// Generic enough to work with any type of Grid.
- segResizeMousedown: function(seg, ev, isStart) {
+ buildSegResizeListener: function(seg, isStart) {
var _this = this;
var view = this.view;
var calendar = view.calendar;
var el = seg.el;
var event = seg.event;
var eventEnd = calendar.getEventEnd(event);
+ var isDragging;
var resizeLocation; // zoned event date properties. falsy if invalid resize
// Tracks mouse movement over the *grid's* coordinate map
- var dragListener = new HitDragListener(this, {
- distance: 5,
+ var dragListener = this.segResizeListener = new HitDragListener(this, {
scroll: view.opt('dragScroll'),
subjectEl: el,
+ interactionStart: function() {
+ isDragging = false;
+ },
dragStart: function(ev) {
- _this.triggerSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
+ isDragging = true;
+ _this.handleSegMouseout(seg, ev); // ensure a mouseout on the manipulated event has been reported
_this.segResizeStart(seg, ev);
},
hitOver: function(hit, isOrig, origHit) {
@@ -4181,16 +4713,18 @@ Grid.mixin({
view.showEvent(event);
enableCursor();
},
- dragStop: function(ev) {
- _this.segResizeStop(seg, ev);
-
+ interactionEnd: function(ev) {
+ if (isDragging) {
+ _this.segResizeStop(seg, ev);
+ }
if (resizeLocation) { // valid date to resize to?
view.reportEventResize(event, resizeLocation, this.largeUnit, el, ev);
}
+ _this.segResizeListener = null;
}
});
- dragListener.mousedown(ev); // start listening, which will eventually lead to a dragStart
+ return dragListener;
},
@@ -4267,6 +4801,7 @@ Grid.mixin({
// Renders a visual indication of an event being resized.
// `range` has the updated dates of the event. `seg` is the original segment object involved in the drag.
+ // Must return elements used for any mock events.
renderEventResize: function(range, seg) {
// subclasses must implement
},
@@ -4312,6 +4847,7 @@ Grid.mixin({
// Generic utility for generating the HTML classNames for an event segment's element
getSegClasses: function(seg, isDraggable, isResizable) {
+ var view = this.view;
var event = seg.event;
var classes = [
'fc-event',
@@ -4329,6 +4865,11 @@ Grid.mixin({
classes.push('fc-resizable');
}
+ // event is currently selected? attach a className.
+ if (view.isEventSelected(event)) {
+ classes.push('fc-selected');
+ }
+
return classes;
},
@@ -5311,10 +5852,7 @@ var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {
// if a segment from the same calendar but another component is being dragged, render a helper event
if (seg && !seg.el.closest(this.el).length) {
- this.renderEventLocationHelper(eventLocation, seg);
- this.applyDragOpacity(this.helperEls);
-
- return true; // a helper has been rendered
+ return this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements
}
},
@@ -5333,7 +5871,7 @@ var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {
// Renders a visual indication of an event being resized
renderEventResize: function(eventLocation, seg) {
this.renderHighlight(this.eventToSpan(eventLocation));
- this.renderEventLocationHelper(eventLocation, seg);
+ return this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements
},
@@ -5379,7 +5917,9 @@ var DayGrid = FC.DayGrid = Grid.extend(DayTableMixin, {
helperNodes.push(skeletonEl[0]);
});
- this.helperEls = $(helperNodes); // array -> jQuery set
+ return ( // must return the elements rendered
+ this.helperEls = $(helperNodes) // array -> jQuery set
+ );
},
@@ -6165,6 +6705,7 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
labelInterval: null, // duration of how often a label should be displayed for a slot
colEls: null, // cells elements in the day-row background
+ slatContainerEl: null, // div that wraps all the slat rows
slatEls: null, // elements running horizontally across all columns
nowIndicatorEls: null,
@@ -6184,7 +6725,8 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
renderDates: function() {
this.el.html(this.renderHtml());
this.colEls = this.el.find('.fc-day');
- this.slatEls = this.el.find('.fc-slats tr');
+ this.slatContainerEl = this.el.find('.fc-slats');
+ this.slatEls = this.slatContainerEl.find('tr');
this.colCoordCache = new CoordCache({
els: this.colEls,
@@ -6463,6 +7005,11 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
},
+ getTotalSlatHeight: function() {
+ return this.slatContainerEl.outerHeight();
+ },
+
+
// Computes the top coordinate, relative to the bounds of the grid, of the given date.
// A `startOfDayDate` must be given for avoiding ambiguity over how to treat midnight.
computeDateTop: function(date, startOfDayDate) {
@@ -6511,13 +7058,10 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
renderDrag: function(eventLocation, seg) {
if (seg) { // if there is event information for this drag, render a helper event
- this.renderEventLocationHelper(eventLocation, seg);
- for (var i = 0; i < this.helperSegs.length; i++) {
- this.applyDragOpacity(this.helperSegs[i].el);
- }
-
- return true; // signal that a helper has been rendered
+ // returns mock event elements
+ // signal that a helper has been rendered
+ return this.renderEventLocationHelper(eventLocation, seg);
}
else {
// otherwise, just render a highlight
@@ -6539,7 +7083,7 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
// Renders a visual indication of an event being resized
renderEventResize: function(eventLocation, seg) {
- this.renderEventLocationHelper(eventLocation, seg);
+ return this.renderEventLocationHelper(eventLocation, seg); // returns mock event elements
},
@@ -6555,7 +7099,7 @@ var TimeGrid = FC.TimeGrid = Grid.extend(DayTableMixin, {
// Renders a mock "helper" event. `sourceSeg` is the original segment object and might be null (an external drag)
renderHelper: function(event, sourceSeg) {
- this.renderHelperSegs(this.eventToSegs(event), sourceSeg);
+ return this.renderHelperSegs(this.eventToSegs(event), sourceSeg); // returns mock event elements
},
@@ -6749,6 +7293,7 @@ TimeGrid.mixin({
renderHelperSegs: function(segs, sourceSeg) {
+ var helperEls = [];
var i, seg;
var sourceEl;
@@ -6766,9 +7311,12 @@ TimeGrid.mixin({
'margin-right': sourceEl.css('margin-right')
});
}
+ helperEls.push(seg.el[0]);
}
this.helperSegs = segs;
+
+ return $(helperEls); // must return rendered helpers
},
@@ -7279,7 +7827,7 @@ function isSlotSegCollision(seg1, seg2) {
/* An abstract class from which other views inherit from
----------------------------------------------------------------------------------------------------------------------*/
-var View = FC.View = Class.extend({
+var View = FC.View = Class.extend(EmitterMixin, ListenerMixin, {
type: null, // subclass' view name (string)
name: null, // deprecated. use `type` instead
@@ -7306,13 +7854,10 @@ var View = FC.View = Class.extend({
isRTL: false,
isSelected: false, // boolean whether a range of time is user-selected or not
+ selectedEvent: null,
eventOrderSpecs: null, // criteria for ordering events when they have same date/time
- // subclasses can optionally use a scroll container
- scrollerEl: null, // the element that will most likely scroll when content is too tall
- scrollTop: null, // cached vertical scroll value
-
// classNames styled by jqui themes
widgetHeaderClass: null,
widgetContentClass: null,
@@ -7322,9 +7867,6 @@ var View = FC.View = Class.extend({
nextDayThreshold: null,
isHiddenDayHash: null,
- // document handlers, bound to `this` object
- documentMousedownProxy: null, // TODO: doesn't work with touch
-
// now indicator
isNowIndicatorRendered: null,
initialNowDate: null, // result first getNow call
@@ -7347,8 +7889,6 @@ var View = FC.View = Class.extend({
this.eventOrderSpecs = parseFieldSpecs(this.opt('eventOrder'));
- this.documentMousedownProxy = proxy(this, 'documentMousedown');
-
this.initialize();
},
@@ -7674,13 +8214,14 @@ var View = FC.View = Class.extend({
// Binds DOM handlers to elements that reside outside the view container, such as the document
bindGlobalHandlers: function() {
- $(document).on('mousedown', this.documentMousedownProxy);
+ this.listenTo($(document), 'mousedown', this.handleDocumentMousedown);
+ this.listenTo($(document), 'touchstart', this.processUnselect);
},
// Unbinds DOM handlers from elements that reside outside the view container
unbindGlobalHandlers: function() {
- $(document).off('mousedown', this.documentMousedownProxy);
+ this.stopListeningTo($(document));
},
@@ -7848,27 +8389,6 @@ var View = FC.View = Class.extend({
------------------------------------------------------------------------------------------------------------------*/
- // Given the total height of the view, return the number of pixels that should be used for the scroller.
- // Utility for subclasses.
- computeScrollerHeight: function(totalHeight) {
- var scrollerEl = this.scrollerEl;
- var both;
- var otherHeight; // cumulative height of everything that is not the scrollerEl in the view (header+borders)
-
- both = this.el.add(scrollerEl);
-
- // fuckin IE8/9/10/11 sometimes returns 0 for dimensions. this weird hack was the only thing that worked
- both.css({
- position: 'relative', // cause a reflow, which will force fresh dimension recalculation
- left: -1 // ensure reflow in case the el was already relative. negative is less likely to cause new scroll
- });
- otherHeight = this.el.outerHeight() - scrollerEl.height(); // grab the dimensions
- both.css({ position: '', left: '' }); // undo hack
-
- return totalHeight - otherHeight;
- },
-
-
// Computes the initial pre-configured scroll state prior to allowing the user to change it.
// Given the scroll state from the previous rendering. If first time rendering, given null.
computeInitialScroll: function(previousScrollState) {
@@ -7878,17 +8398,13 @@ var View = FC.View = Class.extend({
// Retrieves the view's current natural scroll state. Can return an arbitrary format.
queryScroll: function() {
- if (this.scrollerEl) {
- return this.scrollerEl.scrollTop(); // operates on scrollerEl by default
- }
+ // subclasses must implement
},
// Sets the view's scroll state. Will accept the same format computeInitialScroll and queryScroll produce.
setScroll: function(scrollState) {
- if (this.scrollerEl) {
- return this.scrollerEl.scrollTop(scrollState); // operates on scrollerEl by default
- }
+ // subclasses must implement
},
@@ -8103,7 +8619,8 @@ var View = FC.View = Class.extend({
// Renders a visual indication of a event or external-element drag over the given drop zone.
- // If an external-element, seg will be `null`
+ // If an external-element, seg will be `null`.
+ // Must return elements used for any mock events.
renderDrag: function(dropLocation, seg) {
// subclasses must implement
},
@@ -8166,7 +8683,7 @@ var View = FC.View = Class.extend({
},
- /* Selection
+ /* Selection (time range)
------------------------------------------------------------------------------------------------------------------*/
@@ -8224,13 +8741,62 @@ var View = FC.View = Class.extend({
},
- // Handler for unselecting when the user clicks something and the 'unselectAuto' setting is on
- documentMousedown: function(ev) {
+ /* Event Selection
+ ------------------------------------------------------------------------------------------------------------------*/
+
+
+ selectEvent: function(event) {
+ if (!this.selectedEvent || this.selectedEvent !== event) {
+ this.unselectEvent();
+ this.renderedEventSegEach(function(seg) {
+ seg.el.addClass('fc-selected');
+ }, event);
+ this.selectedEvent = event;
+ }
+ },
+
+
+ unselectEvent: function() {
+ if (this.selectedEvent) {
+ this.renderedEventSegEach(function(seg) {
+ seg.el.removeClass('fc-selected');
+ }, this.selectedEvent);
+ this.selectedEvent = null;
+ }
+ },
+
+
+ isEventSelected: function(event) {
+ // event references might change on refetchEvents(), while selectedEvent doesn't,
+ // so compare IDs
+ return this.selectedEvent && this.selectedEvent._id === event._id;
+ },
+
+
+ /* Mouse / Touch Unselecting (time range & event unselection)
+ ------------------------------------------------------------------------------------------------------------------*/
+ // TODO: move consistently to down/start or up/end?
+ // TODO: don't kill previous selection if touch scrolling
+
+
+ handleDocumentMousedown: function(ev) {
+ if (isPrimaryMouseButton(ev)) {
+ this.processUnselect(ev);
+ }
+ },
+
+
+ processUnselect: function(ev) {
+ this.processRangeUnselect(ev);
+ this.processEventUnselect(ev);
+ },
+
+
+ processRangeUnselect: function(ev) {
var ignore;
- // is there a selection, and has the user made a proper left click?
- if (this.isSelected && this.opt('unselectAuto') && isPrimaryMouseButton(ev)) {
-
+ // is there a time-range selection?
+ if (this.isSelected && this.opt('unselectAuto')) {
// only unselect if the clicked element is not identical to or inside of an 'unselectCancel' element
ignore = this.opt('unselectCancel');
if (!ignore || !$(ev.target).closest(ignore).length) {
@@ -8240,6 +8806,15 @@ var View = FC.View = Class.extend({
},
+ processEventUnselect: function(ev) {
+ if (this.selectedEvent) {
+ if (!$(ev.target).closest('.fc-selected').length) {
+ this.unselectEvent();
+ }
+ }
+ },
+
+
/* Day Click
------------------------------------------------------------------------------------------------------------------*/
@@ -8354,6 +8929,127 @@ var View = FC.View = Class.extend({
;;
+/*
+Embodies a div that has potential scrollbars
+*/
+var Scroller = FC.Scroller = Class.extend({
+
+ el: null, // the guaranteed outer element
+ scrollEl: null, // the element with the scrollbars
+ overflowX: null,
+ overflowY: null,
+
+
+ constructor: function(options) {
+ options = options || {};
+ this.overflowX = options.overflowX || options.overflow || 'auto';
+ this.overflowY = options.overflowY || options.overflow || 'auto';
+ },
+
+
+ render: function() {
+ this.el = this.renderEl();
+ this.applyOverflow();
+ },
+
+
+ renderEl: function() {
+ return (this.scrollEl = $(''));
+ },
+
+
+ // sets to natural height, unlocks overflow
+ clear: function() {
+ this.setHeight('auto');
+ this.applyOverflow();
+ },
+
+
+ destroy: function() {
+ this.el.remove();
+ },
+
+
+ // Overflow
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ applyOverflow: function() {
+ this.scrollEl.css({
+ 'overflow-x': this.overflowX,
+ 'overflow-y': this.overflowY
+ });
+ },
+
+
+ // Causes any 'auto' overflow values to resolves to 'scroll' or 'hidden'.
+ // Useful for preserving scrollbar widths regardless of future resizes.
+ // Can pass in scrollbarWidths for optimization.
+ lockOverflow: function(scrollbarWidths) {
+ var overflowX = this.overflowX;
+ var overflowY = this.overflowY;
+
+ scrollbarWidths = scrollbarWidths || this.getScrollbarWidths();
+
+ if (overflowX === 'auto') {
+ overflowX = (
+ scrollbarWidths.top || scrollbarWidths.bottom || // horizontal scrollbars?
+ // OR scrolling pane with massless scrollbars?
+ this.scrollEl[0].scrollWidth - 1 > this.scrollEl[0].clientWidth
+ // subtract 1 because of IE off-by-one issue
+ ) ? 'scroll' : 'hidden';
+ }
+
+ if (overflowY === 'auto') {
+ overflowY = (
+ scrollbarWidths.left || scrollbarWidths.right || // vertical scrollbars?
+ // OR scrolling pane with massless scrollbars?
+ this.scrollEl[0].scrollHeight - 1 > this.scrollEl[0].clientHeight
+ // subtract 1 because of IE off-by-one issue
+ ) ? 'scroll' : 'hidden';
+ }
+
+ this.scrollEl.css({ 'overflow-x': overflowX, 'overflow-y': overflowY });
+ },
+
+
+ // Getters / Setters
+ // -----------------------------------------------------------------------------------------------------------------
+
+
+ setHeight: function(height) {
+ this.scrollEl.height(height);
+ },
+
+
+ getScrollTop: function() {
+ return this.scrollEl.scrollTop();
+ },
+
+
+ setScrollTop: function(top) {
+ this.scrollEl.scrollTop(top);
+ },
+
+
+ getClientWidth: function() {
+ return this.scrollEl[0].clientWidth;
+ },
+
+
+ getClientHeight: function() {
+ return this.scrollEl[0].clientHeight;
+ },
+
+
+ getScrollbarWidths: function() {
+ return getScrollbarWidths(this.scrollEl);
+ }
+
+});
+
+;;
+
var Calendar = FC.Calendar = Class.extend({
dirDefaults: null, // option defaults related to LTR or RTL
@@ -8608,7 +9304,7 @@ var Calendar = FC.Calendar = Class.extend({
});
-Calendar.mixin(Emitter);
+Calendar.mixin(EmitterMixin);
function Calendar_constructor(element, overrides) {
@@ -9369,7 +10065,9 @@ Calendar.defaults = {
dayPopoverFormat: 'LL',
handleWindowResize: true,
- windowResizeDelay: 200 // milliseconds before an updateSize happens
+ windowResizeDelay: 200, // milliseconds before an updateSize happens
+
+ longPressDelay: 1000
};
@@ -10368,6 +11066,8 @@ function EventManager(options) { // assumed to be a calendar
assignDatesToEvent(start, end, allDay, out);
}
+ t.normalizeEvent(out); // hook for external use. a prototype method
+
return out;
}
@@ -10900,6 +11600,12 @@ function EventManager(options) { // assumed to be a calendar
}
+// hook for external libs to manipulate event properties upon creation.
+// should manipulate the event in-place.
+Calendar.prototype.normalizeEvent = function(event) {
+};
+
+
// Returns a list of events that the given event should be compared against when being considered for a move to
// the specified span. Attached to the Calendar's prototype because EventManager is a mixin for a Calendar.
Calendar.prototype.getPeerEvents = function(span, event) {
@@ -10937,6 +11643,8 @@ function backupEventDates(event) {
var BasicView = FC.BasicView = View.extend({
+ scroller: null,
+
dayGridClass: DayGrid, // class the dayGrid will be instantiated from (overridable by subclasses)
dayGrid: null, // the main subcomponent that does most of the heavy lifting
@@ -10951,6 +11659,11 @@ var BasicView = FC.BasicView = View.extend({
initialize: function() {
this.dayGrid = this.instantiateDayGrid();
+
+ this.scroller = new Scroller({
+ overflowX: 'hidden',
+ overflowY: 'auto'
+ });
},
@@ -11003,9 +11716,12 @@ var BasicView = FC.BasicView = View.extend({
this.el.addClass('fc-basic-view').html(this.renderSkeletonHtml());
this.renderHead();
- this.scrollerEl = this.el.find('.fc-day-grid-container');
+ this.scroller.render();
+ var dayGridContainerEl = this.scroller.el.addClass('fc-day-grid-container');
+ var dayGridEl = $('').appendTo(dayGridContainerEl);
+ this.el.find('.fc-body > tr > td').append(dayGridContainerEl);
- this.dayGrid.setElement(this.el.find('.fc-day-grid'));
+ this.dayGrid.setElement(dayGridEl);
this.dayGrid.renderDates(this.hasRigidRows());
},
@@ -11024,6 +11740,7 @@ var BasicView = FC.BasicView = View.extend({
unrenderDates: function() {
this.dayGrid.unrenderDates();
this.dayGrid.removeElement();
+ this.scroller.destroy();
},
@@ -11044,11 +11761,7 @@ var BasicView = FC.BasicView = View.extend({
'' +
'' +
'' +
- '' +
- '' +
- ' | ' +
+ ' | ' +
'
' +
'' +
'';
@@ -11091,9 +11804,10 @@ var BasicView = FC.BasicView = View.extend({
setHeight: function(totalHeight, isAuto) {
var eventLimit = this.opt('eventLimit');
var scrollerHeight;
+ var scrollbarWidths;
// reset all heights to be natural
- unsetScroller(this.scrollerEl);
+ this.scroller.clear();
uncompensateScroll(this.headRowEl);
this.dayGrid.removeSegPopover(); // kill the "more" popover if displayed
@@ -11103,6 +11817,8 @@ var BasicView = FC.BasicView = View.extend({
this.dayGrid.limitRows(eventLimit); // limit the levels first so the height can redistribute after
}
+ // distribute the height to the rows
+ // (totalHeight is a "recommended" value if isAuto)
scrollerHeight = this.computeScrollerHeight(totalHeight);
this.setGridHeight(scrollerHeight, isAuto);
@@ -11111,17 +11827,33 @@ var BasicView = FC.BasicView = View.extend({
this.dayGrid.limitRows(eventLimit); // limit the levels after the grid's row heights have been set
}
- if (!isAuto && setPotentialScroller(this.scrollerEl, scrollerHeight)) { // using scrollbars?
+ if (!isAuto) { // should we force dimensions of the scroll container?
- compensateScroll(this.headRowEl, getScrollbarWidths(this.scrollerEl));
+ this.scroller.setHeight(scrollerHeight);
+ scrollbarWidths = this.scroller.getScrollbarWidths();
- // doing the scrollbar compensation might have created text overflow which created more height. redo
- scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.scrollerEl.height(scrollerHeight);
+ if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
+
+ compensateScroll(this.headRowEl, scrollbarWidths);
+
+ // doing the scrollbar compensation might have created text overflow which created more height. redo
+ scrollerHeight = this.computeScrollerHeight(totalHeight);
+ this.scroller.setHeight(scrollerHeight);
+ }
+
+ // guarantees the same scrollbar widths
+ this.scroller.lockOverflow(scrollbarWidths);
}
},
+ // given a desired total height of the view, returns what the height of the scroller should be
+ computeScrollerHeight: function(totalHeight) {
+ return totalHeight -
+ subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
+ },
+
+
// Sets the height of just the DayGrid component in this view
setGridHeight: function(height, isAuto) {
if (isAuto) {
@@ -11133,6 +11865,20 @@ var BasicView = FC.BasicView = View.extend({
},
+ /* Scroll
+ ------------------------------------------------------------------------------------------------------------------*/
+
+
+ queryScroll: function() {
+ return this.scroller.getScrollTop();
+ },
+
+
+ setScroll: function(top) {
+ this.scroller.setScrollTop(top);
+ },
+
+
/* Hit Areas
------------------------------------------------------------------------------------------------------------------*/
// forward all hit-related method calls to dayGrid
@@ -11368,6 +12114,8 @@ fcViews.month = {
var AgendaView = FC.AgendaView = View.extend({
+ scroller: null,
+
timeGridClass: TimeGrid, // class used to instantiate the timeGrid. subclasses can override
timeGrid: null, // the main time-grid subcomponent of this view
@@ -11377,11 +12125,10 @@ var AgendaView = FC.AgendaView = View.extend({
axisWidth: null, // the width of the time axis running down the side
headContainerEl: null, // div that hold's the timeGrid's rendered date header
- noScrollRowEls: null, // set of fake row elements that must compensate when scrollerEl has scrollbars
+ noScrollRowEls: null, // set of fake row elements that must compensate when scroller has scrollbars
// when the time-grid isn't tall enough to occupy the given height, we render an
underneath
bottomRuleEl: null,
- bottomRuleHeight: null,
initialize: function() {
@@ -11390,6 +12137,11 @@ var AgendaView = FC.AgendaView = View.extend({
if (this.opt('allDaySlot')) { // should we display the "all-day" area?
this.dayGrid = this.instantiateDayGrid(); // the all-day subcomponent of this view
}
+
+ this.scroller = new Scroller({
+ overflowX: 'hidden',
+ overflowY: 'auto'
+ });
},
@@ -11430,10 +12182,12 @@ var AgendaView = FC.AgendaView = View.extend({
this.el.addClass('fc-agenda-view').html(this.renderSkeletonHtml());
this.renderHead();
- // the element that wraps the time-grid that will probably scroll
- this.scrollerEl = this.el.find('.fc-time-grid-container');
+ this.scroller.render();
+ var timeGridWrapEl = this.scroller.el.addClass('fc-time-grid-container');
+ var timeGridEl = $('').appendTo(timeGridWrapEl);
+ this.el.find('.fc-body > tr > td').append(timeGridWrapEl);
- this.timeGrid.setElement(this.el.find('.fc-time-grid'));
+ this.timeGrid.setElement(timeGridEl);
this.timeGrid.renderDates();
// the
that sometimes displays under the time-grid
@@ -11470,6 +12224,8 @@ var AgendaView = FC.AgendaView = View.extend({
this.dayGrid.unrenderDates();
this.dayGrid.removeElement();
}
+
+ this.scroller.destroy();
},
@@ -11491,9 +12247,6 @@ var AgendaView = FC.AgendaView = View.extend({
'' :
''
) +
- '' +
'' +
'' +
'' +
@@ -11573,16 +12326,11 @@ var AgendaView = FC.AgendaView = View.extend({
setHeight: function(totalHeight, isAuto) {
var eventLimit;
var scrollerHeight;
-
- if (this.bottomRuleHeight === null) {
- // calculate the height of the rule the very first time
- this.bottomRuleHeight = this.bottomRuleEl.outerHeight();
- }
- this.bottomRuleEl.hide(); // .show() will be called later if this
is necessary
+ var scrollbarWidths;
// reset all dimensions back to the original state
- this.scrollerEl.css('overflow', '');
- unsetScroller(this.scrollerEl);
+ this.bottomRuleEl.hide(); // .show() will be called later if this
is necessary
+ this.scroller.clear(); // sets height to 'auto' and clears overflow
uncompensateScroll(this.noScrollRowEls);
// limit number of events in the all-day area
@@ -11598,28 +12346,46 @@ var AgendaView = FC.AgendaView = View.extend({
}
}
- if (!isAuto) { // should we force dimensions of the scroll container, or let the contents be natural height?
+ if (!isAuto) { // should we force dimensions of the scroll container?
scrollerHeight = this.computeScrollerHeight(totalHeight);
- if (setPotentialScroller(this.scrollerEl, scrollerHeight)) { // using scrollbars?
+ this.scroller.setHeight(scrollerHeight);
+ scrollbarWidths = this.scroller.getScrollbarWidths();
+
+ if (scrollbarWidths.left || scrollbarWidths.right) { // using scrollbars?
// make the all-day and header rows lines up
- compensateScroll(this.noScrollRowEls, getScrollbarWidths(this.scrollerEl));
+ compensateScroll(this.noScrollRowEls, scrollbarWidths);
// the scrollbar compensation might have changed text flow, which might affect height, so recalculate
// and reapply the desired height to the scroller.
scrollerHeight = this.computeScrollerHeight(totalHeight);
- this.scrollerEl.height(scrollerHeight);
+ this.scroller.setHeight(scrollerHeight);
}
- else { // no scrollbars
- // still, force a height and display the bottom rule (marks the end of day)
- this.scrollerEl.height(scrollerHeight).css('overflow', 'hidden'); // in case
goes outside
+
+ // guarantees the same scrollbar widths
+ this.scroller.lockOverflow(scrollbarWidths);
+
+ // if there's any space below the slats, show the horizontal rule.
+ // this won't cause any new overflow, because lockOverflow already called.
+ if (this.timeGrid.getTotalSlatHeight() < scrollerHeight) {
this.bottomRuleEl.show();
}
}
},
+ // given a desired total height of the view, returns what the height of the scroller should be
+ computeScrollerHeight: function(totalHeight) {
+ return totalHeight -
+ subtractInnerElHeight(this.el, this.scroller.el); // everything that's NOT the scroller
+ },
+
+
+ /* Scroll
+ ------------------------------------------------------------------------------------------------------------------*/
+
+
// Computes the initial pre-configured scroll state prior to allowing the user to change it
computeInitialScroll: function() {
var scrollTime = moment.duration(this.opt('scrollTime'));
@@ -11636,6 +12402,16 @@ var AgendaView = FC.AgendaView = View.extend({
},
+ queryScroll: function() {
+ return this.scroller.getScrollTop();
+ },
+
+
+ setScroll: function(top) {
+ this.scroller.setScrollTop(top);
+ },
+
+
/* Hit Areas
------------------------------------------------------------------------------------------------------------------*/
// forward all hit-related method calls to the grids (dayGrid might not be defined)
diff --git a/library/fullcalendar/fullcalendar.min.css b/library/fullcalendar/fullcalendar.min.css
index 2dc7e9f8a..3a251eb19 100644
--- a/library/fullcalendar/fullcalendar.min.css
+++ b/library/fullcalendar/fullcalendar.min.css
@@ -1,5 +1,5 @@
/*!
- * FullCalendar v2.6.1 Stylesheet
+ * FullCalendar v2.7.3 Stylesheet
* Docs & License: http://fullcalendar.io/
- * (c) 2015 Adam Shaw
- */.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}body .fc{font-size:1em}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1;opacity:.3;filter:alpha(opacity=30)}.fc-bgevent{background:#8fdf82;opacity:.3;filter:alpha(opacity=30)}.fc-nonbusiness{background:#d7d7d7}.fc-icon{display:inline-block;width:1em;height:1em;line-height:1em;font-size:1em;text-align:center;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative;margin:0 -1em}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%;left:3%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%;left:-3%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%;left:-2%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%;left:2%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;white-space:nowrap;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-default{background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.fc-button-group{display:inline-block}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-popover .fc-header .fc-close{cursor:pointer}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc-bg{bottom:0}.fc-bg table{height:100%}.fc table{width:100%;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{overflow-y:scroll;overflow-x:hidden}.fc-scroller>*{position:relative;width:100%;overflow:hidden}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;background-color:#3a87ad;font-weight:400}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-event.fc-draggable,.fc-event[href]{cursor:pointer}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25;filter:alpha(opacity=25)}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:3}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-h-event .fc-resizer{top:-1px;bottom:-1px;left:-1px;right:-1px;width:5px}.fc-ltr .fc-h-event .fc-start-resizer,.fc-ltr .fc-h-event .fc-start-resizer:after,.fc-ltr .fc-h-event .fc-start-resizer:before,.fc-rtl .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-end-resizer:after,.fc-rtl .fc-h-event .fc-end-resizer:before{right:auto;cursor:w-resize}.fc-ltr .fc-h-event .fc-end-resizer,.fc-ltr .fc-h-event .fc-end-resizer:after,.fc-ltr .fc-h-event .fc-end-resizer:before,.fc-rtl .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-start-resizer:after,.fc-rtl .fc-h-event .fc-start-resizer:before{left:auto;cursor:e-resize}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-day-grid-event .fc-resizer{left:-3px;right:-3px;width:7px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-toolbar{text-align:center;margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid{overflow:hidden}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:0 2px}.fc-basic-view td.fc-day-number,.fc-basic-view td.fc-week-number span{padding-top:2px;padding-bottom:2px}.fc-basic-view .fc-week-number{text-align:center}.fc-basic-view .fc-week-number span{display:inline-block;min-width:1.25em}.fc-ltr .fc-basic-view .fc-day-number{text-align:right}.fc-rtl .fc-basic-view .fc-day-number{text-align:left}.fc-day-number.fc-other-month{opacity:.3;filter:alpha(opacity=30)}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-helper-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight-container{position:relative}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event .fc-resizer:after{content:"="}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent}
\ No newline at end of file
+ * (c) 2016 Adam Shaw
+ */.fc-bgevent,.fc-highlight{opacity:.3;filter:alpha(opacity=30)}.fc-icon,body .fc{font-size:1em}.fc-button-group,.fc-icon{display:inline-block}.fc-bg,.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-icon,.fc-unselectable{-khtml-user-select:none;-webkit-touch-callout:none}.fc .fc-axis,.fc button,.fc-time-grid-event .fc-time,.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}.fc th,.fc-basic-view .fc-week-number,.fc-icon,.fc-toolbar{text-align:center}.fc-unthemed .fc-content,.fc-unthemed .fc-divider,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1}.fc-bgevent{background:#8fdf82}.fc-nonbusiness{background:#d7d7d7}.fc-icon{height:1em;line-height:1em;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid;background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.fc-event.fc-draggable,.fc-event[href],.fc-popover .fc-header .fc-close{cursor:pointer}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-bg table,.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc table{width:100%;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{-webkit-overflow-scrolling:touch}.fc-row.fc-rigid,.fc-time-grid-event{overflow:hidden}.fc-scroller>.fc-day-grid,.fc-scroller>.fc-time-grid{position:relative;width:100%}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;background-color:#3a87ad;font-weight:400}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25;filter:alpha(opacity=25)}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:4;display:none}.fc-event.fc-allow-mouse-resize .fc-resizer,.fc-event.fc-selected .fc-resizer{display:block}.fc-event.fc-selected .fc-resizer:before{content:"";position:absolute;z-index:9999;top:50%;left:50%;width:40px;height:40px;margin-left:-20px;margin-top:-20px}.fc-event.fc-selected{z-index:9999!important;box-shadow:0 2px 5px rgba(0,0,0,.2)}.fc-event.fc-selected.fc-dragging{box-shadow:0 2px 7px rgba(0,0,0,.3)}.fc-h-event.fc-selected:before{content:"";position:absolute;z-index:3;top:-10px;bottom:-10px;left:0;right:0}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-ltr .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-end-resizer{cursor:w-resize;left:-1px}.fc-ltr .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-start-resizer{cursor:e-resize;right:-1px}.fc-h-event.fc-allow-mouse-resize .fc-resizer{width:7px;top:-1px;bottom:-1px}.fc-h-event.fc-selected .fc-resizer{border-radius:4px;border-width:1px;width:6px;height:6px;border-style:solid;border-color:inherit;background:#fff;top:50%;margin-top:-4px}.fc-ltr .fc-h-event.fc-selected .fc-start-resizer,.fc-rtl .fc-h-event.fc-selected .fc-end-resizer{margin-left:-4px}.fc-ltr .fc-h-event.fc-selected .fc-end-resizer,.fc-rtl .fc-h-event.fc-selected .fc-start-resizer{margin-right:-4px}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}.fc-day-grid-event.fc-selected:after{content:"";position:absolute;z-index:1;top:-1px;right:-1px;bottom:-1px;left:-1px;background:#000;opacity:.25;filter:alpha(opacity=25)}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer{margin-left:-2px}.fc-ltr .fc-day-grid-event.fc-allow-mouse-resize .fc-end-resizer,.fc-rtl .fc-day-grid-event.fc-allow-mouse-resize .fc-start-resizer{margin-right:-2px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-now-indicator{position:absolute;border:0 solid red}.fc-unselectable{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.fc-toolbar{margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:0 2px}.fc-basic-view td.fc-day-number,.fc-basic-view td.fc-week-number span{padding-top:2px;padding-bottom:2px}.fc-basic-view .fc-week-number span{display:inline-block;min-width:1.25em}.fc-ltr .fc-basic-view .fc-day-number{text-align:right}.fc-rtl .fc-basic-view .fc-day-number{text-align:left}.fc-day-number.fc-other-month{opacity:.3;filter:alpha(opacity=30)}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-content-col{position:relative}.fc-time-grid .fc-content-skeleton{position:absolute;z-index:3;top:0;left:0;right:0}.fc-time-grid .fc-business-container{position:relative;z-index:1}.fc-time-grid .fc-bgevent-container{position:relative;z-index:2}.fc-time-grid .fc-highlight-container{z-index:3;position:relative}.fc-time-grid .fc-event-container{position:relative;z-index:4}.fc-time-grid .fc-now-indicator-line{z-index:5}.fc-time-grid .fc-helper-container{position:relative;z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event.fc-selected{overflow:visible}.fc-time-grid-event.fc-selected .fc-bg{display:none}.fc-time-grid-event .fc-content{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event.fc-allow-mouse-resize .fc-resizer:after{content:"="}.fc-time-grid-event.fc-selected .fc-resizer{border-radius:5px;border-width:1px;width:8px;height:8px;border-style:solid;border-color:inherit;background:#fff;left:50%;margin-left:-5px;bottom:-5px}.fc-time-grid .fc-now-indicator-line{border-top-width:1px;left:0;right:0}.fc-time-grid .fc-now-indicator-arrow{margin-top:-5px}.fc-ltr .fc-time-grid .fc-now-indicator-arrow{left:0;border-width:5px 0 5px 6px;border-top-color:transparent;border-bottom-color:transparent}.fc-rtl .fc-time-grid .fc-now-indicator-arrow{right:0;border-width:5px 6px 5px 0;border-top-color:transparent;border-bottom-color:transparent}
\ No newline at end of file
diff --git a/library/fullcalendar/fullcalendar.min.js b/library/fullcalendar/fullcalendar.min.js
index 5c3cce29f..f27380229 100644
--- a/library/fullcalendar/fullcalendar.min.js
+++ b/library/fullcalendar/fullcalendar.min.js
@@ -1,9 +1,9 @@
/*!
- * FullCalendar v2.6.1
+ * FullCalendar v2.7.3
* Docs & License: http://fullcalendar.io/
- * (c) 2015 Adam Shaw
+ * (c) 2016 Adam Shaw
*/
-!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){function c(a){return Q(a,Ra)}function d(b){var c,d={views:b.views||{}};return a.each(b,function(b,e){"views"!=b&&(a.isPlainObject(e)&&!/(time|duration|interval)$/i.test(b)&&-1==a.inArray(b,Ra)?(c=null,a.each(e,function(a,e){/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(a)?(d.views[a]||(d.views[a]={}),d.views[a][b]=e):(c||(c={}),c[a]=e)}),c&&(d[b]=c)):d[b]=e)}),d}function e(a,b){b.left&&a.css({"border-left-width":1,"margin-left":b.left-1}),b.right&&a.css({"border-right-width":1,"margin-right":b.right-1})}function f(a){a.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function g(){a("body").addClass("fc-not-allowed")}function h(){a("body").removeClass("fc-not-allowed")}function i(b,c,d){var e=Math.floor(c/b.length),f=Math.floor(c-e*(b.length-1)),g=[],h=[],i=[],k=0;j(b),b.each(function(c,d){var j=c===b.length-1?f:e,l=a(d).outerHeight(!0);j>l?(g.push(d),h.push(l),i.push(a(d).height())):k+=l}),d&&(c-=k,e=Math.floor(c/g.length),f=Math.floor(c-e*(g.length-1))),a(g).each(function(b,c){var d=b===g.length-1?f:e,j=h[b],k=i[b],l=d-(j-k);d>j&&a(c).height(l)})}function j(a){a.height("")}function k(b){var c=0;return b.find("> span").each(function(b,d){var e=a(d).outerWidth();e>c&&(c=e)}),c++,b.width(c),c}function l(a,b){return a.height(b).addClass("fc-scroller"),a[0].scrollHeight-1>a[0].clientHeight?!0:(m(a),!1)}function m(a){a.height("").removeClass("fc-scroller")}function n(b){var c=b.css("position"),d=b.parents().filter(function(){var b=a(this);return/(auto|scroll)/.test(b.css("overflow")+b.css("overflow-y")+b.css("overflow-x"))}).eq(0);return"fixed"!==c&&d.length?d:a(b[0].ownerDocument||document)}function o(a){var b=a.offset();return{left:b.left,right:b.left+a.outerWidth(),top:b.top,bottom:b.top+a.outerHeight()}}function p(a){var b=a.offset(),c=r(a),d=b.left+u(a,"border-left-width")+c.left,e=b.top+u(a,"border-top-width")+c.top;return{left:d,right:d+a[0].clientWidth,top:e,bottom:e+a[0].clientHeight}}function q(a){var b=a.offset(),c=b.left+u(a,"border-left-width")+u(a,"padding-left"),d=b.top+u(a,"border-top-width")+u(a,"padding-top");return{left:c,right:c+a.width(),top:d,bottom:d+a.height()}}function r(a){var b=a.innerWidth()-a[0].clientWidth,c={left:0,right:0,top:0,bottom:a.innerHeight()-a[0].clientHeight};return s()&&"rtl"==a.css("direction")?c.left=b:c.right=b,c}function s(){return null===Sa&&(Sa=t()),Sa}function t(){var b=a("").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),c=b.children(),d=c.offset().left>b.offset().left;return b.remove(),d}function u(a,b){return parseFloat(a.css(b))||0}function v(a){return 1==a.which&&!a.ctrlKey}function w(a,b){var c={left:Math.max(a.left,b.left),right:Math.min(a.right,b.right),top:Math.max(a.top,b.top),bottom:Math.min(a.bottom,b.bottom)};return c.lefti&&j>g?(g>=i?(c=g.clone(),e=!0):(c=i.clone(),e=!1),j>=h?(d=h.clone(),f=!0):(d=j.clone(),f=!1),{start:c,end:d,isStart:e,isEnd:f}):void 0}function F(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days"),ms:a.time()-c.time()})}function G(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days")})}function H(a,c,d){return b.duration(Math.round(a.diff(c,d,!0)),d)}function I(a,b){var c,d,e;for(c=0;c=1&&ba(e)));c++);return d}function J(a,c,d){return null!=d?d.diff(c,a,!0):b.isDuration(c)?c.as(a):c.end.diff(c.start,a,!0)}function K(a,b,c){var d;return N(c)?(b-a)/c:(d=c.asMonths(),Math.abs(d)>=1&&ba(d)?b.diff(a,"months",!0)/d:b.diff(a,"days",!0)/c.asDays())}function L(a,b){var c,d;return N(a)||N(b)?a/b:(c=a.asMonths(),d=b.asMonths(),Math.abs(c)>=1&&ba(c)&&Math.abs(d)>=1&&ba(d)?c/d:a.asDays()/b.asDays())}function M(a,c){var d;return N(a)?b.duration(a*c):(d=a.asMonths(),Math.abs(d)>=1&&ba(d)?b.duration({months:d*c}):b.duration({days:a.asDays()*c}))}function N(a){return Boolean(a.hours()||a.minutes()||a.seconds()||a.milliseconds())}function O(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function P(a){return/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(a)}function Q(a,b){var c,d,e,f,g,h,i={};if(b)for(c=0;c=0;f--)if(g=a[f][d],"object"==typeof g)e.unshift(g);else if(void 0!==g){i[d]=g;break}e.length&&(i[d]=Q(e))}for(c=a.length-1;c>=0;c--){h=a[c];for(d in h)d in i||(i[d]=h[d])}return i}function R(a){var b=function(){};return b.prototype=a,new b}function S(a,b){for(var c in a)U(a,c)&&(b[c]=a[c])}function T(a,b){var c,d,e=["constructor","toString","valueOf"];for(c=0;c/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"
")}function Z(a){return a.replace(/&.*?;/g,"")}function $(b){var c=[];return a.each(b,function(a,b){null!=b&&c.push(a+":"+b)}),c.join(";")}function _(a){return a.charAt(0).toUpperCase()+a.slice(1)}function aa(a,b){return a-b}function ba(a){return a%1===0}function ca(a,b){var c=a[b];return function(){return c.apply(a,arguments)}}function da(a,b){var c,d,e,f,g=function(){var h=+new Date-f;b>h&&h>0?c=setTimeout(g,b-h):(c=null,a.apply(e,d),c||(e=d=null))};return function(){e=this,d=arguments,f=+new Date,c||(c=setTimeout(g,b))}}function ea(c,d,e){var f,g,h,i,j=c[0],k=1==c.length&&"string"==typeof j;return b.isMoment(j)?(i=b.apply(null,c),ga(j,i)):O(j)||void 0===j?i=b.apply(null,c):(f=!1,g=!1,k?Za.test(j)?(j+="-01",c=[j],f=!0,g=!0):(h=$a.exec(j))&&(f=!h[5],g=!0):a.isArray(j)&&(g=!0),i=d||f?b.utc.apply(b,c):b.apply(null,c),f?(i._ambigTime=!0,i._ambigZone=!0):e&&(g?i._ambigZone=!0:k&&(i.utcOffset?i.utcOffset(j):i.zone(j)))),i._fullCalendar=!0,i}function fa(a,c){var d,e,f=!1,g=!1,h=a.length,i=[];for(d=0;h>d;d++)e=a[d],b.isMoment(e)||(e=Pa.moment.parseZone(e)),f=f||e._ambigTime,g=g||e._ambigZone,i.push(e);for(d=0;h>d;d++)e=i[d],c||!f||e._ambigTime?g&&!e._ambigZone&&(i[d]=e.clone().stripZone()):i[d]=e.clone().stripTime();return i}function ga(a,b){a._ambigTime?b._ambigTime=!0:b._ambigTime&&(b._ambigTime=!1),a._ambigZone?b._ambigZone=!0:b._ambigZone&&(b._ambigZone=!1)}function ha(a,b){a.year(b[0]||0).month(b[1]||0).date(b[2]||0).hours(b[3]||0).minutes(b[4]||0).seconds(b[5]||0).milliseconds(b[6]||0)}function ia(a,b){return ab.format.call(a,b)}function ja(a,b){return ka(a,pa(b))}function ka(a,b){var c,d="";for(c=0;cg&&(f=oa(a,b,j,k,c[h]),f!==!1);h--)m=f+m;for(i=g;h>=i;i++)n+=la(a,c[i]),o+=la(b,c[i]);return(n||o)&&(p=e?o+d+n:n+d+o),l+p+m}function oa(a,b,c,d,e){var f,g;return"string"==typeof e?e:(f=e.token)&&(g=cb[f.charAt(0)],g&&c.isSame(d,g))?ia(a,f):!1}function pa(a){return a in db?db[a]:db[a]=qa(a)}function qa(a){for(var b,c=[],d=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;b=d.exec(a);)b[1]?c.push(b[1]):b[2]?c.push({maybe:qa(b[2])}):b[3]?c.push({token:b[3]}):b[5]&&c.push(b[5]);return c}function ra(){}function sa(a,b){var c;return U(b,"constructor")&&(c=b.constructor),"function"!=typeof c&&(c=b.constructor=function(){a.apply(this,arguments)}),c.prototype=R(a.prototype),S(b,c.prototype),T(b,c.prototype),S(a,c),c}function ta(a,b){S(b.prototype||b,a.prototype)}function ua(a,b){return a||b?a&&b?a.component===b.component&&va(a,b)&&va(b,a):!1:!0}function va(a,b){for(var c in a)if(!/^(component|left|right|top|bottom)$/.test(c)&&a[c]!==b[c])return!1;return!0}function wa(a){var b=ya(a);return"background"===b||"inverse-background"===b}function xa(a){return"inverse-background"===ya(a)}function ya(a){return X((a.source||{}).rendering,a.rendering)}function za(a){var b,c,d={};for(b=0;b=a.leftCol)return!0;return!1}function Da(a,b){return a.leftCol-b.leftCol}function Ea(a){var b,c,d,e=[];for(b=0;bb.top&&a.top").prependTo(c),S=N.header=new Ma(N,O),T=S.render(),T&&c.prepend(T),i(O.defaultView),O.handleWindowResize&&(Y=da(m,O.windowResizeDelay),a(window).resize(Y))}function g(){W&&W.removeElement(),S.removeElement(),U.remove(),c.removeClass("fc fc-ltr fc-rtl fc-unthemed ui-widget"),Y&&a(window).unbind("resize",Y)}function h(){return c.is(":visible")}function i(b){ca++,W&&b&&W.type!==b&&(S.deactivateButton(W.type),H(),W.removeElement(),W=N.view=null),!W&&b&&(W=N.view=ba[b]||(ba[b]=N.instantiateView(b)),W.setElement(a("").appendTo(U)),S.activateButton(b)),W&&(Z=W.massageCurrentDate(Z),W.displaying&&Z.isWithin(W.intervalStart,W.intervalEnd)||h()&&(W.display(Z),I(),u(),v(),q())),I(),ca--}function j(a){return h()?(a&&l(),ca++,W.updateSize(!0),ca--,!0):void 0}function k(){h()&&l()}function l(){X="number"==typeof O.contentHeight?O.contentHeight:"number"==typeof O.height?O.height-(T?T.outerHeight(!0):0):Math.round(U.width()/Math.max(O.aspectRatio,.5))}function m(a){!ca&&a.target===window&&W.start&&j(!0)&&W.trigger("windowResize",aa)}function n(){p(),r()}function o(){h()&&(H(),W.displayEvents(ea),I())}function p(){H(),W.clearEvents(),I()}function q(){!O.lazyFetching||$(W.start,W.end)?r():o()}function r(){_(W.start,W.end)}function s(a){ea=a,o()}function t(){o()}function u(){S.updateTitle(W.title)}function v(){var a=N.getNow();a.isWithin(W.intervalStart,W.intervalEnd)?S.disableButton("today"):S.enableButton("today")}function w(a,b){W.select(N.buildSelectSpan.apply(N,arguments))}function x(){W&&W.unselect()}function y(){Z=W.computePrevDate(Z),i()}function z(){Z=W.computeNextDate(Z),i()}function A(){Z.add(-1,"years"),i()}function B(){Z.add(1,"years"),i()}function C(){Z=N.getNow(),i()}function D(a){Z=N.moment(a).stripZone(),i()}function E(a){Z.add(b.duration(a)),i()}function F(a,b){var c;b=b||"day",c=N.getViewSpec(b)||N.getUnitViewSpec(b),Z=a.clone(),i(c?c.type:null)}function G(){return N.applyTimezone(Z)}function H(){U.css({width:"100%",height:U.height(),overflow:"hidden"})}function I(){U.css({width:"",height:"",overflow:""})}function J(){return N}function K(){return W}function L(a,b){return void 0===b?O[a]:void(("height"==a||"contentHeight"==a||"aspectRatio"==a)&&(O[a]=b,j(!0)))}function M(a,b){var c=Array.prototype.slice.call(arguments,2);return b=b||aa,this.triggerWith(a,b,c),O[a]?O[a].apply(b,c):void 0}var N=this;N.initOptions(d||{});var O=this.options;N.render=e,N.destroy=g,N.refetchEvents=n,N.reportEvents=s,N.reportEventChange=t,N.rerenderEvents=o,N.changeView=i,N.select=w,N.unselect=x,N.prev=y,N.next=z,N.prevYear=A,N.nextYear=B,N.today=C,N.gotoDate=D,N.incrementDate=E,N.zoomTo=F,N.getDate=G,N.getCalendar=J,N.getView=K,N.option=L,N.trigger=M;var P=R(La(O.lang));if(O.monthNames&&(P._months=O.monthNames),O.monthNamesShort&&(P._monthsShort=O.monthNamesShort),O.dayNames&&(P._weekdays=O.dayNames),O.dayNamesShort&&(P._weekdaysShort=O.dayNamesShort),null!=O.firstDay){var Q=R(P._week);Q.dow=O.firstDay,P._week=Q}P._fullCalendar_weekCalc=function(a){return"function"==typeof a?a:"local"===a?a:"iso"===a||"ISO"===a?"ISO":void 0}(O.weekNumberCalculation),N.defaultAllDayEventDuration=b.duration(O.defaultAllDayEventDuration),N.defaultTimedEventDuration=b.duration(O.defaultTimedEventDuration),N.moment=function(){var a;return"local"===O.timezone?(a=Pa.moment.apply(null,arguments),a.hasTime()&&a.local()):a="UTC"===O.timezone?Pa.moment.utc.apply(null,arguments):Pa.moment.parseZone.apply(null,arguments),"_locale"in a?a._locale=P:a._lang=P,a},N.getIsAmbigTimezone=function(){return"local"!==O.timezone&&"UTC"!==O.timezone},N.applyTimezone=function(a){if(!a.hasTime())return a.clone();var b,c=N.moment(a.toArray()),d=a.time()-c.time();return d&&(b=c.clone().add(d),a.time()-b.time()===0&&(c=b)),c},N.getNow=function(){var a=O.now;return"function"==typeof a&&(a=a()),N.moment(a).stripZone()},N.getEventEnd=function(a){return a.end?a.end.clone():N.getDefaultEventEnd(a.allDay,a.start)},N.getDefaultEventEnd=function(a,b){var c=b.clone();return a?c.stripTime().add(N.defaultAllDayEventDuration):c.add(N.defaultTimedEventDuration),N.getIsAmbigTimezone()&&c.stripZone(),c},N.humanizeDuration=function(a){return(a.locale||a.lang).call(a,O.lang).humanize()},Na.call(N,O);var S,T,U,V,W,X,Y,Z,$=N.isFetchNeeded,_=N.fetchEvents,aa=c[0],ba={},ca=0,ea=[];Z=null!=O.defaultDate?N.moment(O.defaultDate).stripZone():N.getNow(),N.getSuggestedViewHeight=function(){return void 0===X&&k(),X},N.isHeightAuto=function(){return"auto"===O.contentHeight||"auto"===O.height},N.freezeContentHeight=H,N.unfreezeContentHeight=I,N.initialize()}function Ka(b){a.each(tb,function(a,c){null==b[a]&&(b[a]=c(b))})}function La(a){var c=b.localeData||b.langData;return c.call(b,a)||c.call(b,"en")}function Ma(b,c){function d(){var b=c.header;return n=c.theme?"ui":"fc",b?o=a("").append(f("left")).append(f("right")).append(f("center")).append(''):void 0}function e(){o.remove(),o=a()}function f(d){var e=a(''),f=c.header[d];return f&&a.each(f.split(" "),function(d){var f,g=a(),h=!0;a.each(this.split(","),function(d,e){var f,i,j,k,l,m,o,q,r,s;"title"==e?(g=g.add(a("
")),h=!1):((f=(b.options.customButtons||{})[e])?(j=function(a){f.click&&f.click.call(s[0],a)},k="",l=f.text):(i=b.getViewSpec(e))?(j=function(){b.changeView(e)},p.push(e),k=i.buttonTextOverride,l=i.buttonTextDefault):b[e]&&(j=function(){b[e]()},k=(b.overrides.buttonText||{})[e],l=c.buttonText[e]),j&&(m=f?f.themeIcon:c.themeButtonIcons[e],o=f?f.icon:c.buttonIcons[e],q=k?Y(k):m&&c.theme?"":o&&!c.theme?"":Y(l),r=["fc-"+e+"-button",n+"-button",n+"-state-default"],s=a('").click(function(a){s.hasClass(n+"-state-disabled")||(j(a),(s.hasClass(n+"-state-active")||s.hasClass(n+"-state-disabled"))&&s.removeClass(n+"-state-hover"))}).mousedown(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-down")}).mouseup(function(){s.removeClass(n+"-state-down")}).hover(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-hover")},function(){s.removeClass(n+"-state-hover").removeClass(n+"-state-down")}),g=g.add(s)))}),h&&g.first().addClass(n+"-corner-left").end().last().addClass(n+"-corner-right").end(),g.length>1?(f=a(""),h&&f.addClass("fc-button-group"),f.append(g),e.append(f)):e.append(g)}),e}function g(a){o.find("h2").text(a)}function h(a){o.find(".fc-"+a+"-button").addClass(n+"-state-active")}function i(a){o.find(".fc-"+a+"-button").removeClass(n+"-state-active")}function j(a){o.find(".fc-"+a+"-button").attr("disabled","disabled").addClass(n+"-state-disabled")}function k(a){o.find(".fc-"+a+"-button").removeAttr("disabled").removeClass(n+"-state-disabled")}function l(){return p}var m=this;m.render=d,m.removeElement=e,m.updateTitle=g,m.activateButton=h,m.deactivateButton=i,m.disableButton=j,m.enableButton=k,m.getViewsWithButtons=l;var n,o=a(),p=[]}function Na(c){function d(a,b){return!L||L>a||b>M}function e(a,b){L=a,M=b,T=[];var c=++R,d=Q.length;S=d;for(var e=0;d>e;e++)f(Q[e],c)}function f(b,c){g(b,function(d){var e,f,g,h=a.isArray(b.events);if(c==R){if(d)for(e=0;e=c&&b.end<=d}function J(a,b){var c=a.start.clone().stripZone(),d=K.getEventEnd(a).stripZone();return b.startc}var K=this;K.isFetchNeeded=d,K.fetchEvents=e,K.addEventSource=h,K.removeEventSource=j,K.updateEvent=m,K.renderEvent=p,K.removeEvents=q,K.clientEvents=r,K.mutateEvent=x,K.normalizeEventDates=u,K.normalizeEventTimes=v;var L,M,N=K.reportEvents,O={events:[]},Q=[O],R=0,S=0,T=[];a.each((c.events?[c.events]:[]).concat(c.eventSources||[]),function(a,b){var c=i(b);c&&Q.push(c)}),K.getBusinessHoursEvents=z,K.isEventSpanAllowed=A,K.isExternalSpanAllowed=B,K.isSelectionSpanAllowed=C,K.getEventCache=function(){return T}}function Oa(a){a._allDay=a.allDay,a._start=a.start.clone(),a._end=a.end?a.end.clone():null}var Pa=a.fullCalendar={version:"2.6.1",internalApiVersion:3},Qa=Pa.views={};a.fn.fullCalendar=function(b){var c=Array.prototype.slice.call(arguments,1),d=this;return this.each(function(e,f){var g,h=a(f),i=h.data("fullCalendar");"string"==typeof b?i&&a.isFunction(i[b])&&(g=i[b].apply(i,c),e||(d=g),"destroy"===b&&h.removeData("fullCalendar")):i||(i=new pb(h,b),h.data("fullCalendar",i),i.render())}),d};var Ra=["header","buttonText","buttonIcons","themeButtonIcons"];Pa.intersectRanges=E,Pa.applyAll=W,Pa.debounce=da,Pa.isInt=ba,Pa.htmlEscape=Y,Pa.cssToStr=$,Pa.proxy=ca,Pa.capitaliseFirstLetter=_,Pa.getOuterRect=o,Pa.getClientRect=p,Pa.getContentRect=q,Pa.getScrollbarWidths=r;var Sa=null;Pa.intersectRects=w,Pa.parseFieldSpecs=A,Pa.compareByFieldSpecs=B,Pa.compareByFieldSpec=C,Pa.flexibleCompare=D,Pa.computeIntervalUnit=I,Pa.divideRangeByDuration=K,Pa.divideDurationByDuration=L,Pa.multiplyDuration=M,Pa.durationHasTime=N;var Ta=["sun","mon","tue","wed","thu","fri","sat"],Ua=["year","month","week","day","hour","minute","second","millisecond"];Pa.log=function(){var a=window.console;return a&&a.log?a.log.apply(a,arguments):void 0},Pa.warn=function(){var a=window.console;return a&&a.warn?a.warn.apply(a,arguments):Pa.log.apply(Pa,arguments)};var Va,Wa,Xa,Ya={}.hasOwnProperty,Za=/^\s*\d{4}-\d\d$/,$a=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,_a=b.fn,ab=a.extend({},_a);Pa.moment=function(){return ea(arguments)},Pa.moment.utc=function(){var a=ea(arguments,!0);return a.hasTime()&&a.utc(),a},Pa.moment.parseZone=function(){return ea(arguments,!0,!0)},_a.clone=function(){var a=ab.clone.apply(this,arguments);return ga(this,a),this._fullCalendar&&(a._fullCalendar=!0),a},_a.week=_a.weeks=function(a){var b=(this._locale||this._lang)._fullCalendar_weekCalc;return null==a&&"function"==typeof b?b(this):"ISO"===b?ab.isoWeek.apply(this,arguments):ab.week.apply(this,arguments)},_a.time=function(a){if(!this._fullCalendar)return ab.time.apply(this,arguments);if(null==a)return b.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,b.isDuration(a)||b.isMoment(a)||(a=b.duration(a));var c=0;return b.isDuration(a)&&(c=24*Math.floor(a.asDays())),this.hours(c+a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds())},_a.stripTime=function(){var a;return this._ambigTime||(a=this.toArray(),this.utc(),Wa(this,a.slice(0,3)),this._ambigTime=!0,this._ambigZone=!0),this},_a.hasTime=function(){return!this._ambigTime},_a.stripZone=function(){var a,b;return this._ambigZone||(a=this.toArray(),b=this._ambigTime,this.utc(),Wa(this,a),this._ambigTime=b||!1,this._ambigZone=!0),this},_a.hasZone=function(){return!this._ambigZone},_a.local=function(){var a=this.toArray(),b=this._ambigZone;return ab.local.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,b&&Xa(this,a),this},_a.utc=function(){return ab.utc.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,this},a.each(["zone","utcOffset"],function(a,b){ab[b]&&(_a[b]=function(a){return null!=a&&(this._ambigTime=!1,this._ambigZone=!1),ab[b].apply(this,arguments)})}),_a.format=function(){return this._fullCalendar&&arguments[0]?ja(this,arguments[0]):this._ambigTime?ia(this,"YYYY-MM-DD"):this._ambigZone?ia(this,"YYYY-MM-DD[T]HH:mm:ss"):ab.format.apply(this,arguments)},_a.toISOString=function(){return this._ambigTime?ia(this,"YYYY-MM-DD"):this._ambigZone?ia(this,"YYYY-MM-DD[T]HH:mm:ss"):ab.toISOString.apply(this,arguments)},_a.isWithin=function(a,b){var c=fa([this,a,b]);return c[0]>=c[1]&&c[0]a;a++)b=arguments[a],c-1>a&&ta(this,b);return sa(this,b||{})},ra.mixin=function(a){ta(this,a)};var eb=Pa.Emitter=ra.extend({callbackHash:null,on:function(a,b){return this.getCallbacks(a).add(b),this},off:function(a,b){return this.getCallbacks(a).remove(b),this},trigger:function(a){var b=Array.prototype.slice.call(arguments,1);return this.triggerWith(a,this,b),this},triggerWith:function(a,b,c){var d=this.getCallbacks(a);return d.fireWith(b,c),this},getCallbacks:function(b){var c;return this.callbackHash||(this.callbackHash={}),c=this.callbackHash[b],c||(c=this.callbackHash[b]=a.Callbacks()),c}}),fb=ra.extend({isHidden:!0,options:null,el:null,documentMousedownProxy:null,margin:10,constructor:function(a){this.options=a||{}},show:function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},hide:function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},render:function(){var b=this,c=this.options;this.el=a('').addClass(c.className||"").css({top:0,left:0}).append(c.content).appendTo(c.parentEl),this.el.on("click",".fc-close",function(){b.hide()}),c.autoHide&&a(document).on("mousedown",this.documentMousedownProxy=ca(this,"documentMousedown"))},documentMousedown:function(b){this.el&&!a(b.target).closest(this.el).length&&this.hide()},removeElement:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),a(document).off("mousedown",this.documentMousedownProxy)},position:function(){var b,c,d,e,f,g=this.options,h=this.el.offsetParent().offset(),i=this.el.outerWidth(),j=this.el.outerHeight(),k=a(window),l=n(this.el);e=g.top||0,f=void 0!==g.left?g.left:void 0!==g.right?g.right-i:0,l.is(window)||l.is(document)?(l=k,b=0,c=0):(d=l.offset(),b=d.top,c=d.left),b+=k.scrollTop(),c+=k.scrollLeft(),g.viewportConstrain!==!1&&(e=Math.min(e,b+l.outerHeight()-j-this.margin),e=Math.max(e,b+this.margin),f=Math.min(f,c+l.outerWidth()-i-this.margin),
-f=Math.max(f,c+this.margin)),this.el.css({top:e-h.top,left:f-h.left})},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1))}}),gb=Pa.CoordCache=ra.extend({els:null,forcedOffsetParentEl:null,origin:null,boundingRect:null,isHorizontal:!1,isVertical:!1,lefts:null,rights:null,tops:null,bottoms:null,constructor:function(b){this.els=a(b.els),this.isHorizontal=b.isHorizontal,this.isVertical=b.isVertical,this.forcedOffsetParentEl=b.offsetParent?a(b.offsetParent):null},build:function(){var a=this.forcedOffsetParentEl||this.els.eq(0).offsetParent();this.origin=a.offset(),this.boundingRect=this.queryBoundingRect(),this.isHorizontal&&this.buildElHorizontals(),this.isVertical&&this.buildElVerticals()},clear:function(){this.origin=null,this.boundingRect=null,this.lefts=null,this.rights=null,this.tops=null,this.bottoms=null},ensureBuilt:function(){this.origin||this.build()},queryBoundingRect:function(){var a=n(this.els.eq(0));return a.is(document)?void 0:p(a)},buildElHorizontals:function(){var b=[],c=[];this.els.each(function(d,e){var f=a(e),g=f.offset().left,h=f.outerWidth();b.push(g),c.push(g+h)}),this.lefts=b,this.rights=c},buildElVerticals:function(){var b=[],c=[];this.els.each(function(d,e){var f=a(e),g=f.offset().top,h=f.outerHeight();b.push(g),c.push(g+h)}),this.tops=b,this.bottoms=c},getHorizontalIndex:function(a){this.ensureBuilt();var b,c=this.boundingRect,d=this.lefts,e=this.rights,f=d.length;if(!c||a>=c.left&&ab;b++)if(a>=d[b]&&a=c.top&&ab;b++)if(a>=d[b]&&a=b*b&&this.startDrag(a)),this.isDragging&&this.drag(d,e,a)},startDrag:function(a){this.isListening||this.startListening(),this.isDragging||(this.isDragging=!0,this.dragStart(a))},dragStart:function(a){var b=this.subjectEl;this.trigger("dragStart",a),(this.subjectHref=b?b.attr("href"):null)&&b.removeAttr("href")},drag:function(a,b,c){this.trigger("drag",a,b,c),this.updateScroll(c)},mouseup:function(a){this.stopListening(a)},stopDrag:function(a){this.isDragging&&(this.stopScrolling(),this.dragStop(a),this.isDragging=!1)},dragStop:function(a){var b=this;this.trigger("dragStop",a),setTimeout(function(){b.subjectHref&&b.subjectEl.attr("href",b.subjectHref)},0)},stopListening:function(b){this.stopDrag(b),this.isListening&&(this.scrollEl&&(this.scrollEl.off("scroll",this.scrollHandlerProxy),this.scrollHandlerProxy=null),a(document).off("mousemove",this.mousemoveProxy).off("mouseup",this.mouseupProxy).off("selectstart",this.preventDefault),this.mousemoveProxy=null,this.mouseupProxy=null,this.isListening=!1,this.listenStop(b))},listenStop:function(a){this.trigger("listenStop",a)},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1))},preventDefault:function(a){a.preventDefault()},computeScrollBounds:function(){var a=this.scrollEl;this.scrollBounds=a?o(a):null},updateScroll:function(a){var b,c,d,e,f=this.scrollSensitivity,g=this.scrollBounds,h=0,i=0;g&&(b=(f-(a.pageY-g.top))/f,c=(f-(g.bottom-a.pageY))/f,d=(f-(a.pageX-g.left))/f,e=(f-(g.right-a.pageX))/f,b>=0&&1>=b?h=b*this.scrollSpeed*-1:c>=0&&1>=c&&(h=c*this.scrollSpeed),d>=0&&1>=d?i=d*this.scrollSpeed*-1:e>=0&&1>=e&&(i=e*this.scrollSpeed)),this.setScrollVel(h,i)},setScrollVel:function(a,b){this.scrollTopVel=a,this.scrollLeftVel=b,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(ca(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var a=this.scrollEl;this.scrollTopVel<0?a.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&a.scrollTop()+a[0].clientHeight>=a[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?a.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&a.scrollLeft()+a[0].clientWidth>=a[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var a=this.scrollEl,b=this.scrollIntervalMs/1e3;this.scrollTopVel&&a.scrollTop(a.scrollTop()+this.scrollTopVel*b),this.scrollLeftVel&&a.scrollLeft(a.scrollLeft()+this.scrollLeftVel*b),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.stopScrolling()},stopScrolling:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.scrollStop())},scrollHandler:function(){this.scrollIntervalId||this.scrollStop()},scrollStop:function(){}}),ib=hb.extend({component:null,origHit:null,hit:null,coordAdjust:null,constructor:function(a,b){hb.call(this,b),this.component=a},listenStart:function(a){var b,c,d,e=this.subjectEl;hb.prototype.listenStart.apply(this,arguments),this.computeCoords(),a?(c={left:a.pageX,top:a.pageY},d=c,e&&(b=o(e),d=x(d,b)),this.origHit=this.queryHit(d.left,d.top),e&&this.options.subjectCenter&&(this.origHit&&(b=w(this.origHit,b)||b),d=y(b)),this.coordAdjust=z(d,c)):(this.origHit=null,this.coordAdjust=null)},computeCoords:function(){this.component.prepareHits(),this.computeScrollBounds()},dragStart:function(a){var b;hb.prototype.dragStart.apply(this,arguments),b=this.queryHit(a.pageX,a.pageY),b&&this.hitOver(b)},drag:function(a,b,c){var d;hb.prototype.drag.apply(this,arguments),d=this.queryHit(c.pageX,c.pageY),ua(d,this.hit)||(this.hit&&this.hitOut(),d&&this.hitOver(d))},dragStop:function(){this.hitDone(),hb.prototype.dragStop.apply(this,arguments)},hitOver:function(a){var b=ua(a,this.origHit);this.hit=a,this.trigger("hitOver",this.hit,b,this.origHit)},hitOut:function(){this.hit&&(this.trigger("hitOut",this.hit),this.hitDone(),this.hit=null)},hitDone:function(){this.hit&&this.trigger("hitDone",this.hit)},listenStop:function(){hb.prototype.listenStop.apply(this,arguments),this.origHit=null,this.hit=null,this.component.releaseHits()},scrollStop:function(){hb.prototype.scrollStop.apply(this,arguments),this.computeCoords()},queryHit:function(a,b){return this.coordAdjust&&(a+=this.coordAdjust.left,b+=this.coordAdjust.top),this.component.queryHit(a,b)}}),jb=ra.extend({options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,mouseY0:null,mouseX0:null,topDelta:null,leftDelta:null,mousemoveProxy:null,isFollowing:!1,isHidden:!1,isAnimating:!1,constructor:function(b,c){this.options=c=c||{},this.sourceEl=b,this.parentEl=c.parentEl?a(c.parentEl):b.parent()},start:function(b){this.isFollowing||(this.isFollowing=!0,this.mouseY0=b.pageY,this.mouseX0=b.pageX,this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),a(document).on("mousemove",this.mousemoveProxy=ca(this,"mousemove")))},stop:function(b,c){function d(){this.isAnimating=!1,e.removeElement(),this.top0=this.left0=null,c&&c()}var e=this,f=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,a(document).off("mousemove",this.mousemoveProxy),b&&f&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:f,complete:d})):d())},getEl:function(){var a=this.el;return a||(this.sourceEl.width(),a=this.el=this.sourceEl.clone().css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}).appendTo(this.parentEl)),a},removeElement:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var a,b;this.getEl(),null===this.top0&&(this.sourceEl.width(),a=this.sourceEl.offset(),b=this.el.offsetParent().offset(),this.top0=a.top-b.top,this.left0=a.left-b.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},mousemove:function(a){this.topDelta=a.pageY-this.mouseY0,this.leftDelta=a.pageX-this.mouseX0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}}),kb=Pa.Grid=ra.extend({view:null,isRTL:null,start:null,end:null,el:null,elsByFill:null,externalDragStartProxy:null,eventTimeFormat:null,displayEventTime:null,displayEventEnd:null,minResizeDuration:null,largeUnit:null,constructor:function(a){this.view=a,this.isRTL=a.opt("isRTL"),this.elsByFill={},this.externalDragStartProxy=ca(this,"externalDragStart")},computeEventTimeFormat:function(){return this.view.opt("smallTimeFormat")},computeDisplayEventTime:function(){return!0},computeDisplayEventEnd:function(){return!0},setRange:function(a){this.start=a.start.clone(),this.end=a.end.clone(),this.rangeUpdated(),this.processRangeOptions()},rangeUpdated:function(){},processRangeOptions:function(){var a,b,c=this.view;this.eventTimeFormat=c.opt("eventTimeFormat")||c.opt("timeFormat")||this.computeEventTimeFormat(),a=c.opt("displayEventTime"),null==a&&(a=this.computeDisplayEventTime()),b=c.opt("displayEventEnd"),null==b&&(b=this.computeDisplayEventEnd()),this.displayEventTime=a,this.displayEventEnd=b},spanToSegs:function(a){},diffDates:function(a,b){return this.largeUnit?H(a,b,this.largeUnit):F(a,b)},prepareHits:function(){},releaseHits:function(){},queryHit:function(a,b){},getHitSpan:function(a){},getHitEl:function(a){},setElement:function(b){var c=this;this.el=b,b.on("mousedown",function(b){a(b.target).is(".fc-event-container *, .fc-more")||a(b.target).closest(".fc-popover").length||c.dayMousedown(b)}),this.bindSegHandlers(),this.bindGlobalHandlers()},removeElement:function(){this.unbindGlobalHandlers(),this.el.remove()},renderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},bindGlobalHandlers:function(){a(document).on("dragstart sortstart",this.externalDragStartProxy)},unbindGlobalHandlers:function(){a(document).off("dragstart sortstart",this.externalDragStartProxy)},dayMousedown:function(a){var b,c,d=this,e=this.view,f=e.opt("selectable"),i=new ib(this,{scroll:e.opt("dragScroll"),dragStart:function(){e.unselect()},hitOver:function(a,e,h){h&&(b=e?a:null,f&&(c=d.computeSelection(d.getHitSpan(h),d.getHitSpan(a)),c?d.renderSelection(c):c===!1&&g()))},hitOut:function(){b=null,c=null,d.unrenderSelection(),h()},listenStop:function(a){b&&e.triggerDayClick(d.getHitSpan(b),d.getHitEl(b),a),c&&e.reportSelection(c,a),h()}});i.mousedown(a)},renderEventLocationHelper:function(a,b){var c=this.fabricateHelperEvent(a,b);this.renderHelper(c,b)},fabricateHelperEvent:function(a,b){var c=b?R(b.event):{};return c.start=a.start.clone(),c.end=a.end?a.end.clone():null,c.allDay=null,this.view.calendar.normalizeEventDates(c),c.className=(c.className||[]).concat("fc-helper"),b||(c.editable=!1),c},renderHelper:function(a,b){},unrenderHelper:function(){},renderSelection:function(a){this.renderHighlight(a)},unrenderSelection:function(){this.unrenderHighlight()},computeSelection:function(a,b){var c=this.computeSelectionSpan(a,b);return c&&!this.view.calendar.isSelectionSpanAllowed(c)?!1:c},computeSelectionSpan:function(a,b){var c=[a.start,a.end,b.start,b.end];return c.sort(aa),{start:c[0].clone(),end:c[3].clone()}},renderHighlight:function(a){this.renderFill("highlight",this.spanToSegs(a))},unrenderHighlight:function(){this.unrenderFill("highlight")},highlightSegClasses:function(){return["fc-highlight"]},renderBusinessHours:function(){},unrenderBusinessHours:function(){},getNowIndicatorUnit:function(){},renderNowIndicator:function(a){},unrenderNowIndicator:function(){},renderFill:function(a,b){},unrenderFill:function(a){var b=this.elsByFill[a];b&&(b.remove(),delete this.elsByFill[a])},renderFillSegEls:function(b,c){var d,e=this,f=this[b+"SegEl"],g="",h=[];if(c.length){for(d=0;d"},getDayClasses:function(a){var b=this.view,c=b.calendar.getNow(),d=["fc-"+Ta[a.day()]];return 1==b.intervalDuration.as("months")&&a.month()!=b.intervalStart.month()&&d.push("fc-other-month"),a.isSame(c,"day")?d.push("fc-today",b.highlightStateClass):c>a?d.push("fc-past"):d.push("fc-future"),d}});kb.mixin({mousedOverSeg:null,isDraggingSeg:!1,isResizingSeg:!1,isDraggingExternal:!1,segs:null,renderEvents:function(a){var b,c=[],d=[];for(b=0;b *",function(c){var e=a(this).data("fc-seg");return!e||b.isDraggingSeg||b.isResizingSeg?void 0:d.call(this,e,c)})})},triggerSegMouseover:function(a,b){this.mousedOverSeg||(this.mousedOverSeg=a,this.view.trigger("eventMouseover",a.el[0],a.event,b))},triggerSegMouseout:function(a,b){b=b||{},this.mousedOverSeg&&(a=a||this.mousedOverSeg,this.mousedOverSeg=null,this.view.trigger("eventMouseout",a.el[0],a.event,b))},segDragMousedown:function(a,b){var c,d=this,e=this.view,f=e.calendar,i=a.el,j=a.event,k=new jb(a.el,{parentEl:e.el,opacity:e.opt("dragOpacity"),revertDuration:e.opt("dragRevertDuration"),zIndex:2}),l=new ib(e,{distance:5,scroll:e.opt("dragScroll"),subjectEl:i,subjectCenter:!0,listenStart:function(a){k.hide(),k.start(a)},dragStart:function(b){d.triggerSegMouseout(a,b),d.segDragStart(a,b),e.hideEvent(j)},hitOver:function(b,h,i){a.hit&&(i=a.hit),c=d.computeEventDrop(i.component.getHitSpan(i),b.component.getHitSpan(b),j),c&&!f.isEventSpanAllowed(d.eventToSpan(c),j)&&(g(),c=null),c&&e.renderDrag(c,a)?k.hide():k.show(),h&&(c=null)},hitOut:function(){e.unrenderDrag(),k.show(),c=null},hitDone:function(){h()},dragStop:function(b){k.stop(!c,function(){e.unrenderDrag(),e.showEvent(j),d.segDragStop(a,b),c&&e.reportEventDrop(j,c,this.largeUnit,i,b)})},listenStop:function(){k.stop()}});l.mousedown(b)},segDragStart:function(a,b){this.isDraggingSeg=!0,this.view.trigger("eventDragStart",a.el[0],a.event,b,{})},segDragStop:function(a,b){this.isDraggingSeg=!1,this.view.trigger("eventDragStop",a.el[0],a.event,b,{})},computeEventDrop:function(a,b,c){var d,e,f=this.view.calendar,g=a.start,h=b.start;return g.hasTime()===h.hasTime()?(d=this.diffDates(h,g),c.allDay&&N(d)?(e={start:c.start.clone(),end:f.getEventEnd(c),allDay:!1},f.normalizeEventTimes(e)):e={start:c.start.clone(),end:c.end?c.end.clone():null,allDay:c.allDay},e.start.add(d),e.end&&e.end.add(d)):e={start:h.clone(),end:null,allDay:!h.hasTime()},e},applyDragOpacity:function(a){var b=this.view.opt("dragOpacity");null!=b&&a.each(function(a,c){c.style.opacity=b})},externalDragStart:function(b,c){var d,e,f=this.view;f.opt("droppable")&&(d=a((c?c.item:null)||b.target),e=f.opt("dropAccept"),(a.isFunction(e)?e.call(d[0],d):d.is(e))&&(this.isDraggingExternal||this.listenToExternalDrag(d,b,c)))},listenToExternalDrag:function(a,b,c){var d,e=this,f=this.view.calendar,i=Ba(a),j=new ib(this,{listenStart:function(){e.isDraggingExternal=!0},hitOver:function(a){d=e.computeExternalDrop(a.component.getHitSpan(a),i),d&&!f.isExternalSpanAllowed(e.eventToSpan(d),d,i.eventProps)&&(g(),d=null),d&&e.renderDrag(d)},hitOut:function(){d=null},hitDone:function(){h(),e.unrenderDrag()},dragStop:function(){d&&e.view.reportExternalDrop(i,d,a,b,c)},listenStop:function(){e.isDraggingExternal=!1}});j.startDrag(b)},computeExternalDrop:function(a,b){var c=this.view.calendar,d={start:c.applyTimezone(a.start),end:null};return b.startTime&&!d.start.hasTime()&&d.start.time(b.startTime),b.duration&&(d.end=d.start.clone().add(b.duration)),d},renderDrag:function(a,b){},unrenderDrag:function(){},segResizeMousedown:function(a,b,c){var d,e=this,f=this.view,i=f.calendar,j=a.el,k=a.event,l=i.getEventEnd(k),m=new ib(this,{distance:5,scroll:f.opt("dragScroll"),subjectEl:j,dragStart:function(b){e.triggerSegMouseout(a,b),e.segResizeStart(a,b)},hitOver:function(b,h,j){var m=e.getHitSpan(j),n=e.getHitSpan(b);d=c?e.computeEventStartResize(m,n,k):e.computeEventEndResize(m,n,k),d&&(i.isEventSpanAllowed(e.eventToSpan(d),k)?d.start.isSame(k.start)&&d.end.isSame(l)&&(d=null):(g(),d=null)),d&&(f.hideEvent(k),e.renderEventResize(d,a))},hitOut:function(){d=null},hitDone:function(){e.unrenderEventResize(),f.showEvent(k),h()},dragStop:function(b){e.segResizeStop(a,b),d&&f.reportEventResize(k,d,this.largeUnit,j,b)}});m.mousedown(b)},segResizeStart:function(a,b){this.isResizingSeg=!0,this.view.trigger("eventResizeStart",a.el[0],a.event,b,{})},segResizeStop:function(a,b){this.isResizingSeg=!1,this.view.trigger("eventResizeStop",a.el[0],a.event,b,{})},computeEventStartResize:function(a,b,c){return this.computeEventResize("start",a,b,c)},computeEventEndResize:function(a,b,c){return this.computeEventResize("end",a,b,c)},computeEventResize:function(a,b,c,d){var e,f,g=this.view.calendar,h=this.diffDates(c[a],b[a]);return e={start:d.start.clone(),end:g.getEventEnd(d),allDay:d.allDay},e.allDay&&N(h)&&(e.allDay=!1,g.normalizeEventTimes(e)),e[a].add(h),e.start.isBefore(e.end)||(f=this.minResizeDuration||(d.allDay?g.defaultAllDayEventDuration:g.defaultTimedEventDuration),"start"==a?e.start=e.end.clone().subtract(f):e.end=e.start.clone().add(f)),e},renderEventResize:function(a,b){},unrenderEventResize:function(){},getEventTimeText:function(a,b,c){return null==b&&(b=this.eventTimeFormat),null==c&&(c=this.displayEventEnd),this.displayEventTime&&a.start.hasTime()?c&&a.end?this.view.formatRange(a,b):a.start.format(b):""},getSegClasses:function(a,b,c){var d=a.event,e=["fc-event",a.isStart?"fc-start":"fc-not-start",a.isEnd?"fc-end":"fc-not-end"].concat(d.className,d.source?d.source.className:[]);return b&&e.push("fc-draggable"),c&&e.push("fc-resizable"),e},getSegSkinCss:function(a){var b=a.event,c=this.view,d=b.source||{},e=b.color,f=d.color,g=c.opt("eventColor");return{"background-color":b.backgroundColor||e||d.backgroundColor||f||c.opt("eventBackgroundColor")||g,"border-color":b.borderColor||e||d.borderColor||f||c.opt("eventBorderColor")||g,color:b.textColor||d.textColor||c.opt("eventTextColor")}},eventToSegs:function(a){return this.eventsToSegs([a])},eventToSpan:function(a){return this.eventToSpans(a)[0]},eventToSpans:function(a){var b=this.eventToRange(a);return this.eventRangeToSpans(b,a)},eventsToSegs:function(b,c){var d=this,e=za(b),f=[];return a.each(e,function(a,b){var e,g=[];for(e=0;eh&&g.push({start:h,end:c.start}),h=c.end;return f>h&&g.push({start:h,end:f}),g},sortEventSegs:function(a){a.sort(ca(this,"compareEventSegs"))},compareEventSegs:function(a,b){return a.eventStartMS-b.eventStartMS||b.eventDurationMS-a.eventDurationMS||b.event.allDay-a.event.allDay||B(a.event,b.event,this.view.eventOrderSpecs)}}),Pa.isBgEvent=wa,Pa.dataAttrPrefix="";var lb=Pa.DayTableMixin={breakOnWeeks:!1,dayDates:null,dayIndices:null,daysPerRow:null,rowCnt:null,colCnt:null,colHeadFormat:null,updateDayTable:function(){for(var a,b,c,d=this.view,e=this.start.clone(),f=-1,g=[],h=[];e.isBefore(this.end);)d.isHiddenDay(e)?g.push(f+.5):(f++,g.push(f),h.push(e.clone())),e.add(1,"days");if(this.breakOnWeeks){for(b=h[0].day(),a=1;ac?b[0]-1:c>=b.length?b[b.length-1]+1:b[c]},computeColHeadFormat:function(){return this.rowCnt>1||this.colCnt>10?"ddd":this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},sliceRangeByRow:function(a){var b,c,d,e,f,g=this.daysPerRow,h=this.view.computeDayRange(a),i=this.getDateDayIndex(h.start),j=this.getDateDayIndex(h.end.clone().subtract(1,"days")),k=[];for(b=0;b=e&&k.push({row:b,firstRowDayIndex:e-c,lastRowDayIndex:f-c,isStart:e===i,isEnd:f===j});return k},sliceRangeByDay:function(a){var b,c,d,e,f,g,h=this.daysPerRow,i=this.view.computeDayRange(a),j=this.getDateDayIndex(i.start),k=this.getDateDayIndex(i.end.clone().subtract(1,"days")),l=[];for(b=0;b=e;e++)f=Math.max(j,e),g=Math.min(k,e),f=Math.ceil(f),g=Math.floor(g),g>=f&&l.push({row:b,firstRowDayIndex:f-c,lastRowDayIndex:g-c,isStart:f===j,isEnd:g===k});return l},renderHeadHtml:function(){var a=this.view;return'"},renderHeadIntroHtml:function(){return this.renderIntroHtml()},renderHeadTrHtml:function(){return""+(this.isRTL?"":this.renderHeadIntroHtml())+this.renderHeadDateCellsHtml()+(this.isRTL?this.renderHeadIntroHtml():"")+"
"},renderHeadDateCellsHtml:function(){var a,b,c=[];for(a=0;a")),d=''+(Y(f.title||"")||" ")+"",''+(this.isRTL?d+" "+l:l+" "+d)+"
"+(h?'':"")+(i?'':"")+""},renderSegRow:function(b,c){function d(b){for(;b>g;)k=(r[e-1]||[])[g],k?k.attr("rowspan",parseInt(k.attr("rowspan")||1,10)+1):(k=a(" | "),h.append(k)),q[e][g]=k,r[e][g]=k,g++}var e,f,g,h,i,j,k,l=this.colCnt,m=this.buildSegLevels(c),n=Math.max(1,m.length),o=a(""),p=[],q=[],r=[];for(e=0;n>e;e++){if(f=m[e],g=0,h=a("
"),p.push([]),q.push([]),r.push([]),f)for(i=0;i').append(j.el),j.leftCol!=j.rightCol?k.attr("colspan",j.rightCol-j.leftCol+1):r[e][g]=k;g<=j.rightCol;)q[e][g]=k,p[e][g]=j,g++;h.append(k)}d(l),this.bookendCells(h),o.append(h)}return{row:b,tbodyEl:o,cellMatrix:q,segMatrix:p,segLevels:m,segs:c}},buildSegLevels:function(a){var b,c,d,e=[];for(this.sortEventSegs(a),b=0;b td > :first-child").each(c),e.position().top+f>h)return d;return!1},limitRow:function(b,c){function d(d){for(;d>w;)j=t.getCellSegs(b,w,c),j.length&&(m=f[c-1][w],s=t.renderMoreLink(b,w,j),r=a("").append(s),m.append(r),v.push(r[0])),w++}var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t=this,u=this.rowStructs[b],v=[],w=0;if(c&&c').attr("rowspan",n),j=l[p],s=this.renderMoreLink(b,i.leftCol+p,[i].concat(j)),r=a("").append(s),q.append(r),o.push(q[0]),v.push(q[0]);m.addClass("fc-limited").after(a(o)),g.push(m[0])}}d(this.colCnt),u.moreEls=a(v),u.limitedEls=a(g)}},unlimitRow:function(a){var b=this.rowStructs[a];b.moreEls&&(b.moreEls.remove(),b.moreEls=null),b.limitedEls&&(b.limitedEls.removeClass("fc-limited"),b.limitedEls=null)},renderMoreLink:function(b,c,d){var e=this,f=this.view;return a('').text(this.getMoreLinkText(d.length)).on("click",function(g){var h=f.opt("eventLimitClick"),i=e.getCellDate(b,c),j=a(this),k=e.getCellEl(b,c),l=e.getCellSegs(b,c),m=e.resliceDaySegs(l,i),n=e.resliceDaySegs(d,i);"function"==typeof h&&(h=f.trigger("eventLimitClick",null,{date:i,dayEl:k,moreEl:j,segs:m,hiddenSegs:n},g)),"popover"===h?e.showSegPopover(b,c,j,m):"string"==typeof h&&f.calendar.zoomTo(i,h)})},showSegPopover:function(a,b,c,d){var e,f,g=this,h=this.view,i=c.parent();e=1==this.rowCnt?h.el:this.rowEls.eq(a),f={className:"fc-more-popover",content:this.renderSegPopoverContent(a,b,d),parentEl:this.el,top:e.offset().top,autoHide:!0,viewportConstrain:h.opt("popoverViewportConstrain"),hide:function(){g.segPopover.removeElement(),g.segPopover=null,g.popoverSegs=null}},this.isRTL?f.right=i.offset().left+i.outerWidth()+1:f.left=i.offset().left-1,this.segPopover=new fb(f),this.segPopover.show()},renderSegPopoverContent:function(b,c,d){var e,f=this.view,g=f.opt("theme"),h=this.getCellDate(b,c).format(f.opt("dayPopoverFormat")),i=a(''),j=i.find(".fc-event-container");for(d=this.renderFgSegEls(d,!0),this.popoverSegs=d,e=0;e'+this.renderBgTrHtml(0)+'
'+this.renderSlatRowHtml()+"
"},renderSlatRowHtml:function(){for(var a,c,d,e=this.view,f=this.isRTL,g="",h=b.duration(+this.minTime);h"+(c?""+Y(a.format(this.labelFormat))+"":"")+"",g+='"+(f?"":d)+' | '+(f?d:"")+"
",h.add(this.slotDuration);return g},processOptions:function(){var c,d=this.view,e=d.opt("slotDuration"),f=d.opt("snapDuration");e=b.duration(e),f=f?b.duration(f):e,this.slotDuration=e,this.snapDuration=f,this.snapsPerSlot=e/f,this.minResizeDuration=f,this.minTime=b.duration(d.opt("minTime")),this.maxTime=b.duration(d.opt("maxTime")),c=d.opt("slotLabelFormat"),a.isArray(c)&&(c=c[c.length-1]),this.labelFormat=c||d.opt("axisFormat")||d.opt("smallTimeFormat"),c=d.opt("slotLabelInterval"),this.labelInterval=c?b.duration(c):this.computeLabelInterval(e)},computeLabelInterval:function(a){var c,d,e;for(c=Db.length-1;c>=0;c--)if(d=b.duration(Db[c]),e=L(d,a),ba(e)&&e>1)return d;return b.duration(a)},computeEventTimeFormat:function(){return this.view.opt("noMeridiemTimeFormat")},computeDisplayEventEnd:function(){return!0},prepareHits:function(){this.colCoordCache.build(),this.slatCoordCache.build()},releaseHits:function(){this.colCoordCache.clear()},queryHit:function(a,b){var c=this.snapsPerSlot,d=this.colCoordCache,e=this.slatCoordCache,f=d.getHorizontalIndex(a),g=e.getVerticalIndex(b);if(null!=f&&null!=g){var h=e.getTopOffset(g),i=e.getHeight(g),j=(b-h)/i,k=Math.floor(j*c),l=g*c+k,m=h+k/c*i,n=h+(k+1)/c*i;return{col:f,snap:l,component:this,left:d.getLeftOffset(f),right:d.getRightOffset(f),top:m,bottom:n}}},getHitSpan:function(a){var b,c=this.getCellDate(0,a.col),d=this.computeSnapTime(a.snap);return c.time(d),b=c.clone().add(this.snapDuration),{start:c,end:b}},getHitEl:function(a){return this.colEls.eq(a.col)},rangeUpdated:function(){this.updateDayTable()},computeSnapTime:function(a){return b.duration(this.minTime+this.snapDuration*a)},spanToSegs:function(a){var b,c=this.sliceRangeByTimes(a);for(b=0;b').css("top",e).appendTo(this.colContainerEls.eq(d[c].col))[0]);d.length>0&&f.push(a('').css("top",e).appendTo(this.el.find(".fc-content-skeleton"))[0]),this.nowIndicatorEls=a(f)},unrenderNowIndicator:function(){this.nowIndicatorEls&&(this.nowIndicatorEls.remove(),this.nowIndicatorEls=null)},renderSelection:function(a){this.view.opt("selectHelper")?this.renderEventLocationHelper(a):this.renderHighlight(a)},unrenderSelection:function(){this.unrenderHelper(),this.unrenderHighlight()},renderHighlight:function(a){this.renderHighlightSegs(this.spanToSegs(a))},unrenderHighlight:function(){this.unrenderHighlightSegs()}});nb.mixin({colContainerEls:null,fgContainerEls:null,bgContainerEls:null,helperContainerEls:null,highlightContainerEls:null,businessContainerEls:null,fgSegs:null,bgSegs:null,helperSegs:null,highlightSegs:null,businessSegs:null,renderContentSkeleton:function(){var b,c,d="";for(b=0;b';c=a('"),this.colContainerEls=c.find(".fc-content-col"),this.helperContainerEls=c.find(".fc-helper-container"),this.fgContainerEls=c.find(".fc-event-container:not(.fc-helper-container)"),this.bgContainerEls=c.find(".fc-bgevent-container"),this.highlightContainerEls=c.find(".fc-highlight-container"),this.businessContainerEls=c.find(".fc-business-container"),this.bookendCells(c.find("tr")),this.el.append(c)},renderFgSegs:function(a){return a=this.renderFgSegsIntoContainers(a,this.fgContainerEls),this.fgSegs=a,a},unrenderFgSegs:function(){this.unrenderNamedSegs("fgSegs")},renderHelperSegs:function(a,b){var c,d,e;for(a=this.renderFgSegsIntoContainers(a,this.helperContainerEls),c=0;c'+(c?'
'+Y(c)+"
":"")+(g.title?'
'+Y(g.title)+"
":"")+'
'+(j?'':"")+""},updateSegVerticals:function(a){this.computeSegVerticals(a),this.assignSegVerticals(a)},computeSegVerticals:function(a){var b,c;for(b=0;b1?"ll":"LL"},formatRange:function(a,b,c){var d=a.end;return d.hasTime()||(d=d.clone().subtract(1)),ma(a.start,d,b,c,this.opt("isRTL"))},setElement:function(a){this.el=a,this.bindGlobalHandlers()},removeElement:function(){this.clear(),this.isSkeletonRendered&&(this.unrenderSkeleton(),this.isSkeletonRendered=!1),this.unbindGlobalHandlers(),this.el.remove()},display:function(b){var c=this,d=null;return this.displaying&&(d=this.queryScroll()),this.calendar.freezeContentHeight(),this.clear().then(function(){return c.displaying=a.when(c.displayView(b)).then(function(){c.forceScroll(c.computeInitialScroll(d)),c.calendar.unfreezeContentHeight(),c.triggerRender()})})},clear:function(){var b=this,c=this.displaying;return c?c.then(function(){return b.displaying=null,b.clearEvents(),b.clearView()}):a.when()},displayView:function(a){this.isSkeletonRendered||(this.renderSkeleton(),this.isSkeletonRendered=!0),a&&this.setDate(a),this.render&&this.render(),this.renderDates(),this.updateSize(),this.renderBusinessHours(),this.startNowIndicator()},clearView:function(){this.unselect(),this.stopNowIndicator(),this.triggerUnrender(),this.unrenderBusinessHours(),this.unrenderDates(),this.destroy&&this.destroy()},renderSkeleton:function(){},unrenderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},triggerRender:function(){this.trigger("viewRender",this,this,this.el)},triggerUnrender:function(){this.trigger("viewDestroy",this,this,this.el)},bindGlobalHandlers:function(){a(document).on("mousedown",this.documentMousedownProxy)},unbindGlobalHandlers:function(){a(document).off("mousedown",this.documentMousedownProxy)},initThemingProps:function(){var a=this.opt("theme")?"ui":"fc";this.widgetHeaderClass=a+"-widget-header",this.widgetContentClass=a+"-widget-content",this.highlightStateClass=a+"-state-highlight"},renderBusinessHours:function(){},unrenderBusinessHours:function(){},startNowIndicator:function(){var a,c,d,e=this;this.opt("nowIndicator")&&(a=this.getNowIndicatorUnit(),a&&(c=ca(this,"updateNowIndicator"),this.initialNowDate=this.calendar.getNow(),this.initialNowQueriedMs=+new Date,this.renderNowIndicator(this.initialNowDate),this.isNowIndicatorRendered=!0,d=this.initialNowDate.clone().startOf(a).add(1,a)-this.initialNowDate,this.nowIndicatorTimeoutID=setTimeout(function(){e.nowIndicatorTimeoutID=null,c(),d=+b.duration(1,a),d=Math.max(100,d),e.nowIndicatorIntervalID=setInterval(c,d)},d)))},updateNowIndicator:function(){this.isNowIndicatorRendered&&(this.unrenderNowIndicator(),this.renderNowIndicator(this.initialNowDate.clone().add(new Date-this.initialNowQueriedMs)))},stopNowIndicator:function(){this.isNowIndicatorRendered&&(this.nowIndicatorTimeoutID&&(clearTimeout(this.nowIndicatorTimeoutID),this.nowIndicatorTimeoutID=null),this.nowIndicatorIntervalID&&(clearTimeout(this.nowIndicatorIntervalID),this.nowIndicatorIntervalID=null),this.unrenderNowIndicator(),this.isNowIndicatorRendered=!1)},getNowIndicatorUnit:function(){},renderNowIndicator:function(a){},unrenderNowIndicator:function(){},updateSize:function(a){var b;a&&(b=this.queryScroll()),this.updateHeight(a),this.updateWidth(a),this.updateNowIndicator(),a&&this.setScroll(b)},updateWidth:function(a){},updateHeight:function(a){var b=this.calendar;this.setHeight(b.getSuggestedViewHeight(),b.isHeightAuto())},setHeight:function(a,b){},computeScrollerHeight:function(a){var b,c,d=this.scrollerEl;return b=this.el.add(d),b.css({position:"relative",left:-1}),c=this.el.outerHeight()-d.height(),b.css({position:"",left:""}),a-c},computeInitialScroll:function(a){return 0},queryScroll:function(){return this.scrollerEl?this.scrollerEl.scrollTop():void 0},setScroll:function(a){return this.scrollerEl?this.scrollerEl.scrollTop(a):void 0},forceScroll:function(a){var b=this;this.setScroll(a),setTimeout(function(){b.setScroll(a)},0)},displayEvents:function(a){var b=this.queryScroll();this.clearEvents(),this.renderEvents(a),this.isEventsRendered=!0,this.setScroll(b),this.triggerEventRender()},clearEvents:function(){var a;this.isEventsRendered&&(a=this.queryScroll(),this.triggerEventUnrender(),this.destroyEvents&&this.destroyEvents(),this.unrenderEvents(),this.setScroll(a),this.isEventsRendered=!1)},renderEvents:function(a){},unrenderEvents:function(){},triggerEventRender:function(){this.renderedEventSegEach(function(a){this.trigger("eventAfterRender",a.event,a.event,a.el)}),this.trigger("eventAfterAllRender")},triggerEventUnrender:function(){this.renderedEventSegEach(function(a){this.trigger("eventDestroy",a.event,a.event,a.el)})},resolveEventEl:function(b,c){var d=this.trigger("eventRender",b,b,c);return d===!1?c=null:d&&d!==!0&&(c=a(d)),c},showEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","")},a)},hideEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","hidden")},a)},renderedEventSegEach:function(a,b){var c,d=this.getEventSegs();for(c=0;cb;b++)(d[b]=-1!==a.inArray(b,c))||e++;if(!e)throw"invalid hiddenDays";this.isHiddenDayHash=d},isHiddenDay:function(a){return b.isMoment(a)&&(a=a.day()),this.isHiddenDayHash[a]},skipHiddenDays:function(a,b,c){var d=a.clone();for(b=b||1;this.isHiddenDayHash[(d.day()+(c?b:0)+7)%7];)d.add(b,"days");return d},computeDayRange:function(a){var b,c=a.start.clone().stripTime(),d=a.end,e=null;return d&&(e=d.clone().stripTime(),b=+d.time(),b&&b>=this.nextDayThreshold&&e.add(1,"days")),(!d||c>=e)&&(e=c.clone().add(1,"days")),{start:c,end:e}},isMultiDayEvent:function(a){var b=this.computeDayRange(a);return b.end.diff(b.start,"days")>1}}),pb=Pa.Calendar=ra.extend({dirDefaults:null,langDefaults:null,overrides:null,options:null,viewSpecCache:null,view:null,header:null,loadingLevel:0,constructor:Ja,initialize:function(){},initOptions:function(a){var b,e,f,g;a=d(a),b=a.lang,e=qb[b],e||(b=pb.defaults.lang,e=qb[b]||{}),f=X(a.isRTL,e.isRTL,pb.defaults.isRTL),g=f?pb.rtlDefaults:{},this.dirDefaults=g,this.langDefaults=e,this.overrides=a,this.options=c([pb.defaults,g,e,a]),Ka(this.options),this.viewSpecCache={}},getViewSpec:function(a){var b=this.viewSpecCache;return b[a]||(b[a]=this.buildViewSpec(a))},getUnitViewSpec:function(b){var c,d,e;if(-1!=a.inArray(b,Ua))for(c=this.header.getViewsWithButtons(),a.each(Pa.views,function(a){c.push(a)}),d=0;d1,this.weekNumbersVisible=this.opt("weekNumbers"),this.dayGrid.numbersVisible=this.dayNumbersVisible||this.weekNumbersVisible,this.el.addClass("fc-basic-view").html(this.renderSkeletonHtml()),this.renderHead(),this.scrollerEl=this.el.find(".fc-day-grid-container"),this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(this.hasRigidRows())},renderHead:function(){this.headContainerEl=this.el.find(".fc-head-container").html(this.dayGrid.renderHeadHtml()),this.headRowEl=this.headContainerEl.find(".fc-row")},unrenderDates:function(){this.dayGrid.unrenderDates(),this.dayGrid.removeElement()},renderBusinessHours:function(){this.dayGrid.renderBusinessHours()},renderSkeletonHtml:function(){return''},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var a=this.opt("eventLimit");return a&&"number"!=typeof a},updateWidth:function(){this.weekNumbersVisible&&(this.weekNumberWidth=k(this.el.find(".fc-week-number")))},setHeight:function(a,b){var c,d=this.opt("eventLimit");m(this.scrollerEl),f(this.headRowEl),this.dayGrid.removeSegPopover(),d&&"number"==typeof d&&this.dayGrid.limitRows(d),c=this.computeScrollerHeight(a),this.setGridHeight(c,b),d&&"number"!=typeof d&&this.dayGrid.limitRows(d),!b&&l(this.scrollerEl,c)&&(e(this.headRowEl,r(this.scrollerEl)),c=this.computeScrollerHeight(a),this.scrollerEl.height(c))},setGridHeight:function(a,b){b?j(this.dayGrid.rowEls):i(this.dayGrid.rowEls,a,!0)},prepareHits:function(){this.dayGrid.prepareHits()},releaseHits:function(){this.dayGrid.releaseHits()},queryHit:function(a,b){return this.dayGrid.queryHit(a,b)},getHitSpan:function(a){return this.dayGrid.getHitSpan(a)},getHitEl:function(a){return this.dayGrid.getHitEl(a)},renderEvents:function(a){this.dayGrid.renderEvents(a),this.updateHeight()},getEventSegs:function(){return this.dayGrid.getEventSegs()},unrenderEvents:function(){this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return this.dayGrid.renderDrag(a,b)},unrenderDrag:function(){this.dayGrid.unrenderDrag()},renderSelection:function(a){this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.dayGrid.unrenderSelection()}}),xb={renderHeadIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?'":""},renderNumberIntroHtml:function(a){var b=this.view;return b.weekNumbersVisible?'"+this.getCellDate(a,0).format("w")+" | ":""},renderBgIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?' | ":""},renderIntroHtml:function(){var a=this.view;return a.weekNumbersVisible?' | ":""}},yb=Pa.MonthView=wb.extend({computeRange:function(a){var b,c=wb.prototype.computeRange.call(this,a);return this.isFixedWeeks()&&(b=Math.ceil(c.end.diff(c.start,"weeks",!0)),c.end.add(6-b,"weeks")),c},setGridHeight:function(a,b){b=b||"variable"===this.opt("weekMode"),b&&(a*=this.rowCnt/6),i(this.dayGrid.rowEls,a,!b)},isFixedWeeks:function(){var a=this.opt("weekMode");return a?"fixed"===a:this.opt("fixedWeekCount")}});Qa.basic={"class":wb},Qa.basicDay={type:"basic",duration:{days:1}},Qa.basicWeek={type:"basic",duration:{weeks:1}},Qa.month={"class":yb,duration:{months:1},defaults:{fixedWeekCount:!0}};var zb=Pa.AgendaView=ob.extend({timeGridClass:nb,timeGrid:null,dayGridClass:mb,dayGrid:null,axisWidth:null,headContainerEl:null,noScrollRowEls:null,bottomRuleEl:null,bottomRuleHeight:null,initialize:function(){this.timeGrid=this.instantiateTimeGrid(),this.opt("allDaySlot")&&(this.dayGrid=this.instantiateDayGrid())},instantiateTimeGrid:function(){var a=this.timeGridClass.extend(Ab);return new a(this)},instantiateDayGrid:function(){var a=this.dayGridClass.extend(Bb);return new a(this)},setRange:function(a){ob.prototype.setRange.call(this,a),this.timeGrid.setRange(a),this.dayGrid&&this.dayGrid.setRange(a)},renderDates:function(){this.el.addClass("fc-agenda-view").html(this.renderSkeletonHtml()),this.renderHead(),this.scrollerEl=this.el.find(".fc-time-grid-container"),this.timeGrid.setElement(this.el.find(".fc-time-grid")),this.timeGrid.renderDates(),this.bottomRuleEl=a('').appendTo(this.timeGrid.el),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight()),this.noScrollRowEls=this.el.find(".fc-row:not(.fc-scroller *)")},renderHead:function(){this.headContainerEl=this.el.find(".fc-head-container").html(this.timeGrid.renderHeadHtml())},unrenderDates:function(){this.timeGrid.unrenderDates(),this.timeGrid.removeElement(),this.dayGrid&&(this.dayGrid.unrenderDates(),this.dayGrid.removeElement())},renderSkeletonHtml:function(){return''},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},renderBusinessHours:function(){this.timeGrid.renderBusinessHours(),this.dayGrid&&this.dayGrid.renderBusinessHours()},unrenderBusinessHours:function(){this.timeGrid.unrenderBusinessHours(),this.dayGrid&&this.dayGrid.unrenderBusinessHours()},getNowIndicatorUnit:function(){return this.timeGrid.getNowIndicatorUnit()},renderNowIndicator:function(a){this.timeGrid.renderNowIndicator(a)},unrenderNowIndicator:function(){this.timeGrid.unrenderNowIndicator()},updateSize:function(a){this.timeGrid.updateSize(a),ob.prototype.updateSize.call(this,a)},updateWidth:function(){this.axisWidth=k(this.el.find(".fc-axis"))},setHeight:function(a,b){var c,d;null===this.bottomRuleHeight&&(this.bottomRuleHeight=this.bottomRuleEl.outerHeight()),this.bottomRuleEl.hide(),this.scrollerEl.css("overflow",""),m(this.scrollerEl),f(this.noScrollRowEls),this.dayGrid&&(this.dayGrid.removeSegPopover(),c=this.opt("eventLimit"),c&&"number"!=typeof c&&(c=Cb),c&&this.dayGrid.limitRows(c)),b||(d=this.computeScrollerHeight(a),l(this.scrollerEl,d)?(e(this.noScrollRowEls,r(this.scrollerEl)),d=this.computeScrollerHeight(a),this.scrollerEl.height(d)):(this.scrollerEl.height(d).css("overflow","hidden"),this.bottomRuleEl.show()))},computeInitialScroll:function(){var a=b.duration(this.opt("scrollTime")),c=this.timeGrid.computeTimeTop(a);return c=Math.ceil(c),c&&c++,c},prepareHits:function(){this.timeGrid.prepareHits(),this.dayGrid&&this.dayGrid.prepareHits()},releaseHits:function(){this.timeGrid.releaseHits(),this.dayGrid&&this.dayGrid.releaseHits()},queryHit:function(a,b){var c=this.timeGrid.queryHit(a,b);return!c&&this.dayGrid&&(c=this.dayGrid.queryHit(a,b)),c},getHitSpan:function(a){return a.component.getHitSpan(a)},getHitEl:function(a){return a.component.getHitEl(a)},renderEvents:function(a){var b,c,d=[],e=[],f=[];for(c=0;c